@@ -22,9 +22,7 @@ import * as fs from 'node:fs';
2222import * as path from 'node:path' ;
2323import { chromium } from 'playwright' ;
2424import type { Browser , Page } from 'playwright' ;
25- import { spawn } from 'node:child_process' ;
26- import type { ChildProcess } from 'node:child_process' ;
27- import http from 'node:http' ;
25+ import { DEV_SERVER_URL , ensureDevServer , killDevServer } from './dev-server-utils' ;
2826
2927// ── Types ───────────────────────────────────────────────────
3028
@@ -83,11 +81,9 @@ interface ReplaySummary {
8381
8482// ── Constants ───────────────────────────────────────────────
8583
86- const DEV_SERVER_URL = 'http://localhost:3000' ;
8784const VIEWPORT = { width : 900 , height : 700 } ;
8885const SCENE_READY_TIMEOUT = 30_000 ;
8986const STATE_SETTLED_TIMEOUT = 10_000 ;
90- const DEV_SERVER_START_TIMEOUT = 30_000 ;
9187
9288// ── CLI Arg Parsing ─────────────────────────────────────────
9389
@@ -180,64 +176,6 @@ function loadTranscript(filePath: string): GameTranscript {
180176 return transcript ;
181177}
182178
183- // ── Dev Server Management ───────────────────────────────────
184-
185- /** Check if a URL is reachable with an HTTP GET. */
186- function isServerReady ( url : string ) : Promise < boolean > {
187- return new Promise ( ( resolve ) => {
188- const req = http . get ( url , ( res ) => {
189- res . resume ( ) ; // consume response body
190- resolve ( res . statusCode !== undefined && res . statusCode < 500 ) ;
191- } ) ;
192- req . on ( 'error' , ( ) => resolve ( false ) ) ;
193- req . setTimeout ( 2000 , ( ) => {
194- req . destroy ( ) ;
195- resolve ( false ) ;
196- } ) ;
197- } ) ;
198- }
199-
200- /** Start the dev server if not already running. Returns the child process (or null). */
201- async function ensureDevServer ( ) : Promise < ChildProcess | null > {
202- const ready = await isServerReady ( DEV_SERVER_URL ) ;
203- if ( ready ) {
204- console . log ( 'Dev server already running at' , DEV_SERVER_URL ) ;
205- return null ;
206- }
207-
208- console . log ( 'Starting dev server (npm run dev)...' ) ;
209- const child = spawn ( 'npm' , [ 'run' , 'dev' ] , {
210- stdio : [ 'ignore' , 'pipe' , 'pipe' ] ,
211- detached : false ,
212- } ) ;
213-
214- // Wait for the server to become ready
215- const start = Date . now ( ) ;
216- while ( Date . now ( ) - start < DEV_SERVER_START_TIMEOUT ) {
217- await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
218- const ok = await isServerReady ( DEV_SERVER_URL ) ;
219- if ( ok ) {
220- console . log ( 'Dev server is ready.' ) ;
221- return child ;
222- }
223- }
224-
225- // Timeout -- kill and exit
226- child . kill ( 'SIGTERM' ) ;
227- console . error (
228- `Error: Dev server did not become ready within ${ DEV_SERVER_START_TIMEOUT / 1000 } s` ,
229- ) ;
230- process . exit ( 1 ) ;
231- }
232-
233- /** Kill the dev server process if we started it. */
234- function killDevServer ( child : ChildProcess | null ) : void {
235- if ( child && ! child . killed ) {
236- child . kill ( 'SIGTERM' ) ;
237- console . log ( 'Dev server stopped.' ) ;
238- }
239- }
240-
241179// ── Playwright Automation ───────────────────────────────────
242180
243181/**
0 commit comments