everything-dev 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/api-contract.cjs +55 -8
  2. package/dist/api-contract.cjs.map +1 -1
  3. package/dist/api-contract.mjs +55 -8
  4. package/dist/api-contract.mjs.map +1 -1
  5. package/dist/app.cjs +26 -2
  6. package/dist/app.cjs.map +1 -1
  7. package/dist/app.mjs +27 -3
  8. package/dist/app.mjs.map +1 -1
  9. package/dist/cli/init.cjs +4 -4
  10. package/dist/cli/init.cjs.map +1 -1
  11. package/dist/cli/init.mjs +4 -4
  12. package/dist/cli/init.mjs.map +1 -1
  13. package/dist/cli/sync.cjs +4 -3
  14. package/dist/cli/sync.cjs.map +1 -1
  15. package/dist/cli/sync.mjs +4 -3
  16. package/dist/cli/sync.mjs.map +1 -1
  17. package/dist/cli.cjs +0 -1
  18. package/dist/cli.cjs.map +1 -1
  19. package/dist/cli.mjs +0 -1
  20. package/dist/cli.mjs.map +1 -1
  21. package/dist/components/streaming-view.cjs +0 -18
  22. package/dist/components/streaming-view.cjs.map +1 -1
  23. package/dist/components/streaming-view.mjs +0 -18
  24. package/dist/components/streaming-view.mjs.map +1 -1
  25. package/dist/config.cjs +21 -5
  26. package/dist/config.cjs.map +1 -1
  27. package/dist/config.d.cts +2 -1
  28. package/dist/config.d.cts.map +1 -1
  29. package/dist/config.d.mts +2 -1
  30. package/dist/config.d.mts.map +1 -1
  31. package/dist/config.mjs +21 -6
  32. package/dist/config.mjs.map +1 -1
  33. package/dist/contract.cjs +8 -1
  34. package/dist/contract.cjs.map +1 -1
  35. package/dist/contract.d.cts +44 -8
  36. package/dist/contract.d.cts.map +1 -1
  37. package/dist/contract.d.mts +44 -8
  38. package/dist/contract.d.mts.map +1 -1
  39. package/dist/contract.meta.cjs +1 -1
  40. package/dist/contract.meta.cjs.map +1 -1
  41. package/dist/contract.meta.d.cts +1 -1
  42. package/dist/contract.meta.d.mts +1 -1
  43. package/dist/contract.meta.mjs +1 -1
  44. package/dist/contract.meta.mjs.map +1 -1
  45. package/dist/contract.mjs +8 -1
  46. package/dist/contract.mjs.map +1 -1
  47. package/dist/dev-session.cjs +51 -66
  48. package/dist/dev-session.cjs.map +1 -1
  49. package/dist/dev-session.mjs +52 -67
  50. package/dist/dev-session.mjs.map +1 -1
  51. package/dist/fastkv.cjs +56 -0
  52. package/dist/fastkv.cjs.map +1 -1
  53. package/dist/fastkv.d.cts +45 -1
  54. package/dist/fastkv.d.cts.map +1 -1
  55. package/dist/fastkv.d.mts +45 -1
  56. package/dist/fastkv.d.mts.map +1 -1
  57. package/dist/fastkv.mjs +54 -1
  58. package/dist/fastkv.mjs.map +1 -1
  59. package/dist/host.cjs +1 -1
  60. package/dist/host.cjs.map +1 -1
  61. package/dist/host.mjs +1 -1
  62. package/dist/host.mjs.map +1 -1
  63. package/dist/index.cjs +4 -0
  64. package/dist/index.d.cts +4 -4
  65. package/dist/index.d.mts +4 -4
  66. package/dist/index.mjs +3 -3
  67. package/dist/near-cli.cjs +1 -1
  68. package/dist/near-cli.mjs +1 -1
  69. package/dist/orchestrator.cjs +55 -20
  70. package/dist/orchestrator.cjs.map +1 -1
  71. package/dist/orchestrator.d.cts +5 -4
  72. package/dist/orchestrator.d.cts.map +1 -1
  73. package/dist/orchestrator.d.mts +5 -4
  74. package/dist/orchestrator.d.mts.map +1 -1
  75. package/dist/orchestrator.mjs +55 -20
  76. package/dist/orchestrator.mjs.map +1 -1
  77. package/dist/plugin.cjs +135 -9
  78. package/dist/plugin.cjs.map +1 -1
  79. package/dist/plugin.d.cts +50 -9
  80. package/dist/plugin.d.cts.map +1 -1
  81. package/dist/plugin.d.mts +50 -9
  82. package/dist/plugin.d.mts.map +1 -1
  83. package/dist/plugin.mjs +137 -11
  84. package/dist/plugin.mjs.map +1 -1
  85. package/dist/types.cjs +15 -5
  86. package/dist/types.cjs.map +1 -1
  87. package/dist/types.d.cts +62 -11
  88. package/dist/types.d.cts.map +1 -1
  89. package/dist/types.d.mts +62 -11
  90. package/dist/types.d.mts.map +1 -1
  91. package/dist/types.mjs +15 -5
  92. package/dist/types.mjs.map +1 -1
  93. package/package.json +2 -2
  94. package/src/api-contract.ts +88 -9
  95. package/src/app.ts +55 -7
  96. package/src/cli/init.ts +6 -6
  97. package/src/cli/sync.ts +11 -4
  98. package/src/cli.ts +0 -1
  99. package/src/components/streaming-view.ts +0 -20
  100. package/src/config.ts +39 -23
  101. package/src/contract.meta.ts +4 -1
  102. package/src/contract.ts +7 -0
  103. package/src/dev-session.ts +85 -83
  104. package/src/fastkv.ts +95 -0
  105. package/src/host.ts +1 -1
  106. package/src/orchestrator.ts +61 -31
  107. package/src/plugin.ts +202 -5
  108. package/src/types.ts +38 -4
@@ -66,6 +66,26 @@ const processConfigBases = {
66
66
  }
67
67
  };
68
68
  function getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig) {
69
+ if (pkg === "auth") {
70
+ const authConfig = runtimeConfig?.auth;
71
+ if (!authConfig?.localPath || authConfig.source !== "local") return null;
72
+ const port = portOverride ?? authConfig.port ?? (authConfig.url ? require_config.parsePort(authConfig.url) : 3020);
73
+ return {
74
+ name: "auth",
75
+ command: "bun",
76
+ args: ["run", "dev"],
77
+ cwd: authConfig.localPath,
78
+ port,
79
+ readyPatterns: [
80
+ /ready in/i,
81
+ /compiled.*successfully/i,
82
+ /listening/i,
83
+ /started/i
84
+ ],
85
+ errorPatterns: [/error/i, /failed/i],
86
+ env
87
+ };
88
+ }
69
89
  if (pkg.startsWith("plugin:")) {
70
90
  const pluginId = pkg.slice(7);
71
91
  const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;
@@ -268,11 +288,14 @@ const spawnRemoteHost = (config, callbacks, runtimeConfig) => effect.Effect.gen(
268
288
  return {
269
289
  name: config.name,
270
290
  pid: process.pid,
271
- kill: async () => {
291
+ kill: effect.Effect.gen(function* () {
272
292
  callbacks.onLog(config.name, "Shutting down remote host...");
273
293
  restoreConsole();
274
- await serverHandle.shutdown();
275
- },
294
+ yield* effect.Effect.tryPromise({
295
+ try: () => serverHandle.shutdown(),
296
+ catch: () => {}
297
+ }).pipe(effect.Effect.ignore);
298
+ }),
276
299
  waitForReady: effect.Effect.succeed(void 0),
277
300
  waitForExit: effect.Effect.never
278
301
  };
@@ -315,7 +338,7 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => effect.E
315
338
  if (config.port > 0) {
316
339
  const readinessPath = config.name === "host" ? "/health" : config.name === "ui-ssr" ? "/" : "/remoteEntry.js";
317
340
  const url = `http://127.0.0.1:${config.port}${readinessPath}`;
318
- yield* effect.Effect.fork(effect.Effect.gen(function* () {
341
+ yield* effect.Effect.forkScoped(effect.Effect.gen(function* () {
319
342
  const deadline = Date.now() + 9e4;
320
343
  while (Date.now() < deadline) {
321
344
  const status = yield* effect.Ref.get(statusRef);
@@ -341,7 +364,7 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => effect.E
341
364
  startedAt: Date.now(),
342
365
  command: [config.command, ...config.args].join(" ")
343
366
  });
344
- yield* effect.Effect.fork(effect.Effect.promise(() => proc.exited).pipe(effect.Effect.andThen((code) => effect.Effect.gen(function* () {
367
+ yield* effect.Effect.forkScoped(effect.Effect.promise(() => proc.exited).pipe(effect.Effect.andThen((code) => effect.Effect.gen(function* () {
345
368
  if (registry && proc.pid) yield* registry.untrack(proc.pid).pipe(effect.Effect.ignore);
346
369
  if ((yield* effect.Ref.get(statusRef)) === "ready") return;
347
370
  callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);
@@ -362,14 +385,16 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => effect.E
362
385
  }
363
386
  });
364
387
  const decoder = new TextDecoder();
365
- const stdoutFiber = yield* effect.Effect.fork(effect.Effect.async((resume) => {
388
+ const stdoutFiber = yield* effect.Effect.forkScoped(effect.Effect.async((resume) => {
366
389
  if (!proc.stdout) {
367
390
  resume(effect.Effect.void);
368
391
  return;
369
392
  }
370
393
  const reader = proc.stdout.getReader();
371
394
  let buffer = "";
395
+ let active = true;
372
396
  const pump = () => reader.read().then(({ done, value }) => {
397
+ if (!active) return;
373
398
  if (done) {
374
399
  if (buffer) effect.Effect.runSync(handleLine(buffer, false));
375
400
  return;
@@ -380,16 +405,24 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => effect.E
380
405
  for (const line of lines) effect.Effect.runSync(handleLine(line, false));
381
406
  return pump();
382
407
  });
383
- pump().then(() => resume(effect.Effect.void));
408
+ pump().then(() => {
409
+ if (active) resume(effect.Effect.void);
410
+ });
411
+ return effect.Effect.sync(() => {
412
+ active = false;
413
+ reader.cancel();
414
+ });
384
415
  }));
385
- const stderrFiber = yield* effect.Effect.fork(effect.Effect.async((resume) => {
416
+ const stderrFiber = yield* effect.Effect.forkScoped(effect.Effect.async((resume) => {
386
417
  if (!proc.stderr) {
387
418
  resume(effect.Effect.void);
388
419
  return;
389
420
  }
390
421
  const reader = proc.stderr.getReader();
391
422
  let buffer = "";
423
+ let active = true;
392
424
  const pump = () => reader.read().then(({ done, value }) => {
425
+ if (!active) return;
393
426
  if (done) {
394
427
  if (buffer) effect.Effect.runSync(handleLine(buffer, true));
395
428
  return;
@@ -400,22 +433,24 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => effect.E
400
433
  for (const line of lines) effect.Effect.runSync(handleLine(line, true));
401
434
  return pump();
402
435
  });
403
- pump().then(() => resume(effect.Effect.void));
436
+ pump().then(() => {
437
+ if (active) resume(effect.Effect.void);
438
+ });
439
+ return effect.Effect.sync(() => {
440
+ active = false;
441
+ reader.cancel();
442
+ });
404
443
  }));
405
444
  return {
406
445
  name: config.name,
407
446
  pid: proc.pid,
408
- kill: async () => {
409
- const pid = proc.pid;
410
- if (pid) await effect.Effect.runPromise(killProcessTree(pid));
411
- else {
412
- proc.kill("SIGTERM");
413
- await new Promise((r) => setTimeout(r, 100));
414
- try {
415
- proc.kill("SIGKILL");
416
- } catch {}
417
- }
418
- },
447
+ kill: proc.pid ? killProcessTree(proc.pid) : effect.Effect.gen(function* () {
448
+ proc.kill("SIGTERM");
449
+ yield* effect.Effect.sleep("100 millis");
450
+ try {
451
+ proc.kill("SIGKILL");
452
+ } catch {}
453
+ }),
419
454
  waitForReady: effect.Deferred.await(readyDeferred),
420
455
  waitForExit: effect.Effect.gen(function* () {
421
456
  yield* effect.Fiber.joinAll([stdoutFiber, stderrFiber]);
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.cjs","names":["parsePort","getHostDevelopmentPort","Effect","getProjectRoot","Deferred","Ref","Fiber"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { createConnection } from \"node:net\";\nimport { Deferred, Effect, Fiber, Ref } from \"effect\";\nimport { getHostDevelopmentPort, getProjectRoot, parsePort } from \"./config\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport type { ProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig } from \"./types\";\n\nexport interface DevProcess {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n env?: Record<string, string>;\n port: number;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nexport interface ProcessCallbacks {\n onStatus: (name: string, status: ProcessStatus, message?: string) => void;\n onLog: (name: string, line: string, isError?: boolean) => void;\n}\n\nexport interface ProcessHandle {\n name: string;\n pid: number | undefined;\n kill: () => Promise<void>;\n waitForReady: Effect.Effect<void, Error>;\n waitForExit: Effect.Effect<unknown>;\n}\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\ninterface ProcessConfigBase {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nconst processConfigBases: Record<string, ProcessConfigBase> = {\n \"host-build\": {\n name: \"host-build\",\n command: \"bun\",\n args: [\"run\", \"build\"],\n cwd: \"host\",\n readyPatterns: [/built in/i, /compiled.*successfully/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n host: {\n name: \"host\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"host\",\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n ui: {\n name: \"ui\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"ui\",\n // Wait for the client build (mf) specifically, not just SSR.\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n },\n \"ui-ssr\": {\n name: \"ui-ssr\",\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n cwd: \"ui\",\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n },\n api: {\n name: \"api\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"api\",\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n },\n};\n\nexport function getProcessConfig(\n pkg: string,\n env?: Record<string, string>,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n): DevProcess | null {\n if (pkg.startsWith(\"plugin:\")) {\n const pluginId = pkg.slice(\"plugin:\".length);\n const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;\n const localPath = pluginConfig?.localPath;\n\n if (!localPath || pluginConfig?.source !== \"local\") return null;\n\n const port =\n portOverride ?? pluginConfig?.port ?? (pluginConfig?.url ? parsePort(pluginConfig.url) : 0);\n\n return {\n name: pkg,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: localPath,\n port,\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n env,\n };\n }\n\n const base = processConfigBases[pkg];\n if (!base) return null;\n\n let port: number;\n if (pkg === \"host\") {\n port =\n portOverride ??\n (runtimeConfig?.hostUrl\n ? parsePort(runtimeConfig.hostUrl)\n : bosConfig\n ? getHostDevelopmentPort(bosConfig.app.host.development)\n : 3000);\n } else if (pkg === \"ui\") {\n port =\n runtimeConfig?.ui.port ?? (runtimeConfig?.ui.url ? parsePort(runtimeConfig.ui.url) : 3002);\n } else if (pkg === \"ui-ssr\") {\n const uiPort = runtimeConfig?.ui.ssrUrl\n ? parsePort(runtimeConfig.ui.ssrUrl)\n : runtimeConfig?.ui.port\n ? runtimeConfig.ui.port + 1\n : 3003;\n port = uiPort;\n } else if (pkg === \"api\") {\n port =\n runtimeConfig?.api.port ?? (runtimeConfig?.api.url ? parsePort(runtimeConfig.api.url) : 3014);\n } else {\n port = 0;\n }\n\n const cwd =\n pkg === \"ui\"\n ? (runtimeConfig?.ui.localPath ?? base.cwd)\n : pkg === \"api\"\n ? (runtimeConfig?.api.localPath ?? base.cwd)\n : base.cwd;\n\n return { ...base, cwd, port, env };\n}\n\nconst stripAnsi = (input: string): string => {\n const ESC = String.fromCharCode(27);\n const BEL = String.fromCharCode(7);\n return input\n .replace(new RegExp(`${ESC}\\\\][^${BEL}]*${BEL}`, \"g\"), \"\")\n .replace(new RegExp(`${ESC}\\\\[[0-?]*[ -/]*[@-~]`, \"g\"), \"\");\n};\n\nconst probeHttpOk = async (url: string, timeoutMs = 400): Promise<boolean> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n};\n\nconst probeTcpOpen = async (port: number, timeoutMs = 250): Promise<boolean> => {\n return new Promise((resolve) => {\n const socket = createConnection({ host: \"127.0.0.1\", port });\n const timer = setTimeout(() => {\n socket.destroy();\n resolve(false);\n }, timeoutMs);\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n};\n\nconst detectStatus = (\n line: string,\n config: DevProcess,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n for (const pattern of config.errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n for (const pattern of config.readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n return null;\n};\n\nconst killProcessTree = (pid: number) =>\n Effect.gen(function* () {\n const killSignal = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(-pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const killDirect = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const isRunning = () =>\n Effect.try({\n try: () => {\n process.kill(pid, 0);\n return true;\n },\n catch: () => false,\n });\n\n yield* killSignal(\"SIGTERM\");\n yield* killDirect(\"SIGTERM\");\n\n yield* Effect.sleep(\"200 millis\");\n\n const stillRunning = yield* isRunning();\n if (stillRunning) {\n yield* killSignal(\"SIGKILL\");\n yield* killDirect(\"SIGKILL\");\n yield* Effect.sleep(\"100 millis\");\n }\n });\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n}\n\nconst patchConsole = (name: string, callbacks: ProcessCallbacks): (() => void) => {\n const originalLog = console.log;\n const originalError = console.error;\n const originalWarn = console.warn;\n const originalInfo = console.info;\n\n const formatArgs = (args: unknown[]): string => {\n return args\n .map((arg) => (typeof arg === \"object\" ? JSON.stringify(arg, null, 2) : String(arg)))\n .join(\" \");\n };\n\n console.log = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.error = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), true);\n };\n console.warn = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.info = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n\n return () => {\n console.log = originalLog;\n console.error = originalError;\n console.warn = originalWarn;\n console.info = originalInfo;\n };\n};\n\nexport const spawnRemoteHost = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig: RuntimeConfig,\n) =>\n Effect.gen(function* () {\n const remoteUrl = config.env?.HOST_REMOTE_URL;\n if (!remoteUrl) {\n return yield* Effect.fail(new Error(\"HOST_REMOTE_URL not provided for remote host\"));\n }\n\n if (config.env) {\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n }\n\n callbacks.onStatus(config.name, \"starting\");\n callbacks.onLog(config.name, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(config.name, callbacks);\n callbacks.onLog(config.name, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (e) => new Error(`Failed to load MF runtime: ${e}`),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (e) => new Error(`Failed to load MF core: ${e}`),\n });\n\n let mf = mfRuntime.getInstance();\n if (!mf) {\n mf = mfRuntime.createInstance({ name: \"cli-host\", remotes: [] });\n mfCore.setGlobalFederationInstance(mf);\n }\n patchManifestFetchForSsrPublicPath(mf as any);\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n const res = await fetch(manifestUrl);\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch {}\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(config.name, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n (mf as any).loadRemote(\"host/Server\") as Promise<{\n runServer: (input: ServerInput) => ServerHandle;\n }>,\n catch: (e) => new Error(`Failed to load host module: ${e}`),\n });\n\n if (!hostModule?.runServer) {\n return yield* Effect.fail(new Error(\"Host module does not export runServer function\"));\n }\n\n callbacks.onLog(config.name, \"Starting server...\");\n const serverHandle = hostModule.runServer({ config: runtimeConfig });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (e) => new Error(`Server failed to start: ${e}`),\n });\n\n callbacks.onStatus(config.name, \"ready\");\n\n return {\n name: config.name,\n pid: process.pid,\n kill: async () => {\n callbacks.onLog(config.name, \"Shutting down remote host...\");\n restoreConsole();\n await serverHandle.shutdown();\n },\n waitForReady: Effect.succeed(undefined),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const spawnDevProcess = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n let configDir: string;\n try {\n configDir = getProjectRoot();\n } catch {\n configDir = process.cwd();\n }\n const fullCwd = config.cwd.startsWith(\"/\") ? config.cwd : `${configDir}/${config.cwd}`;\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(config.name, \"starting\");\n\n const envVars: Record<string, string> = {\n ...(process.env as Record<string, string>),\n ...config.env,\n FORCE_COLOR: \"1\",\n ...(config.port > 0 ? { PORT: String(config.port) } : {}),\n };\n\n if (runtimeConfig && config.name === \"host\") {\n envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);\n }\n\n const proc = Bun.spawn({\n cmd: [config.command, ...config.args],\n cwd: fullCwd,\n env: envVars,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n callbacks.onStatus(config.name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n // Prefer probe-based readiness to avoid brittle log regexes.\n // This is best-effort and complements log detection.\n if (config.port > 0) {\n const readinessPath =\n config.name === \"host\" ? \"/health\" : config.name === \"ui-ssr\" ? \"/\" : \"/remoteEntry.js\";\n const url = `http://127.0.0.1:${config.port}${readinessPath}`;\n\n yield* Effect.fork(\n Effect.gen(function* () {\n const deadline = Date.now() + 90_000;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n const ok = url\n ? yield* Effect.tryPromise({\n try: () => probeHttpOk(url),\n catch: () => false,\n })\n : yield* Effect.tryPromise({\n try: () => probeTcpOpen(config.port),\n catch: () => false,\n });\n if (ok) {\n yield* markReady;\n return;\n }\n yield* Effect.sleep(\"200 millis\");\n }\n }),\n );\n }\n\n if (registry && proc.pid) {\n yield* registry.track({\n pid: proc.pid,\n name: config.name,\n port: config.port,\n startedAt: Date.now(),\n command: [config.command, ...config.args].join(\" \"),\n });\n }\n\n yield* Effect.fork(\n Effect.promise(() => proc.exited).pipe(\n Effect.andThen((code) =>\n Effect.gen(function* () {\n if (registry && proc.pid) {\n yield* registry.untrack(proc.pid).pipe(Effect.ignore);\n }\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(config.name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new Error(`Process exited before ready: ${config.name}`),\n ).pipe(Effect.ignore);\n }),\n ),\n ),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n callbacks.onLog(config.name, line, isStderr);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, config);\n if (detected) {\n yield* Ref.set(statusRef, detected.status);\n callbacks.onStatus(config.name, detected.status);\n if (detected.status === \"ready\" || detected.status === \"error\") {\n if (detected.status === \"ready\") {\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n } else {\n yield* Deferred.fail(readyDeferred, new Error(`Process failed: ${config.name}`)).pipe(\n Effect.ignore,\n );\n }\n }\n }\n });\n\n const decoder = new TextDecoder();\n\n const stdoutFiber = yield* Effect.fork(\n Effect.async<void>((resume) => {\n if (!proc.stdout) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stdout.getReader();\n let buffer = \"\";\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer) {\n Effect.runSync(handleLine(buffer, false));\n }\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, false));\n }\n return pump();\n });\n\n pump().then(() => resume(Effect.void));\n }),\n );\n\n const stderrFiber = yield* Effect.fork(\n Effect.async<void>((resume) => {\n if (!proc.stderr) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stderr.getReader();\n let buffer = \"\";\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer) {\n Effect.runSync(handleLine(buffer, true));\n }\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, true));\n }\n return pump();\n });\n\n pump().then(() => resume(Effect.void));\n }),\n );\n\n const handle: ProcessHandle = {\n name: config.name,\n pid: proc.pid,\n kill: async () => {\n const pid = proc.pid;\n if (pid) {\n await Effect.runPromise(killProcessTree(pid));\n } else {\n proc.kill(\"SIGTERM\");\n await new Promise((r) => setTimeout(r, 100));\n try {\n proc.kill(\"SIGKILL\");\n } catch {}\n }\n },\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.gen(function* () {\n yield* Fiber.joinAll([stdoutFiber, stderrFiber]);\n return yield* Effect.promise(() => proc.exited);\n }),\n };\n\n return handle;\n });\n\nexport const makeDevProcess = (\n pkg: string,\n env: Record<string, string> | undefined,\n callbacks: ProcessCallbacks,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n const config = getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig);\n if (!config) {\n return yield* Effect.fail(new Error(`Unknown package: ${pkg}`));\n }\n\n if (pkg === \"host\" && runtimeConfig) {\n if (env?.HOST_SOURCE === \"remote\") {\n return yield* spawnRemoteHost(config, callbacks, runtimeConfig);\n }\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n }\n\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.cjs","names":["parsePort","getHostDevelopmentPort","Effect","getProjectRoot","Deferred","Ref","Fiber"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { createConnection } from \"node:net\";\nimport { Deferred, Effect, Fiber, Ref } from \"effect\";\nimport { getHostDevelopmentPort, getProjectRoot, parsePort } from \"./config\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport type { ProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig } from \"./types\";\n\nexport interface DevProcess {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n env?: Record<string, string>;\n port: number;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nexport interface ProcessCallbacks {\n onStatus: (name: string, status: ProcessStatus, message?: string) => void;\n onLog: (name: string, line: string, isError?: boolean) => void;\n}\n\nexport interface ProcessHandle {\n name: string;\n pid: number | undefined;\n kill: Effect.Effect<void, unknown>;\n waitForReady: Effect.Effect<void, Error>;\n waitForExit: Effect.Effect<unknown>;\n}\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\ninterface ProcessConfigBase {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nconst processConfigBases: Record<string, ProcessConfigBase> = {\n \"host-build\": {\n name: \"host-build\",\n command: \"bun\",\n args: [\"run\", \"build\"],\n cwd: \"host\",\n readyPatterns: [/built in/i, /compiled.*successfully/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n host: {\n name: \"host\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"host\",\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n ui: {\n name: \"ui\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"ui\",\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n },\n \"ui-ssr\": {\n name: \"ui-ssr\",\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n cwd: \"ui\",\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n },\n api: {\n name: \"api\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"api\",\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n },\n};\n\nexport function getProcessConfig(\n pkg: string,\n env?: Record<string, string>,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n): DevProcess | null {\n if (pkg === \"auth\") {\n const authConfig = runtimeConfig?.auth;\n if (!authConfig?.localPath || authConfig.source !== \"local\") return null;\n\n const port =\n portOverride ?? authConfig.port ?? (authConfig.url ? parsePort(authConfig.url) : 3020);\n\n return {\n name: \"auth\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: authConfig.localPath,\n port,\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n env,\n };\n }\n\n if (pkg.startsWith(\"plugin:\")) {\n const pluginId = pkg.slice(\"plugin:\".length);\n const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;\n const localPath = pluginConfig?.localPath;\n\n if (!localPath || pluginConfig?.source !== \"local\") return null;\n\n const port =\n portOverride ?? pluginConfig?.port ?? (pluginConfig?.url ? parsePort(pluginConfig.url) : 0);\n\n return {\n name: pkg,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: localPath,\n port,\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n env,\n };\n }\n\n const base = processConfigBases[pkg];\n if (!base) return null;\n\n let port: number;\n if (pkg === \"host\") {\n port =\n portOverride ??\n (runtimeConfig?.hostUrl\n ? parsePort(runtimeConfig.hostUrl)\n : bosConfig\n ? getHostDevelopmentPort(bosConfig.app.host.development)\n : 3000);\n } else if (pkg === \"ui\") {\n port =\n runtimeConfig?.ui.port ?? (runtimeConfig?.ui.url ? parsePort(runtimeConfig.ui.url) : 3002);\n } else if (pkg === \"ui-ssr\") {\n const uiPort = runtimeConfig?.ui.ssrUrl\n ? parsePort(runtimeConfig.ui.ssrUrl)\n : runtimeConfig?.ui.port\n ? runtimeConfig.ui.port + 1\n : 3003;\n port = uiPort;\n } else if (pkg === \"api\") {\n port =\n runtimeConfig?.api.port ?? (runtimeConfig?.api.url ? parsePort(runtimeConfig.api.url) : 3014);\n } else {\n port = 0;\n }\n\n const cwd =\n pkg === \"ui\"\n ? (runtimeConfig?.ui.localPath ?? base.cwd)\n : pkg === \"api\"\n ? (runtimeConfig?.api.localPath ?? base.cwd)\n : base.cwd;\n\n return { ...base, cwd, port, env };\n}\n\nconst stripAnsi = (input: string): string => {\n const ESC = String.fromCharCode(27);\n const BEL = String.fromCharCode(7);\n return input\n .replace(new RegExp(`${ESC}\\\\][^${BEL}]*${BEL}`, \"g\"), \"\")\n .replace(new RegExp(`${ESC}\\\\[[0-?]*[ -/]*[@-~]`, \"g\"), \"\");\n};\n\nconst probeHttpOk = async (url: string, timeoutMs = 400): Promise<boolean> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n};\n\nconst probeTcpOpen = async (port: number, timeoutMs = 250): Promise<boolean> => {\n return new Promise((resolve) => {\n const socket = createConnection({ host: \"127.0.0.1\", port });\n const timer = setTimeout(() => {\n socket.destroy();\n resolve(false);\n }, timeoutMs);\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n};\n\nconst detectStatus = (\n line: string,\n config: DevProcess,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n for (const pattern of config.errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n for (const pattern of config.readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n return null;\n};\n\nconst killProcessTree = (pid: number) =>\n Effect.gen(function* () {\n const killSignal = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(-pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const killDirect = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const isRunning = () =>\n Effect.try({\n try: () => {\n process.kill(pid, 0);\n return true;\n },\n catch: () => false,\n });\n\n yield* killSignal(\"SIGTERM\");\n yield* killDirect(\"SIGTERM\");\n\n yield* Effect.sleep(\"200 millis\");\n\n const stillRunning = yield* isRunning();\n if (stillRunning) {\n yield* killSignal(\"SIGKILL\");\n yield* killDirect(\"SIGKILL\");\n yield* Effect.sleep(\"100 millis\");\n }\n });\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n}\n\nconst patchConsole = (name: string, callbacks: ProcessCallbacks): (() => void) => {\n const originalLog = console.log;\n const originalError = console.error;\n const originalWarn = console.warn;\n const originalInfo = console.info;\n\n const formatArgs = (args: unknown[]): string => {\n return args\n .map((arg) => (typeof arg === \"object\" ? JSON.stringify(arg, null, 2) : String(arg)))\n .join(\" \");\n };\n\n console.log = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.error = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), true);\n };\n console.warn = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.info = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n\n return () => {\n console.log = originalLog;\n console.error = originalError;\n console.warn = originalWarn;\n console.info = originalInfo;\n };\n};\n\nexport const spawnRemoteHost = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig: RuntimeConfig,\n) =>\n Effect.gen(function* () {\n const remoteUrl = config.env?.HOST_REMOTE_URL;\n if (!remoteUrl) {\n return yield* Effect.fail(new Error(\"HOST_REMOTE_URL not provided for remote host\"));\n }\n\n if (config.env) {\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n }\n\n callbacks.onStatus(config.name, \"starting\");\n callbacks.onLog(config.name, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(config.name, callbacks);\n callbacks.onLog(config.name, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (e) => new Error(`Failed to load MF runtime: ${e}`),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (e) => new Error(`Failed to load MF core: ${e}`),\n });\n\n let mf = mfRuntime.getInstance();\n if (!mf) {\n mf = mfRuntime.createInstance({ name: \"cli-host\", remotes: [] });\n mfCore.setGlobalFederationInstance(mf);\n }\n patchManifestFetchForSsrPublicPath(mf as any);\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n const res = await fetch(manifestUrl);\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch {}\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(config.name, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n (mf as any).loadRemote(\"host/Server\") as Promise<{\n runServer: (input: ServerInput) => ServerHandle;\n }>,\n catch: (e) => new Error(`Failed to load host module: ${e}`),\n });\n\n if (!hostModule?.runServer) {\n return yield* Effect.fail(new Error(\"Host module does not export runServer function\"));\n }\n\n callbacks.onLog(config.name, \"Starting server...\");\n const serverHandle = hostModule.runServer({ config: runtimeConfig });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (e) => new Error(`Server failed to start: ${e}`),\n });\n\n callbacks.onStatus(config.name, \"ready\");\n\n return {\n name: config.name,\n pid: process.pid,\n kill: Effect.gen(function* () {\n callbacks.onLog(config.name, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.succeed(undefined),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const spawnDevProcess = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n let configDir: string;\n try {\n configDir = getProjectRoot();\n } catch {\n configDir = process.cwd();\n }\n const fullCwd = config.cwd.startsWith(\"/\") ? config.cwd : `${configDir}/${config.cwd}`;\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(config.name, \"starting\");\n\n const envVars: Record<string, string> = {\n ...(process.env as Record<string, string>),\n ...config.env,\n FORCE_COLOR: \"1\",\n ...(config.port > 0 ? { PORT: String(config.port) } : {}),\n };\n\n if (runtimeConfig && config.name === \"host\") {\n envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);\n }\n\n const proc = Bun.spawn({\n cmd: [config.command, ...config.args],\n cwd: fullCwd,\n env: envVars,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n callbacks.onStatus(config.name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n if (config.port > 0) {\n const readinessPath =\n config.name === \"host\" ? \"/health\" : config.name === \"ui-ssr\" ? \"/\" : \"/remoteEntry.js\";\n const url = `http://127.0.0.1:${config.port}${readinessPath}`;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const deadline = Date.now() + 90_000;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n const ok = url\n ? yield* Effect.tryPromise({\n try: () => probeHttpOk(url),\n catch: () => false,\n })\n : yield* Effect.tryPromise({\n try: () => probeTcpOpen(config.port),\n catch: () => false,\n });\n if (ok) {\n yield* markReady;\n return;\n }\n yield* Effect.sleep(\"200 millis\");\n }\n }),\n );\n }\n\n if (registry && proc.pid) {\n yield* registry.track({\n pid: proc.pid,\n name: config.name,\n port: config.port,\n startedAt: Date.now(),\n command: [config.command, ...config.args].join(\" \"),\n });\n }\n\n yield* Effect.forkScoped(\n Effect.promise(() => proc.exited).pipe(\n Effect.andThen((code) =>\n Effect.gen(function* () {\n if (registry && proc.pid) {\n yield* registry.untrack(proc.pid).pipe(Effect.ignore);\n }\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(config.name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new Error(`Process exited before ready: ${config.name}`),\n ).pipe(Effect.ignore);\n }),\n ),\n ),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n callbacks.onLog(config.name, line, isStderr);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, config);\n if (detected) {\n yield* Ref.set(statusRef, detected.status);\n callbacks.onStatus(config.name, detected.status);\n if (detected.status === \"ready\" || detected.status === \"error\") {\n if (detected.status === \"ready\") {\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n } else {\n yield* Deferred.fail(readyDeferred, new Error(`Process failed: ${config.name}`)).pipe(\n Effect.ignore,\n );\n }\n }\n }\n });\n\n const decoder = new TextDecoder();\n\n const stdoutFiber = yield* Effect.forkScoped(\n Effect.async<void>((resume) => {\n if (!proc.stdout) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stdout.getReader();\n let buffer = \"\";\n let active = true;\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (!active) return;\n if (done) {\n if (buffer) Effect.runSync(handleLine(buffer, false));\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, false));\n }\n return pump();\n });\n\n pump().then(() => {\n if (active) resume(Effect.void);\n });\n\n return Effect.sync(() => {\n active = false;\n reader.cancel();\n });\n }),\n );\n\n const stderrFiber = yield* Effect.forkScoped(\n Effect.async<void>((resume) => {\n if (!proc.stderr) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stderr.getReader();\n let buffer = \"\";\n let active = true;\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (!active) return;\n if (done) {\n if (buffer) Effect.runSync(handleLine(buffer, true));\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, true));\n }\n return pump();\n });\n\n pump().then(() => {\n if (active) resume(Effect.void);\n });\n\n return Effect.sync(() => {\n active = false;\n reader.cancel();\n });\n }),\n );\n\n const handle: ProcessHandle = {\n name: config.name,\n pid: proc.pid,\n kill: proc.pid\n ? killProcessTree(proc.pid)\n : Effect.gen(function* () {\n proc.kill(\"SIGTERM\");\n yield* Effect.sleep(\"100 millis\");\n try {\n proc.kill(\"SIGKILL\");\n } catch {}\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.gen(function* () {\n yield* Fiber.joinAll([stdoutFiber, stderrFiber]);\n return yield* Effect.promise(() => proc.exited);\n }),\n };\n\n return handle;\n });\n\nexport const makeDevProcess = (\n pkg: string,\n env: Record<string, string> | undefined,\n callbacks: ProcessCallbacks,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n const config = getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig);\n if (!config) {\n return yield* Effect.fail(new Error(`Unknown package: ${pkg}`));\n }\n\n if (pkg === \"host\" && runtimeConfig) {\n if (env?.HOST_SOURCE === \"remote\") {\n return yield* spawnRemoteHost(config, callbacks, runtimeConfig);\n }\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n }\n\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n });\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { BosConfig, RuntimeConfig } from "./types.cjs";
2
2
  import { ProcessRegistry } from "./process-registry.cjs";
3
+ import * as _$effect_Scope0 from "effect/Scope";
3
4
  import { Effect } from "effect";
4
5
 
5
6
  //#region src/orchestrator.d.ts
@@ -20,7 +21,7 @@ interface ProcessCallbacks {
20
21
  interface ProcessHandle {
21
22
  name: string;
22
23
  pid: number | undefined;
23
- kill: () => Promise<void>;
24
+ kill: Effect.Effect<void, unknown>;
24
25
  waitForReady: Effect.Effect<void, Error>;
25
26
  waitForExit: Effect.Effect<unknown>;
26
27
  }
@@ -29,12 +30,12 @@ declare function getProcessConfig(pkg: string, env?: Record<string, string>, por
29
30
  declare const spawnRemoteHost: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig: RuntimeConfig) => Effect.Effect<{
30
31
  name: string;
31
32
  pid: number;
32
- kill: () => Promise<void>;
33
+ kill: Effect.Effect<void, never, never>;
33
34
  waitForReady: Effect.Effect<undefined, never, never>;
34
35
  waitForExit: Effect.Effect<never, never, never>;
35
36
  }, string | Error, never>;
36
- declare const spawnDevProcess: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, never, never>;
37
- declare const makeDevProcess: (pkg: string, env: Record<string, string> | undefined, callbacks: ProcessCallbacks, portOverride?: number, bosConfig?: BosConfig, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, string | Error, never>;
37
+ declare const spawnDevProcess: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, never, _$effect_Scope0.Scope>;
38
+ declare const makeDevProcess: (pkg: string, env: Record<string, string> | undefined, callbacks: ProcessCallbacks, portOverride?: number, bosConfig?: BosConfig, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, string | Error, _$effect_Scope0.Scope>;
38
39
  //#endregion
39
40
  export { DevProcess, ProcessCallbacks, ProcessHandle, ProcessStatus, getProcessConfig, makeDevProcess, spawnDevProcess, spawnRemoteHost };
40
41
  //# sourceMappingURL=orchestrator.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.cts","names":[],"sources":["../src/orchestrator.ts"],"mappings":";;;;;UAOiB,UAAA;EACf,IAAA;EACA,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,MAAA;EACN,IAAA;EACA,aAAA,EAAe,MAAA;EACf,aAAA,EAAe,MAAA;AAAA;AAAA,UAGA,gBAAA;EACf,QAAA,GAAW,IAAA,UAAc,MAAA,EAAQ,aAAA,EAAe,OAAA;EAChD,KAAA,GAAQ,IAAA,UAAc,IAAA,UAAc,OAAA;AAAA;AAAA,UAGrB,aAAA;EACf,IAAA;EACA,GAAA;EACA,IAAA,QAAY,OAAA;EACZ,YAAA,EAAc,MAAA,CAAO,MAAA,OAAa,KAAA;EAClC,WAAA,EAAa,MAAA,CAAO,MAAA;AAAA;AAAA,KAGV,aAAA;AAAA,iBAuDI,gBAAA,CACd,GAAA,UACA,GAAA,GAAM,MAAA,kBACN,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,GACf,UAAA;AAAA,cA0MU,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,EAAe,aAAA,KAAa,MAAA,CAAA,MAAA;;;;;;;cAqGjB,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA;AAAA,cA8Nf,cAAA,GACX,GAAA,UACA,GAAA,EAAK,MAAA,8BACL,SAAA,EAAW,gBAAA,EACX,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,WAAA,KAAA"}
1
+ {"version":3,"file":"orchestrator.d.cts","names":[],"sources":["../src/orchestrator.ts"],"mappings":";;;;;;UAOiB,UAAA;EACf,IAAA;EACA,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,MAAA;EACN,IAAA;EACA,aAAA,EAAe,MAAA;EACf,aAAA,EAAe,MAAA;AAAA;AAAA,UAGA,gBAAA;EACf,QAAA,GAAW,IAAA,UAAc,MAAA,EAAQ,aAAA,EAAe,OAAA;EAChD,KAAA,GAAQ,IAAA,UAAc,IAAA,UAAc,OAAA;AAAA;AAAA,UAGrB,aAAA;EACf,IAAA;EACA,GAAA;EACA,IAAA,EAAM,MAAA,CAAO,MAAA;EACb,YAAA,EAAc,MAAA,CAAO,MAAA,OAAa,KAAA;EAClC,WAAA,EAAa,MAAA,CAAO,MAAA;AAAA;AAAA,KAGV,aAAA;AAAA,iBAsDI,gBAAA,CACd,GAAA,UACA,GAAA,GAAM,MAAA,kBACN,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,GACf,UAAA;AAAA,cA6NU,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,EAAe,aAAA,KAAa,MAAA,CAAA,MAAA;;;;;;;cAwGjB,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,SAAA,eAAA,CAAA,KAAA;AAAA,cAuOf,cAAA,GACX,GAAA,UACA,GAAA,EAAK,MAAA,8BACL,SAAA,EAAW,gBAAA,EACX,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,WAAA,KAAA,EAAA,eAAA,CAAA,KAAA"}
@@ -1,6 +1,7 @@
1
1
  import { BosConfig, RuntimeConfig } from "./types.mjs";
2
2
  import { ProcessRegistry } from "./process-registry.mjs";
3
3
  import { Effect } from "effect";
4
+ import * as _$effect_Scope0 from "effect/Scope";
4
5
 
5
6
  //#region src/orchestrator.d.ts
6
7
  interface DevProcess {
@@ -20,7 +21,7 @@ interface ProcessCallbacks {
20
21
  interface ProcessHandle {
21
22
  name: string;
22
23
  pid: number | undefined;
23
- kill: () => Promise<void>;
24
+ kill: Effect.Effect<void, unknown>;
24
25
  waitForReady: Effect.Effect<void, Error>;
25
26
  waitForExit: Effect.Effect<unknown>;
26
27
  }
@@ -29,12 +30,12 @@ declare function getProcessConfig(pkg: string, env?: Record<string, string>, por
29
30
  declare const spawnRemoteHost: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig: RuntimeConfig) => Effect.Effect<{
30
31
  name: string;
31
32
  pid: number;
32
- kill: () => Promise<void>;
33
+ kill: Effect.Effect<void, never, never>;
33
34
  waitForReady: Effect.Effect<undefined, never, never>;
34
35
  waitForExit: Effect.Effect<never, never, never>;
35
36
  }, string | Error, never>;
36
- declare const spawnDevProcess: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, never, never>;
37
- declare const makeDevProcess: (pkg: string, env: Record<string, string> | undefined, callbacks: ProcessCallbacks, portOverride?: number, bosConfig?: BosConfig, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, string | Error, never>;
37
+ declare const spawnDevProcess: (config: DevProcess, callbacks: ProcessCallbacks, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, never, _$effect_Scope0.Scope>;
38
+ declare const makeDevProcess: (pkg: string, env: Record<string, string> | undefined, callbacks: ProcessCallbacks, portOverride?: number, bosConfig?: BosConfig, runtimeConfig?: RuntimeConfig, registry?: ProcessRegistry) => Effect.Effect<ProcessHandle, string | Error, _$effect_Scope0.Scope>;
38
39
  //#endregion
39
40
  export { DevProcess, ProcessCallbacks, ProcessHandle, ProcessStatus, getProcessConfig, makeDevProcess, spawnDevProcess, spawnRemoteHost };
40
41
  //# sourceMappingURL=orchestrator.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.mts","names":[],"sources":["../src/orchestrator.ts"],"mappings":";;;;;UAOiB,UAAA;EACf,IAAA;EACA,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,MAAA;EACN,IAAA;EACA,aAAA,EAAe,MAAA;EACf,aAAA,EAAe,MAAA;AAAA;AAAA,UAGA,gBAAA;EACf,QAAA,GAAW,IAAA,UAAc,MAAA,EAAQ,aAAA,EAAe,OAAA;EAChD,KAAA,GAAQ,IAAA,UAAc,IAAA,UAAc,OAAA;AAAA;AAAA,UAGrB,aAAA;EACf,IAAA;EACA,GAAA;EACA,IAAA,QAAY,OAAA;EACZ,YAAA,EAAc,MAAA,CAAO,MAAA,OAAa,KAAA;EAClC,WAAA,EAAa,MAAA,CAAO,MAAA;AAAA;AAAA,KAGV,aAAA;AAAA,iBAuDI,gBAAA,CACd,GAAA,UACA,GAAA,GAAM,MAAA,kBACN,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,GACf,UAAA;AAAA,cA0MU,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,EAAe,aAAA,KAAa,MAAA,CAAA,MAAA;;;;;;;cAqGjB,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA;AAAA,cA8Nf,cAAA,GACX,GAAA,UACA,GAAA,EAAK,MAAA,8BACL,SAAA,EAAW,gBAAA,EACX,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,WAAA,KAAA"}
1
+ {"version":3,"file":"orchestrator.d.mts","names":[],"sources":["../src/orchestrator.ts"],"mappings":";;;;;;UAOiB,UAAA;EACf,IAAA;EACA,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,MAAA;EACN,IAAA;EACA,aAAA,EAAe,MAAA;EACf,aAAA,EAAe,MAAA;AAAA;AAAA,UAGA,gBAAA;EACf,QAAA,GAAW,IAAA,UAAc,MAAA,EAAQ,aAAA,EAAe,OAAA;EAChD,KAAA,GAAQ,IAAA,UAAc,IAAA,UAAc,OAAA;AAAA;AAAA,UAGrB,aAAA;EACf,IAAA;EACA,GAAA;EACA,IAAA,EAAM,MAAA,CAAO,MAAA;EACb,YAAA,EAAc,MAAA,CAAO,MAAA,OAAa,KAAA;EAClC,WAAA,EAAa,MAAA,CAAO,MAAA;AAAA;AAAA,KAGV,aAAA;AAAA,iBAsDI,gBAAA,CACd,GAAA,UACA,GAAA,GAAM,MAAA,kBACN,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,GACf,UAAA;AAAA,cA6NU,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,EAAe,aAAA,KAAa,MAAA,CAAA,MAAA;;;;;;;cAwGjB,eAAA,GACX,MAAA,EAAQ,UAAA,EACR,SAAA,EAAW,gBAAA,EACX,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,SAAA,eAAA,CAAA,KAAA;AAAA,cAuOf,cAAA,GACX,GAAA,UACA,GAAA,EAAK,MAAA,8BACL,SAAA,EAAW,gBAAA,EACX,YAAA,WACA,SAAA,GAAY,SAAA,EACZ,aAAA,GAAgB,aAAA,EAChB,QAAA,GAAW,eAAA,KAAe,MAAA,CAAA,MAAA,CAAA,aAAA,WAAA,KAAA,EAAA,eAAA,CAAA,KAAA"}
@@ -64,6 +64,26 @@ const processConfigBases = {
64
64
  }
65
65
  };
66
66
  function getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig) {
67
+ if (pkg === "auth") {
68
+ const authConfig = runtimeConfig?.auth;
69
+ if (!authConfig?.localPath || authConfig.source !== "local") return null;
70
+ const port = portOverride ?? authConfig.port ?? (authConfig.url ? parsePort(authConfig.url) : 3020);
71
+ return {
72
+ name: "auth",
73
+ command: "bun",
74
+ args: ["run", "dev"],
75
+ cwd: authConfig.localPath,
76
+ port,
77
+ readyPatterns: [
78
+ /ready in/i,
79
+ /compiled.*successfully/i,
80
+ /listening/i,
81
+ /started/i
82
+ ],
83
+ errorPatterns: [/error/i, /failed/i],
84
+ env
85
+ };
86
+ }
67
87
  if (pkg.startsWith("plugin:")) {
68
88
  const pluginId = pkg.slice(7);
69
89
  const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;
@@ -266,11 +286,14 @@ const spawnRemoteHost = (config, callbacks, runtimeConfig) => Effect.gen(functio
266
286
  return {
267
287
  name: config.name,
268
288
  pid: process.pid,
269
- kill: async () => {
289
+ kill: Effect.gen(function* () {
270
290
  callbacks.onLog(config.name, "Shutting down remote host...");
271
291
  restoreConsole();
272
- await serverHandle.shutdown();
273
- },
292
+ yield* Effect.tryPromise({
293
+ try: () => serverHandle.shutdown(),
294
+ catch: () => {}
295
+ }).pipe(Effect.ignore);
296
+ }),
274
297
  waitForReady: Effect.succeed(void 0),
275
298
  waitForExit: Effect.never
276
299
  };
@@ -313,7 +336,7 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.g
313
336
  if (config.port > 0) {
314
337
  const readinessPath = config.name === "host" ? "/health" : config.name === "ui-ssr" ? "/" : "/remoteEntry.js";
315
338
  const url = `http://127.0.0.1:${config.port}${readinessPath}`;
316
- yield* Effect.fork(Effect.gen(function* () {
339
+ yield* Effect.forkScoped(Effect.gen(function* () {
317
340
  const deadline = Date.now() + 9e4;
318
341
  while (Date.now() < deadline) {
319
342
  const status = yield* Ref.get(statusRef);
@@ -339,7 +362,7 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.g
339
362
  startedAt: Date.now(),
340
363
  command: [config.command, ...config.args].join(" ")
341
364
  });
342
- yield* Effect.fork(Effect.promise(() => proc.exited).pipe(Effect.andThen((code) => Effect.gen(function* () {
365
+ yield* Effect.forkScoped(Effect.promise(() => proc.exited).pipe(Effect.andThen((code) => Effect.gen(function* () {
343
366
  if (registry && proc.pid) yield* registry.untrack(proc.pid).pipe(Effect.ignore);
344
367
  if ((yield* Ref.get(statusRef)) === "ready") return;
345
368
  callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);
@@ -360,14 +383,16 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.g
360
383
  }
361
384
  });
362
385
  const decoder = new TextDecoder();
363
- const stdoutFiber = yield* Effect.fork(Effect.async((resume) => {
386
+ const stdoutFiber = yield* Effect.forkScoped(Effect.async((resume) => {
364
387
  if (!proc.stdout) {
365
388
  resume(Effect.void);
366
389
  return;
367
390
  }
368
391
  const reader = proc.stdout.getReader();
369
392
  let buffer = "";
393
+ let active = true;
370
394
  const pump = () => reader.read().then(({ done, value }) => {
395
+ if (!active) return;
371
396
  if (done) {
372
397
  if (buffer) Effect.runSync(handleLine(buffer, false));
373
398
  return;
@@ -378,16 +403,24 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.g
378
403
  for (const line of lines) Effect.runSync(handleLine(line, false));
379
404
  return pump();
380
405
  });
381
- pump().then(() => resume(Effect.void));
406
+ pump().then(() => {
407
+ if (active) resume(Effect.void);
408
+ });
409
+ return Effect.sync(() => {
410
+ active = false;
411
+ reader.cancel();
412
+ });
382
413
  }));
383
- const stderrFiber = yield* Effect.fork(Effect.async((resume) => {
414
+ const stderrFiber = yield* Effect.forkScoped(Effect.async((resume) => {
384
415
  if (!proc.stderr) {
385
416
  resume(Effect.void);
386
417
  return;
387
418
  }
388
419
  const reader = proc.stderr.getReader();
389
420
  let buffer = "";
421
+ let active = true;
390
422
  const pump = () => reader.read().then(({ done, value }) => {
423
+ if (!active) return;
391
424
  if (done) {
392
425
  if (buffer) Effect.runSync(handleLine(buffer, true));
393
426
  return;
@@ -398,22 +431,24 @@ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.g
398
431
  for (const line of lines) Effect.runSync(handleLine(line, true));
399
432
  return pump();
400
433
  });
401
- pump().then(() => resume(Effect.void));
434
+ pump().then(() => {
435
+ if (active) resume(Effect.void);
436
+ });
437
+ return Effect.sync(() => {
438
+ active = false;
439
+ reader.cancel();
440
+ });
402
441
  }));
403
442
  return {
404
443
  name: config.name,
405
444
  pid: proc.pid,
406
- kill: async () => {
407
- const pid = proc.pid;
408
- if (pid) await Effect.runPromise(killProcessTree(pid));
409
- else {
410
- proc.kill("SIGTERM");
411
- await new Promise((r) => setTimeout(r, 100));
412
- try {
413
- proc.kill("SIGKILL");
414
- } catch {}
415
- }
416
- },
445
+ kill: proc.pid ? killProcessTree(proc.pid) : Effect.gen(function* () {
446
+ proc.kill("SIGTERM");
447
+ yield* Effect.sleep("100 millis");
448
+ try {
449
+ proc.kill("SIGKILL");
450
+ } catch {}
451
+ }),
417
452
  waitForReady: Deferred.await(readyDeferred),
418
453
  waitForExit: Effect.gen(function* () {
419
454
  yield* Fiber.joinAll([stdoutFiber, stderrFiber]);