Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
067f1a9c17 | |||
e7cf3bcb5e | |||
18cfa3e16a | |||
ea921766dc | |||
7e6d632afb | |||
25c61d7d7d | |||
d84c7a16a4 | |||
c5937da870 |
@ -8,10 +8,10 @@
|
|||||||
"projectType": "npm",
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "pushrocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "smartshell",
|
"gitrepo": "smartshell",
|
||||||
"description": "shell actions designed as promises",
|
"description": "shell actions designed as promises",
|
||||||
"npmPackagename": "@pushrocks/smartshell",
|
"npmPackagename": "@push.rocks/smartshell",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
package.json
24
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@pushrocks/smartshell",
|
"name": "@push.rocks/smartshell",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "3.0.0",
|
"version": "3.0.4",
|
||||||
"description": "shell actions designed as promises",
|
"description": "shell actions designed as promises",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
@ -26,19 +26,19 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/pushrocks/smartshell#README",
|
"homepage": "https://gitlab.com/pushrocks/smartshell#README",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tsbuild": "^2.1.66",
|
"@git.zone/tsbuild": "^2.1.66",
|
||||||
"@gitzone/tsrun": "^1.2.42",
|
"@git.zone/tsrun": "^1.2.44",
|
||||||
"@gitzone/tstest": "^1.0.74",
|
"@git.zone/tstest": "^1.0.77",
|
||||||
"@pushrocks/tapbundle": "^5.0.4",
|
"@push.rocks/tapbundle": "^5.0.8",
|
||||||
"@types/node": "^20.3.1"
|
"@types/node": "^20.11.28"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pushrocks/smartdelay": "^3.0.1",
|
"@push.rocks/smartdelay": "^3.0.1",
|
||||||
"@pushrocks/smartexit": "^1.0.20",
|
"@push.rocks/smartexit": "^1.0.20",
|
||||||
"@pushrocks/smartpromise": "^4.0.2",
|
"@push.rocks/smartpromise": "^4.0.2",
|
||||||
"@types/which": "^3.0.0",
|
"@types/which": "^3.0.3",
|
||||||
"tree-kill": "^1.2.2",
|
"tree-kill": "^1.2.2",
|
||||||
"which": "^3.0.1"
|
"which": "^4.0.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/**/*",
|
"ts/**/*",
|
||||||
|
2520
pnpm-lock.yaml
generated
2520
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
12
readme.md
12
readme.md
@ -1,8 +1,8 @@
|
|||||||
# @pushrocks/smartshell
|
# @push.rocks/smartshell
|
||||||
shell actions designed as promises
|
shell actions designed as promises
|
||||||
|
|
||||||
## Availabililty and Links
|
## Availabililty and Links
|
||||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartshell)
|
* [npmjs.org (npm package)](https://www.npmjs.com/package/@push.rocks/smartshell)
|
||||||
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartshell)
|
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartshell)
|
||||||
* [github.com (source mirror)](https://github.com/pushrocks/smartshell)
|
* [github.com (source mirror)](https://github.com/pushrocks/smartshell)
|
||||||
* [docs (typedoc)](https://pushrocks.gitlab.io/smartshell/)
|
* [docs (typedoc)](https://pushrocks.gitlab.io/smartshell/)
|
||||||
@ -13,14 +13,14 @@ Status Category | Status Badge
|
|||||||
-- | --
|
-- | --
|
||||||
GitLab Pipelines | [](https://lossless.cloud)
|
GitLab Pipelines | [](https://lossless.cloud)
|
||||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||||
npm | [](https://lossless.cloud)
|
npm | [](https://lossless.cloud)
|
||||||
Snyk | [](https://lossless.cloud)
|
Snyk | [](https://lossless.cloud)
|
||||||
TypeScript Support | [](https://lossless.cloud)
|
TypeScript Support | [](https://lossless.cloud)
|
||||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||||
Code Style | [](https://lossless.cloud)
|
Code Style | [](https://lossless.cloud)
|
||||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
12
test/test.ts
12
test/test.ts
@ -1,7 +1,7 @@
|
|||||||
import { expect, tap } from '@pushrocks/tapbundle';
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
|
|
||||||
import * as smartshell from '../ts/index.js';
|
import * as smartshell from '../ts/index.js';
|
||||||
import * as smartpromise from '@pushrocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
|
||||||
let testSmartshell: smartshell.Smartshell;
|
let testSmartshell: smartshell.Smartshell;
|
||||||
|
|
||||||
@ -15,12 +15,12 @@ tap.test('smartshell should create a Smartshell instance', async () => {
|
|||||||
|
|
||||||
tap.test('smartshell should run async', async () => {
|
tap.test('smartshell should run async', async () => {
|
||||||
let execResult = await testSmartshell.exec('npm -v');
|
let execResult = await testSmartshell.exec('npm -v');
|
||||||
// expect(execResult.stdout).toMatch(/[0-9\.]*/);
|
expect(execResult.stdout).toMatch(/[0-9\.]*/);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('smartshell should run async and silent', async () => {
|
tap.test('smartshell should run async and silent', async () => {
|
||||||
let execResult = await testSmartshell.execSilent('npm -v');
|
let execResult = await testSmartshell.execSilent('npm -v');
|
||||||
// expect(execResult.stdout).toMatch(/[0-9\.]*/);
|
expect(execResult.stdout).toMatch(/[0-9\.]*/);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('smartshell should stream a shell execution', async () => {
|
tap.test('smartshell should stream a shell execution', async () => {
|
||||||
@ -30,7 +30,7 @@ tap.test('smartshell should stream a shell execution', async () => {
|
|||||||
done.resolve(data);
|
done.resolve(data);
|
||||||
});
|
});
|
||||||
let data = await done.promise;
|
let data = await done.promise;
|
||||||
// expect(data).toMatch(/[0-9\.]*/);
|
expect(data).toMatch(/[0-9\.]*/);
|
||||||
await execStreamingResponse.finalPromise;
|
await execStreamingResponse.finalPromise;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ tap.test('should be able to find git', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should spawn an interactive cli', async () => {
|
tap.test('should spawn an interactive cli', async () => {
|
||||||
// await testSmartshell.execInteractive('echo "hi"');
|
await testSmartshell.execInteractive('echo "hi"');
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.start({
|
tap.start({
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @pushrocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@pushrocks/smartshell',
|
name: '@push.rocks/smartshell',
|
||||||
version: '3.0.0',
|
version: '3.0.4',
|
||||||
description: 'shell actions designed as promises'
|
description: 'shell actions designed as promises'
|
||||||
}
|
}
|
||||||
|
@ -30,43 +30,34 @@ export class Smartshell {
|
|||||||
* executes a given command async
|
* executes a given command async
|
||||||
*/
|
*/
|
||||||
private async _exec(options: {
|
private async _exec(options: {
|
||||||
commandString: string,
|
commandString: string;
|
||||||
silent?: boolean,
|
silent?: boolean;
|
||||||
strict?: boolean,
|
strict?: boolean;
|
||||||
streaming?: boolean,
|
streaming?: boolean;
|
||||||
interactive?: boolean
|
interactive?: boolean;
|
||||||
}): Promise<IExecResult | IExecResultStreaming | void> {
|
}): Promise<IExecResult | IExecResultStreaming | void> {
|
||||||
|
|
||||||
if (options.interactive) {
|
if (options.interactive) {
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
const shell = cp.spawn('sh', [], { stdio: 'pipe' });
|
|
||||||
this.smartexit.addProcess(shell);
|
|
||||||
|
|
||||||
const stdInStream = process.stdin.pipe(shell.stdin);
|
// Notice that stdio is set to 'inherit'
|
||||||
const stdOutStream = shell.stdout.pipe(process.stdout);
|
const shell = cp.spawn(options.commandString, {
|
||||||
|
stdio: 'inherit',
|
||||||
|
shell: true,
|
||||||
|
detached: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.smartexit.addProcess(shell);
|
||||||
|
|
||||||
shell.on('close', (code) => {
|
shell.on('close', (code) => {
|
||||||
console.log(`interactive shell terminated with code ${code}`);
|
console.log(`interactive shell terminated with code ${code}`);
|
||||||
stdInStream.removeAllListeners();
|
this.smartexit.removeProcess(shell);
|
||||||
stdInStream.uncork();
|
|
||||||
stdOutStream.removeAllListeners();
|
|
||||||
stdOutStream.unpipe();
|
|
||||||
shell.kill('SIGTERM');
|
|
||||||
process.stdin.pause();
|
|
||||||
done.resolve();
|
done.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
let commandString = options.commandString;
|
|
||||||
if (process.env.CI) {
|
|
||||||
commandString += ' && exit';
|
|
||||||
}
|
|
||||||
commandString += '\n';
|
|
||||||
|
|
||||||
shell.stdin.write(commandString);
|
|
||||||
await done.promise;
|
await done.promise;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -153,19 +144,30 @@ export class Smartshell {
|
|||||||
return (await this._exec({ commandString, silent: true, strict: true })) as IExecResult;
|
return (await this._exec({ commandString, silent: true, strict: true })) as IExecResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execStreaming(commandString: string, silent: boolean = false): Promise<IExecResultStreaming> {
|
public async execStreaming(
|
||||||
|
commandString: string,
|
||||||
|
silent: boolean = false
|
||||||
|
): Promise<IExecResultStreaming> {
|
||||||
return (await this._exec({ commandString, silent, streaming: true })) as IExecResultStreaming;
|
return (await this._exec({ commandString, silent, streaming: true })) as IExecResultStreaming;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execStreamingSilent(commandString: string): Promise<IExecResultStreaming> {
|
public async execStreamingSilent(commandString: string): Promise<IExecResultStreaming> {
|
||||||
return (await this._exec({ commandString, silent: true, streaming: true })) as IExecResultStreaming;
|
return (await this._exec({
|
||||||
|
commandString,
|
||||||
|
silent: true,
|
||||||
|
streaming: true,
|
||||||
|
})) as IExecResultStreaming;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execInteractive(commandString: string) {
|
public async execInteractive(commandString: string) {
|
||||||
await this._exec({ commandString, interactive: true });
|
await this._exec({ commandString, interactive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execAndWaitForLine(commandString: string, regexArg: RegExp, silentArg: boolean = false) {
|
public async execAndWaitForLine(
|
||||||
|
commandString: string,
|
||||||
|
regexArg: RegExp,
|
||||||
|
silentArg: boolean = false
|
||||||
|
) {
|
||||||
let done = plugins.smartpromise.defer();
|
let done = plugins.smartpromise.defer();
|
||||||
let execStreamingResult = await this.execStreaming(commandString, silentArg);
|
let execStreamingResult = await this.execStreaming(commandString, silentArg);
|
||||||
execStreamingResult.childProcess.stdout.on('data', (stdOutChunk: string) => {
|
execStreamingResult.childProcess.stdout.on('data', (stdOutChunk: string) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as smartdelay from '@pushrocks/smartdelay';
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
import * as smartexit from '@pushrocks/smartexit';
|
import * as smartexit from '@push.rocks/smartexit';
|
||||||
import * as smartpromise from '@pushrocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import which from 'which';
|
import which from 'which';
|
||||||
|
|
||||||
export { smartdelay, smartexit, smartpromise, which };
|
export { smartdelay, smartexit, smartpromise, which };
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"useDefineForClassFields": false,
|
"useDefineForClassFields": false,
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"module": "ES2022",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "nodenext",
|
"moduleResolution": "NodeNext",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true
|
||||||
}
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user