11import * as path from 'node:path' ;
22
3- import { awaitableTreekill , createLogger , fs , getPort , run , waitForIdleProcess , waitForServer } from '../scripts' ;
3+ import {
4+ awaitableTreekill ,
5+ createCiDiagnosticLogger ,
6+ createLogger ,
7+ fs ,
8+ getPort ,
9+ run ,
10+ startDetachedProcessLogMirror ,
11+ waitForIdleProcess ,
12+ waitForServer ,
13+ } from '../scripts' ;
414import type { ApplicationConfig } from './applicationConfig.js' ;
515import type { EnvironmentConfig } from './environment.js' ;
616
@@ -21,6 +31,9 @@ export const application = (
2131 const stderrFilePath = path . resolve ( appDirPath , `e2e.${ now } .err.log` ) ;
2232 let buildOutput = '' ;
2333 let serveOutput = '' ;
34+ const createPhaseLogger = ( phase : string ) => {
35+ return createCiDiagnosticLogger ( `${ appDirName } :: ${ phase } ` , logger . child ( { prefix : phase } ) . info ) ;
36+ } ;
2437
2538 const self = {
2639 name,
@@ -42,14 +55,18 @@ export const application = (
4255 setup : async ( opts ?: { strategy ?: 'ci' | 'i' | 'copy' ; force ?: boolean } ) => {
4356 const { force } = opts || { } ;
4457 const nodeModulesExist = await fs . pathExists ( path . resolve ( appDirPath , 'node_modules' ) ) ;
58+ const log = createPhaseLogger ( 'setup' ) ;
4559 if ( force || ! nodeModulesExist ) {
46- const log = logger . child ( { prefix : ' setup' } ) . info ;
60+ log ( `Running " ${ scripts . setup } " in ${ appDirPath } ` ) ;
4761 await run ( scripts . setup , { cwd : appDirPath , log } ) ;
4862 state . completedSetup = true ;
63+ log ( `Completed "${ scripts . setup } "` ) ;
64+ return ;
4965 }
66+ log ( `Skipping "${ scripts . setup } " because node_modules already exists in ${ appDirPath } ` ) ;
5067 } ,
5168 dev : async ( opts : { port ?: number ; manualStart ?: boolean ; detached ?: boolean ; serverUrl ?: string } = { } ) => {
52- const log = logger . child ( { prefix : 'dev' } ) . info ;
69+ const log = createPhaseLogger ( 'dev' ) ;
5370 const port = opts . port || ( await getPort ( ) ) ;
5471 const getServerUrl = ( ) => {
5572 if ( opts . serverUrl ) {
@@ -68,21 +85,45 @@ export const application = (
6885 return { port, serverUrl : runtimeServerUrl } ;
6986 }
7087
88+ log ( `Running "${ scripts . dev } " in ${ appDirPath } ` ) ;
89+ if ( opts . detached ) {
90+ log ( `Detached process logs will be written to ${ stdoutFilePath } and ${ stderrFilePath } ` ) ;
91+ }
7192 const proc = run ( scripts . dev , {
7293 cwd : appDirPath ,
7394 env : { PORT : port . toString ( ) } ,
7495 detached : opts . detached ,
7596 stdout : opts . detached ? fs . openSync ( stdoutFilePath , 'a' ) : undefined ,
7697 stderr : opts . detached ? fs . openSync ( stderrFilePath , 'a' ) : undefined ,
77- log : opts . detached ? undefined : log ,
98+ log,
99+ } ) ;
100+ void proc . on ( 'error' , error => {
101+ log ( `Process error: ${ error . message } ` ) ;
102+ } ) ;
103+ void proc . on ( 'exit' , ( code , signal ) => {
104+ log ( `Process exited with code ${ String ( code ) } ${ signal ? ` and signal ${ signal } ` : '' } ` ) ;
78105 } ) ;
106+ const detachedLogMirror = opts . detached
107+ ? startDetachedProcessLogMirror ( {
108+ stdoutFilePath,
109+ stderrFilePath,
110+ log,
111+ } )
112+ : undefined ;
79113
80114 const shouldExit = ( ) => ! ! proc . exitCode && proc . exitCode !== 0 ;
81- await waitForServer ( runtimeServerUrl , { log, maxAttempts : Infinity , shouldExit } ) ;
82- log ( `Server started at ${ runtimeServerUrl } , pid: ${ proc . pid } ` ) ;
83- cleanupFns . push ( ( ) => awaitableTreekill ( proc . pid , 'SIGKILL' ) ) ;
84- state . serverUrl = runtimeServerUrl ;
85- return { port, serverUrl : runtimeServerUrl , pid : proc . pid } ;
115+ try {
116+ await waitForServer ( runtimeServerUrl , { log, maxAttempts : Infinity , shouldExit } ) ;
117+ log ( `Server started at ${ runtimeServerUrl } , pid: ${ proc . pid } ` ) ;
118+ cleanupFns . push ( ( ) => awaitableTreekill ( proc . pid , 'SIGKILL' ) ) ;
119+ state . serverUrl = runtimeServerUrl ;
120+ return { port, serverUrl : runtimeServerUrl , pid : proc . pid } ;
121+ } catch ( error ) {
122+ log ( `Server failed to start at ${ runtimeServerUrl } ` ) ;
123+ throw error ;
124+ } finally {
125+ await detachedLogMirror ?. stop ( ) ;
126+ }
86127 } ,
87128 build : async ( ) => {
88129 const log = logger . child ( { prefix : 'build' } ) . info ;
0 commit comments