Skip to content

Commit

Permalink
feat: add flag to disable shell mode for nest start --watch
Browse files Browse the repository at this point in the history
When running on Linux/WSL, `nest start --watch` does not wait the app to shutdown on restart.
That leads to two instances of application running simultaneously, especially if it has async shutdown hooks.
That commit fixes that adding an option to disable shell mode when spawning child processes
so then app will completely shutdown first and only then started again.
Thanks @jleverenz for the investigation (nestjs#1614 (comment))
and solution idea

fixes nestjs/nest-cli/1614
  • Loading branch information
quallrum committed Feb 21, 2024
1 parent 99a4f0b commit 1734980
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
11 changes: 9 additions & 2 deletions actions/start.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,15 @@ export class StartAction extends BuildAction {
commandOptions,
defaultConfiguration.sourceRoot,
);
const noShellOption = commandOptions.find((option) => option.name === 'noShell')
const useShell = noShellOption ? !noShellOption.value : true;
const onSuccess = this.createOnSuccessHook(
entryFile,
sourceRoot,
debugFlag,
outDir,
binaryToRun,
useShell,
);

await this.runBuild(
Expand All @@ -103,6 +106,7 @@ export class StartAction extends BuildAction {
debugFlag: boolean | string | undefined,
outDirName: string,
binaryToRun: string,
useShell: boolean,
) {
let childProcessRef: any;
process.on(
Expand All @@ -120,6 +124,7 @@ export class StartAction extends BuildAction {
debugFlag,
outDirName,
binaryToRun,
useShell,
);
childProcessRef.on('exit', () => (childProcessRef = undefined));
});
Expand All @@ -133,6 +138,7 @@ export class StartAction extends BuildAction {
debugFlag,
outDirName,
binaryToRun,
useShell,
);
childProcessRef.on('exit', (code: number) => {
process.exitCode = code;
Expand All @@ -148,6 +154,7 @@ export class StartAction extends BuildAction {
debug: boolean | string | undefined,
outDirName: string,
binaryToRun: string,
useShell: boolean,
) {
let outputFilePath = join(outDirName, sourceRoot, entryFile);
if (!fs.existsSync(outputFilePath + '.js')) {
Expand Down Expand Up @@ -177,11 +184,11 @@ export class StartAction extends BuildAction {
}
const sourceMapsRegisterPath = this.getSourceMapSupportPkg();
if (sourceMapsRegisterPath !== undefined) {
processArgs.unshift(`-r "${sourceMapsRegisterPath}"`);
processArgs.unshift('-r', `"${sourceMapsRegisterPath}"`);
}
return spawn(binaryToRun, processArgs, {
stdio: 'inherit',
shell: true,
shell: useShell,
});
}

Expand Down
5 changes: 5 additions & 0 deletions commands/start.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class StartCommand extends AbstractCommand {
'--preserveWatchOutput',
'Use "preserveWatchOutput" option when using tsc watch mode.',
)
.option('--noShell', 'Spawn child processes without shell (see node\'s child_process.spawn() method docs)')
.description('Run Nest application.')
.action(async (app: string, command: Command) => {
const options: Input[] = [];
Expand Down Expand Up @@ -79,6 +80,10 @@ export class StartCommand extends AbstractCommand {
!!command.watch &&
!isWebpackEnabled,
});
options.push({
name: 'noShell',
value: !!command.noShell,
})

const availableBuilders = ['tsc', 'webpack', 'swc'];
if (command.builder && !availableBuilders.includes(command.builder)) {
Expand Down

0 comments on commit 1734980

Please sign in to comment.