diff --git a/test/test.ts b/test/test.ts index ee07b10..71b21ec 100644 --- a/test/test.ts +++ b/test/test.ts @@ -52,6 +52,10 @@ tap.test('should spawn an interactive cli', async () => { await testSmartshell.execInteractive('echo "hi"'); }); +tap.test('should spawn an interactive cli', async () => { + await testSmartshell.execInteractive('node'); +}); + tap.start({ throwOnError: true, }); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 8dac35e..1efb3ab 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@pushrocks/smartshell', - version: '3.0.1', + version: '3.0.2', description: 'shell actions designed as promises' } diff --git a/ts/smartshell.classes.smartshell.ts b/ts/smartshell.classes.smartshell.ts index 8892d45..fba9dda 100644 --- a/ts/smartshell.classes.smartshell.ts +++ b/ts/smartshell.classes.smartshell.ts @@ -30,44 +30,45 @@ export class Smartshell { * executes a given command async */ private async _exec(options: { - commandString: string, - silent?: boolean, - strict?: boolean, - streaming?: boolean, - interactive?: boolean + commandString: string; + silent?: boolean; + strict?: boolean; + streaming?: boolean; + interactive?: boolean; }): Promise { - if (options.interactive) { if (process.env.CI) { - return; + return; } - + const done = plugins.smartpromise.defer(); - const shell = cp.spawn('sh', [], { stdio: ['pipe', 'inherit', 'inherit'] }); - this.smartexit.addProcess(shell); - - shell.on('close', (code) => { - console.log(`interactive shell terminated with code ${code}`); - this.smartexit.removeProcess(shell); - done.resolve(); + + // Notice that stdio is set to 'inherit' + const shell = cp.spawn(options.commandString, { + stdio: 'inherit', + shell: true, + detached: true }); - - let commandString = options.commandString; - - shell.stdin.write(commandString + '\n exit \n'); - + + this.smartexit.addProcess(shell); + + shell.on('close', (code) => { + console.log(`interactive shell terminated with code ${code}`); + this.smartexit.removeProcess(shell); + done.resolve(); + }); + await done.promise; - + return; - } - + } const done = plugins.smartpromise.defer(); const childProcessEnded = plugins.smartpromise.defer(); let commandToExecute = options.commandString; commandToExecute = this.shellEnv.createEnvExecString(options.commandString); - + const spawnlogInstance = new ShellLog(); const execChildProcess = cp.spawn(commandToExecute, [], { shell: true, @@ -143,19 +144,30 @@ export class Smartshell { return (await this._exec({ commandString, silent: true, strict: true })) as IExecResult; } - public async execStreaming(commandString: string, silent: boolean = false): Promise { + public async execStreaming( + commandString: string, + silent: boolean = false + ): Promise { return (await this._exec({ commandString, silent, streaming: true })) as IExecResultStreaming; } public async execStreamingSilent(commandString: string): Promise { - 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) { 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 execStreamingResult = await this.execStreaming(commandString, silentArg); execStreamingResult.childProcess.stdout.on('data', (stdOutChunk: string) => {