From cf10efd22276b192b6053d42aabab81348dff1be Mon Sep 17 00:00:00 2001 From: Steve Hodgkiss Date: Sun, 29 Dec 2024 09:09:28 +1100 Subject: [PATCH] feat(cli): add watchStdin option to exit when stdin ends --- packages/vite/src/node/cli.ts | 4 ++++ packages/vite/src/node/http.ts | 4 ++++ packages/vite/src/node/preview.ts | 5 +++-- packages/vite/src/node/server/index.ts | 5 +++-- packages/vite/src/node/utils.ts | 10 +++++++--- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/vite/src/node/cli.ts b/packages/vite/src/node/cli.ts index b520b9b5144b46..58aa57db02a3eb 100644 --- a/packages/vite/src/node/cli.ts +++ b/packages/vite/src/node/cli.ts @@ -169,6 +169,7 @@ cli '--force', `[boolean] force the optimizer to ignore the cache and re-bundle`, ) + .option('--watchStdin', `[boolean] watch stdin and exit on EOF`) .action(async (root: string, options: ServerOptions & GlobalCLIOptions) => { filterDuplicateOptions(options) // output structure is preserved even after bundling so require() @@ -364,6 +365,7 @@ cli .option('--strictPort', `[boolean] exit if specified port is already in use`) .option('--open [path]', `[boolean | string] open browser on startup`) .option('--outDir ', `[string] output directory (default: dist)`) + .option('--watchStdin', `[boolean] watch stdin and exit on EOF`) .action( async ( root: string, @@ -373,6 +375,7 @@ cli open?: boolean | string strictPort?: boolean outDir?: string + watchStdin?: boolean } & GlobalCLIOptions, ) => { filterDuplicateOptions(options) @@ -392,6 +395,7 @@ cli strictPort: options.strictPort, host: options.host, open: options.open, + watchStdin: options.watchStdin, }, }) server.printUrls() diff --git a/packages/vite/src/node/http.ts b/packages/vite/src/node/http.ts index ec1bf5e645641d..89560162811c99 100644 --- a/packages/vite/src/node/http.ts +++ b/packages/vite/src/node/http.ts @@ -67,6 +67,10 @@ export interface CommonServerOptions { * Specify server response headers. */ headers?: HttpServerHeaders + /** + * Watch stdin and exit on EOF + */ + watchStdin?: boolean } /** diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index 2031538cc5c356..38448c1ca6bb5e 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -60,6 +60,7 @@ export function resolvePreviewOptions( proxy: preview?.proxy ?? server.proxy, cors: preview?.cors ?? server.cors, headers: preview?.headers ?? server.headers, + watchStdin: preview?.watchStdin ?? server.watchStdin, } } @@ -153,7 +154,7 @@ export async function preview( middlewares: app, httpServer, async close() { - teardownSIGTERMListener(closeServerAndExit) + teardownSIGTERMListener(config.preview.watchStdin, closeServerAndExit) await closeHttpServer() server.resolvedUrls = null }, @@ -179,7 +180,7 @@ export async function preview( } } - setupSIGTERMListener(closeServerAndExit) + setupSIGTERMListener(config.preview.watchStdin, closeServerAndExit) // apply server hooks from plugins const postHooks: ((() => void) | void)[] = [] diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 32a3371cef527b..207a8d270bed1e 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -675,7 +675,7 @@ export async function _createServer( }, async close() { if (!middlewareMode) { - teardownSIGTERMListener(closeServerAndExit) + teardownSIGTERMListener(config.server.watchStdin, closeServerAndExit) } await Promise.allSettled([ @@ -757,7 +757,7 @@ export async function _createServer( } if (!middlewareMode) { - setupSIGTERMListener(closeServerAndExit) + setupSIGTERMListener(config.server.watchStdin, closeServerAndExit) } const onHMRUpdate = async ( @@ -1036,6 +1036,7 @@ export const serverConfigDefaults = Object.freeze({ host: 'localhost', https: undefined, open: false, + watchStdin: false, proxy: undefined, cors: true, headers: {}, diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 233f96810da833..d42fe5d684853c 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -1530,19 +1530,23 @@ export function partialEncodeURIPath(uri: string): string { } export const setupSIGTERMListener = ( + watchStdin: boolean, callback: (signal?: 'SIGTERM', exitCode?: number) => Promise, ): void => { process.once('SIGTERM', callback) - if (process.env.CI !== 'true') { + if (watchStdin) { process.stdin.on('end', callback) + // resume stdin to allow the server to exit on EOF + process.stdin.resume() } } export const teardownSIGTERMListener = ( - callback: Parameters[0], + watchStdin: boolean, + callback: Parameters[1], ): void => { process.off('SIGTERM', callback) - if (process.env.CI !== 'true') { + if (watchStdin) { process.stdin.off('end', callback) } }