everything-dev 2.0.0-rc.6 → 2.0.0-rc.7

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 (116) hide show
  1. package/README.md +2 -2
  2. package/dist/build.cjs +1 -1
  3. package/dist/build.mjs +1 -1
  4. package/dist/bundle-cache.cjs +1 -1
  5. package/dist/bundle-cache.cjs.map +1 -1
  6. package/dist/bundle-cache.mjs +1 -1
  7. package/dist/bundle-cache.mjs.map +1 -1
  8. package/dist/cli.cjs +2 -2
  9. package/dist/cli.cjs.map +1 -1
  10. package/dist/cli.mjs +1 -1
  11. package/dist/cli.mjs.map +1 -1
  12. package/dist/commands/deploy.cjs +111 -1
  13. package/dist/commands/deploy.cjs.map +1 -1
  14. package/dist/commands/deploy.mjs +112 -2
  15. package/dist/commands/deploy.mjs.map +1 -1
  16. package/dist/commands/smoke.cjs +41 -0
  17. package/dist/commands/smoke.cjs.map +1 -0
  18. package/dist/commands/smoke.mjs +41 -0
  19. package/dist/commands/smoke.mjs.map +1 -0
  20. package/dist/commands/upgrade.cjs +2 -2
  21. package/dist/commands/upgrade.cjs.map +1 -1
  22. package/dist/commands/upgrade.mjs +1 -1
  23. package/dist/commands/upgrade.mjs.map +1 -1
  24. package/dist/contract.cjs +27 -1
  25. package/dist/contract.cjs.map +1 -1
  26. package/dist/contract.d.cts +65 -1
  27. package/dist/contract.d.mts +65 -1
  28. package/dist/contract.meta.cjs +13 -1
  29. package/dist/contract.meta.cjs.map +1 -1
  30. package/dist/contract.meta.d.cts +23 -1
  31. package/dist/contract.meta.d.mts +23 -1
  32. package/dist/contract.meta.mjs +13 -1
  33. package/dist/contract.meta.mjs.map +1 -1
  34. package/dist/contract.mjs +26 -2
  35. package/dist/contract.mjs.map +1 -1
  36. package/dist/dev-log-pipeline.cjs +6 -0
  37. package/dist/dev-log-pipeline.cjs.map +1 -1
  38. package/dist/dev-log-pipeline.mjs +6 -0
  39. package/dist/dev-log-pipeline.mjs.map +1 -1
  40. package/dist/dev-program.cjs +20 -3
  41. package/dist/dev-program.cjs.map +1 -1
  42. package/dist/dev-program.mjs +20 -4
  43. package/dist/dev-program.mjs.map +1 -1
  44. package/dist/dev-session.cjs +1 -0
  45. package/dist/dev-session.cjs.map +1 -1
  46. package/dist/dev-session.mjs +1 -0
  47. package/dist/dev-session.mjs.map +1 -1
  48. package/dist/fastkv.cjs +21 -3
  49. package/dist/fastkv.cjs.map +1 -1
  50. package/dist/fastkv.d.cts +14 -1
  51. package/dist/fastkv.d.mts +14 -1
  52. package/dist/fastkv.mjs +21 -5
  53. package/dist/fastkv.mjs.map +1 -1
  54. package/dist/{mf.cjs → federation.cjs} +6 -13
  55. package/dist/federation.cjs.map +1 -0
  56. package/dist/{mf.d.cts → federation.d.cts} +2 -2
  57. package/dist/{mf.d.mts → federation.d.mts} +2 -2
  58. package/dist/{mf.mjs → federation.mjs} +6 -13
  59. package/dist/federation.mjs.map +1 -0
  60. package/dist/http-client.cjs +70 -53
  61. package/dist/http-client.cjs.map +1 -1
  62. package/dist/http-client.mjs +70 -54
  63. package/dist/http-client.mjs.map +1 -1
  64. package/dist/image-deploy.cjs +9 -0
  65. package/dist/image-deploy.cjs.map +1 -1
  66. package/dist/image-deploy.mjs +9 -1
  67. package/dist/image-deploy.mjs.map +1 -1
  68. package/dist/index.cjs +4 -0
  69. package/dist/index.d.cts +3 -3
  70. package/dist/index.d.mts +3 -3
  71. package/dist/index.mjs +3 -3
  72. package/dist/orchestrator.cjs +39 -35
  73. package/dist/orchestrator.cjs.map +1 -1
  74. package/dist/orchestrator.mjs +39 -35
  75. package/dist/orchestrator.mjs.map +1 -1
  76. package/dist/plugin.cjs +2 -0
  77. package/dist/plugin.cjs.map +1 -1
  78. package/dist/plugin.d.cts +24 -0
  79. package/dist/plugin.d.mts +24 -0
  80. package/dist/plugin.mjs +2 -0
  81. package/dist/plugin.mjs.map +1 -1
  82. package/dist/process-registry.cjs +1 -1
  83. package/dist/process-registry.mjs +1 -1
  84. package/dist/publish.cjs +3 -3
  85. package/dist/publish.cjs.map +1 -1
  86. package/dist/publish.mjs +4 -4
  87. package/dist/publish.mjs.map +1 -1
  88. package/dist/resolver.cjs +293 -0
  89. package/dist/resolver.cjs.map +1 -0
  90. package/dist/resolver.d.cts +99 -0
  91. package/dist/resolver.d.mts +99 -0
  92. package/dist/resolver.mjs +284 -0
  93. package/dist/resolver.mjs.map +1 -0
  94. package/dist/smoke.cjs +262 -0
  95. package/dist/smoke.cjs.map +1 -0
  96. package/dist/smoke.mjs +260 -0
  97. package/dist/smoke.mjs.map +1 -0
  98. package/dist/version-manifest-resolve.cjs +3 -3
  99. package/dist/version-manifest-resolve.cjs.map +1 -1
  100. package/dist/version-manifest-resolve.mjs +1 -1
  101. package/dist/version-manifest-resolve.mjs.map +1 -1
  102. package/dist/workspace.cjs +1 -1
  103. package/dist/workspace.mjs +1 -1
  104. package/package.json +9 -9
  105. package/dist/bundle-fs-resolve.cjs +0 -235
  106. package/dist/bundle-fs-resolve.cjs.map +0 -1
  107. package/dist/bundle-fs-resolve.d.cts +0 -82
  108. package/dist/bundle-fs-resolve.d.mts +0 -82
  109. package/dist/bundle-fs-resolve.mjs +0 -228
  110. package/dist/bundle-fs-resolve.mjs.map +0 -1
  111. package/dist/bundle-path.cjs +0 -48
  112. package/dist/bundle-path.cjs.map +0 -1
  113. package/dist/bundle-path.mjs +0 -45
  114. package/dist/bundle-path.mjs.map +0 -1
  115. package/dist/mf.cjs.map +0 -1
  116. package/dist/mf.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.cjs","names":["Data","Schema","Effect","stripAnsi","DevRuntimeConfig","Deferred","Ref","DevGeneratedEnv","ShellEnv","spawn","Schedule","Readable","Stream","Option","ServiceDescriptorMap"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { Readable } from \"node:stream\";\nimport { Data, Deferred, Effect, Option, Ref, Schedule, Schema, Stream } from \"effect\";\nimport { stripAnsi } from \"./dev-log-pipeline\";\nimport { ShellEnv } from \"./env/project-env\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport {\n DevGeneratedEnv,\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst runFetch = (url: string, init?: RequestInit): Promise<Response> => fetch(url, init);\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\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>;\n waitForReady: Effect.Effect<void, OrchestratorError>;\n waitForExit: Effect.Effect<number, OrchestratorError>;\n}\n\nexport class OrchestratorError extends Data.TaggedError(\"OrchestratorError\")<{\n readonly operation: string;\n readonly detail: string;\n readonly cause?: unknown;\n}> {\n override get message() {\n return `${this.operation}: ${this.detail}`;\n }\n}\n\nconst omitUndefined = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map((item) => (item === undefined ? null : omitUndefined(item)));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, omitUndefined(item)]),\n );\n }\n return value;\n};\n\nexport const encodeRuntimeConfig = (runtimeConfig: unknown) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Json))(omitUndefined(runtimeConfig)).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestratorError({\n operation: \"serialize runtime config\",\n detail: cause.message,\n cause,\n }),\n ),\n );\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n uiPort?: number;\n}\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n try {\n const res = await runFetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n return res.ok;\n } catch {\n return false;\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst cleanExitSignals: Record<string, true> = { SIGTERM: true, SIGINT: true };\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nexport const detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n port?: number;\n env?: Record<string, string>;\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[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) {\n const cause = arg.cause;\n parts.push(\n `(cause: ${cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : (JSON.stringify(cause) ?? \"[Unserializable cause]\")})`,\n );\n }\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n if (arg === null) return \"null\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"bigint\" || typeof arg === \"boolean\")\n return `${arg}`;\n if (typeof arg === \"symbol\") return arg.description ?? \"\";\n if (typeof arg === \"undefined\") return \"undefined\";\n return JSON.stringify(arg, null, 2) ?? \"[Unserializable value]\";\n })\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), 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 class HostRemoteUrlMissing extends Data.TaggedError(\"HostRemoteUrlMissing\")<\n Record<never, never>\n> {\n override get message() {\n return \"remoteUrl not provided on host descriptor\";\n }\n}\n\nexport class HostModuleInvalid extends Data.TaggedError(\"HostModuleInvalid\")<Record<never, never>> {\n override get message() {\n return \"Host module does not export runServer function\";\n }\n}\n\nexport class LocalPathMissing extends Data.TaggedError(\"LocalPathMissing\")<{ key: string }> {\n get message() {\n return `No localPath for local service: ${this.key}`;\n }\n}\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* new HostRemoteUrlMissing();\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load module federation runtime\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load module federation core\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\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 manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n // The manifest IS the entry contract (ADR 0020 amendment: hashed\n // entrypoints, fixed-name `remoteEntry.js` retired — it 404s on the CDN).\n // A failed manifest fetch must fail loud with the URL and status: the old\n // silent fallback to remoteEntry.js turned any transient hiccup (a CDN\n // 403 challenge, a timeout) into a guaranteed loadRemote failure with no\n // named cause.\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n let res: Response;\n try {\n res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(10_000) });\n } catch (e) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${e instanceof Error ? e.message : String(e)}`,\n cause: e,\n });\n }\n if (!res.ok) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : \"\"}`,\n });\n }\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 throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — not a Module Federation manifest (missing metaData/exposes/shared)`,\n });\n }\n return manifestUrl;\n },\n catch: (cause) =>\n cause instanceof OrchestratorError\n ? cause\n : new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${String(cause)}`,\n }),\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(descriptor.key, `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: (cause) =>\n new OrchestratorError({\n operation: \"load host module\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n if (!hostModule?.runServer) {\n return yield* new HostModuleInvalid();\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const hostPort = runtimeConfig.host?.port;\n const hostEnv: Record<string, string> | undefined = hostPort\n ? { PORT: String(hostPort) }\n : undefined;\n const serverHandle = hostModule.runServer({\n config: runtimeConfig,\n port: hostPort,\n env: hostEnv,\n });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (cause) =>\n new OrchestratorError({\n operation: \"start server\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: undefined,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\n/**\n * Spawn env precedence, three tiers: values explicitly exported by the\n * caller (shell / CI / regression harness — captured by the bootstrap\n * program into the `ShellEnv` service before any `.env` loading) outrank the\n * generated infra env, which outranks `.env`-file values inherited through\n * `processEnv`. The service's resolved port is always authoritative.\n */\nexport function composeSpawnEnv(\n processEnv: Record<string, string>,\n generatedEnv: Record<string, string>,\n port: number,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n return {\n ...processEnv,\n ...mergeGeneratedOverFileEnv(generatedEnv, processEnv, shellEnv),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n}\n\n/**\n * Overlay the generated infra env (ports drift, so stale `.env` values must\n * lose) while keeping every explicitly exported key from `shellEnv` intact.\n * Keys absent from both are untouched.\n *\n * Exception (ADR 0012 / plan 038): the origin keys BASE_URL and CORS_ORIGIN\n * are always generated-owned — a wrapper that sourced a stale `.env` must not\n * win over the resolved host port, in the child env or on disk.\n */\nconst GENERATED_OWNED_KEYS = new Set([\"BASE_URL\", \"CORS_ORIGIN\"]);\n\nexport function mergeGeneratedOverFileEnv(\n generatedEnv: Record<string, string>,\n processEnv: Record<string, string>,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n const result: Record<string, string> = { ...processEnv };\n for (const [key, value] of Object.entries(generatedEnv)) {\n if (!GENERATED_OWNED_KEYS.has(key) && key in shellEnv) {\n result[key] = shellEnv[key]!;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* new LocalPathMissing({ key: descriptor.key });\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"pnpm\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const generatedEnv = yield* DevGeneratedEnv;\n const shellTier = yield* ShellEnv;\n // The descriptor's env joins the generated tier — folding it in before\n // composeSpawnEnv keeps the documented precedence (shell > generated >\n // .env-file); assigning after would let it outrank the shell tier (and\n // the generated-owned keys) silently.\n const envVars = composeSpawnEnv(\n process.env as Record<string, string>,\n { ...generatedEnv, ...descriptor.env },\n port,\n shellTier,\n );\n\n envVars.BOS_RUNTIME_CONFIG = yield* encodeRuntimeConfig(runtimeConfig);\n\n const cmd = spawn(command, args, {\n cwd: fullCwd,\n env: envVars,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n });\n\n let lastExit: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n const exitCode = Effect.callback<number, OrchestratorError>((resume) => {\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n lastExit = { code, signal };\n resume(Effect.succeed(code ?? (signal ? 1 : 0)));\n };\n const onError = (err: Error) => {\n callbacks.onLog(name, `Spawn failed: ${err.message}`, true);\n callbacks.onStatus(name, \"error\", `spawn failed: ${err.message}`);\n resume(\n Effect.fail(\n new OrchestratorError({\n operation: \"spawn process\",\n detail: err.message,\n cause: err,\n }),\n ),\n );\n };\n cmd.once(\"exit\", onExit);\n cmd.once(\"error\", onError);\n return Effect.sync(() => {\n cmd.off(\"exit\", onExit);\n cmd.off(\"error\", onError);\n });\n });\n\n const describeExit = (exitCodeValue: number): string => {\n if (lastExit?.code === null && lastExit.signal) return `signal: ${lastExit.signal}`;\n return `exit code: ${exitCodeValue}`;\n };\n const isCleanSignalExit = (): boolean =>\n lastExit?.code === null && lastExit.signal != null && lastExit.signal in cleanExitSignals;\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(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"wait for process readiness\", detail: message }),\n ).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n if (port <= 0) return false;\n const ok = yield* probeHttpOk(url);\n if (ok) yield* markReady;\n return ok;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.spaced(`${port > 0 ? LOCAL_PROBE_INTERVAL_MS : 500} millis`),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${LOCAL_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = cmd.pid ?? undefined;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCodeValue = yield* exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") {\n // Post-ready exits must stay visible — a silently dead child (OOM\n // kill included) used to leave the stack answering with nothing.\n // A SIGTERM/SIGINT-signalled exit is the polite-quit path, not a\n // crash, so it logs as a plain shutdown line.\n if (currentStatus === \"ready\") {\n const detail = describeExit(exitCodeValue);\n callbacks.onLog(name, `Process exited after ready (${detail})`, !isCleanSignalExit());\n if (!isCleanSignalExit()) {\n callbacks.onStatus(name, \"error\", `exited after ready (${detail})`);\n }\n yield* markError(`Process exited after ready: ${name}`);\n }\n return;\n }\n callbacks.onLog(\n name,\n `Process exited before ready (${describeExit(exitCodeValue)})`,\n !isCleanSignalExit(),\n );\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !cleanLine.startsWith(\"$\");\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else if (currentStatus !== \"error\") {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n const stdoutStream = cmd.stdout\n ? (Readable.toWeb(cmd.stdout) as unknown as ReadableStream<Uint8Array>)\n : null;\n const stderrStream = cmd.stderr\n ? (Readable.toWeb(cmd.stderr) as unknown as ReadableStream<Uint8Array>)\n : null;\n\n if (stdoutStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stdoutStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stdout\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n if (stderrStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stderrStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stderr\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const groupPid = pid;\n const groupSignal = (signal: NodeJS.Signals) =>\n Effect.try(() => {\n if (groupPid !== undefined) process.kill(-groupPid, signal);\n }).pipe(Effect.ignore);\n yield* groupSignal(\"SIGTERM\");\n const exited = yield* exitCode.pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(exited)) {\n yield* groupSignal(\"SIGKILL\");\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\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 yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({\n operation: \"probe remote process\",\n detail: `Remote ${pkg} unreachable`,\n }),\n ).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (ok) {\n yield* markReady;\n return true;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (fallbackOk) {\n yield* markReady;\n return true;\n }\n return false;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.min([\n Schedule.exponential(`${REMOTE_PROBE_BACKOFF_INITIAL_MS} millis`, 1.5),\n Schedule.spaced(`${REMOTE_PROBE_BACKOFF_MAX_MS} millis`),\n ]),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${REMOTE_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"stop remote process\", detail: \"Killed\" }),\n ).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks);\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n uiPort: descriptor?.uiPort,\n };\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.cjs","names":["Data","Schema","Effect","stripAnsi","DevRuntimeConfig","fetchRaw","registerRemote","loadRemoteModule","Deferred","Ref","DevGeneratedEnv","ShellEnv","spawn","Schedule","Readable","Stream","Option","ServiceDescriptorMap"],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { Readable } from \"node:stream\";\nimport { Data, Deferred, Effect, Option, Ref, Schedule, Schema, Stream } from \"effect\";\nimport { stripAnsi } from \"./dev-log-pipeline\";\nimport { ShellEnv } from \"./env/project-env\";\nimport { loadRemoteModule, registerRemote } from \"./federation\";\nimport { fetchRaw } from \"./http-client\";\nimport {\n DevGeneratedEnv,\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\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>;\n waitForReady: Effect.Effect<void, OrchestratorError>;\n waitForExit: Effect.Effect<number, OrchestratorError>;\n}\n\nexport class OrchestratorError extends Data.TaggedError(\"OrchestratorError\")<{\n readonly operation: string;\n readonly detail: string;\n readonly cause?: unknown;\n}> {\n override get message() {\n return `${this.operation}: ${this.detail}`;\n }\n}\n\nconst omitUndefined = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map((item) => (item === undefined ? null : omitUndefined(item)));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, omitUndefined(item)]),\n );\n }\n return value;\n};\n\nexport const encodeRuntimeConfig = (runtimeConfig: unknown) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Json))(omitUndefined(runtimeConfig)).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestratorError({\n operation: \"serialize runtime config\",\n detail: cause.message,\n cause,\n }),\n ),\n );\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n uiPort?: number;\n}\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n return res.ok;\n } catch {\n return false;\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\n\n/** Remote-host boot budgets: every stage of the CDN-only boot is deadline-\n * bounded so a hung connection or a wedged module load fails loud with the\n * URL and stage — long before the smoke's 240s probe deadline turns the\n * silence into a mystery. */\nconst MANIFEST_FETCH_DEADLINE = \"10 seconds\";\nconst LOAD_REMOTE_DEADLINE = \"60 seconds\";\nconst SERVER_READY_DEADLINE = \"120 seconds\";\nconst REMOTE_HOST_BOOT_DEADLINE = \"180 seconds\";\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst cleanExitSignals: Record<string, true> = { SIGTERM: true, SIGINT: true };\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nexport const detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n port?: number;\n env?: Record<string, string>;\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[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) {\n const cause = arg.cause;\n parts.push(\n `(cause: ${cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : (JSON.stringify(cause) ?? \"[Unserializable cause]\")})`,\n );\n }\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n if (arg === null) return \"null\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"bigint\" || typeof arg === \"boolean\")\n return `${arg}`;\n if (typeof arg === \"symbol\") return arg.description ?? \"\";\n if (typeof arg === \"undefined\") return \"undefined\";\n return JSON.stringify(arg, null, 2) ?? \"[Unserializable value]\";\n })\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), 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 class HostRemoteUrlMissing extends Data.TaggedError(\"HostRemoteUrlMissing\")<\n Record<never, never>\n> {\n override get message() {\n return \"remoteUrl not provided on host descriptor\";\n }\n}\n\nexport class HostModuleInvalid extends Data.TaggedError(\"HostModuleInvalid\")<Record<never, never>> {\n override get message() {\n return \"Host module does not export runServer function\";\n }\n}\n\nexport class LocalPathMissing extends Data.TaggedError(\"LocalPathMissing\")<{ key: string }> {\n get message() {\n return `No localPath for local service: ${this.key}`;\n }\n}\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* new HostRemoteUrlMissing();\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n // The manifest IS the entry contract (ADR 0020 amendment: hashed\n // entrypoints, fixed-name `remoteEntry.js` retired — it 404s on the CDN).\n // A failed manifest fetch must fail loud with the URL and status: the old\n // silent fallback to remoteEntry.js turned any transient hiccup (a CDN\n // 403 challenge, a timeout) into a guaranteed loadRemote failure with no\n // named cause.\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n let res: Response;\n try {\n res = await fetchRaw(manifestUrl, undefined, MANIFEST_FETCH_DEADLINE);\n } catch (e) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${e instanceof Error ? e.message : String(e)}`,\n cause: e,\n });\n }\n if (!res.ok) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : \"\"}`,\n });\n }\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 throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — not a Module Federation manifest (missing metaData/exposes/shared)`,\n });\n }\n return manifestUrl;\n },\n catch: (cause) =>\n cause instanceof OrchestratorError\n ? cause\n : new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${String(cause)}`,\n }),\n });\n\n yield* Effect.promise(() => registerRemote({ name: \"host\", entry: entryUrl }));\n callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n loadRemoteModule<{\n runServer: (input: ServerInput) => ServerHandle;\n }>(\"host/Server\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load host module\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.timeoutOrElse({\n duration: LOAD_REMOTE_DEADLINE,\n orElse: () =>\n Effect.fail(\n new OrchestratorError({\n operation: \"load host module\",\n detail: `timed out after ${LOAD_REMOTE_DEADLINE} — the module (or its shared dependencies) did not finish loading from ${entryUrl}`,\n }),\n ),\n }),\n );\n\n if (!hostModule?.runServer) {\n return yield* new HostModuleInvalid();\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const hostPort = runtimeConfig.host?.port;\n const hostEnv: Record<string, string> | undefined = hostPort\n ? { PORT: String(hostPort) }\n : undefined;\n const serverHandle = hostModule.runServer({\n config: runtimeConfig,\n port: hostPort,\n env: hostEnv,\n });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (cause) =>\n new OrchestratorError({\n operation: \"start server\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.timeoutOrElse({\n duration: SERVER_READY_DEADLINE,\n // A half-started server must not leak its port on the deadline path —\n // the success path hands shutdown to the process handle instead.\n orElse: () =>\n Effect.gen(function* () {\n yield* Effect.exit(Effect.promise(() => serverHandle.shutdown()));\n return yield* new OrchestratorError({\n operation: \"start server\",\n detail: `server did not become ready within ${SERVER_READY_DEADLINE}`,\n });\n }),\n }),\n );\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: undefined,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\n/**\n * Spawn env precedence, three tiers: values explicitly exported by the\n * caller (shell / CI / regression harness — captured by the bootstrap\n * program into the `ShellEnv` service before any `.env` loading) outrank the\n * generated infra env, which outranks `.env`-file values inherited through\n * `processEnv`. The service's resolved port is always authoritative.\n */\nexport function composeSpawnEnv(\n processEnv: Record<string, string>,\n generatedEnv: Record<string, string>,\n port: number,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n return {\n ...processEnv,\n ...mergeGeneratedOverFileEnv(generatedEnv, processEnv, shellEnv),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n}\n\n/**\n * Overlay the generated infra env (ports drift, so stale `.env` values must\n * lose) while keeping every explicitly exported key from `shellEnv` intact.\n * Keys absent from both are untouched.\n *\n * Exception (ADR 0012 / plan 038): the origin keys BASE_URL and CORS_ORIGIN\n * are always generated-owned — a wrapper that sourced a stale `.env` must not\n * win over the resolved host port, in the child env or on disk.\n */\nconst GENERATED_OWNED_KEYS = new Set([\"BASE_URL\", \"CORS_ORIGIN\"]);\n\nexport function mergeGeneratedOverFileEnv(\n generatedEnv: Record<string, string>,\n processEnv: Record<string, string>,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n const result: Record<string, string> = { ...processEnv };\n for (const [key, value] of Object.entries(generatedEnv)) {\n if (!GENERATED_OWNED_KEYS.has(key) && key in shellEnv) {\n result[key] = shellEnv[key]!;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* new LocalPathMissing({ key: descriptor.key });\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"pnpm\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const generatedEnv = yield* DevGeneratedEnv;\n const shellTier = yield* ShellEnv;\n // The descriptor's env joins the generated tier — folding it in before\n // composeSpawnEnv keeps the documented precedence (shell > generated >\n // .env-file); assigning after would let it outrank the shell tier (and\n // the generated-owned keys) silently.\n const envVars = composeSpawnEnv(\n process.env as Record<string, string>,\n { ...generatedEnv, ...descriptor.env },\n port,\n shellTier,\n );\n\n envVars.BOS_RUNTIME_CONFIG = yield* encodeRuntimeConfig(runtimeConfig);\n\n const cmd = spawn(command, args, {\n cwd: fullCwd,\n env: envVars,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n });\n\n let lastExit: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n const exitCode = Effect.callback<number, OrchestratorError>((resume) => {\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n lastExit = { code, signal };\n resume(Effect.succeed(code ?? (signal ? 1 : 0)));\n };\n const onError = (err: Error) => {\n callbacks.onLog(name, `Spawn failed: ${err.message}`, true);\n callbacks.onStatus(name, \"error\", `spawn failed: ${err.message}`);\n resume(\n Effect.fail(\n new OrchestratorError({\n operation: \"spawn process\",\n detail: err.message,\n cause: err,\n }),\n ),\n );\n };\n cmd.once(\"exit\", onExit);\n cmd.once(\"error\", onError);\n return Effect.sync(() => {\n cmd.off(\"exit\", onExit);\n cmd.off(\"error\", onError);\n });\n });\n\n const describeExit = (exitCodeValue: number): string => {\n if (lastExit?.code === null && lastExit.signal) return `signal: ${lastExit.signal}`;\n return `exit code: ${exitCodeValue}`;\n };\n const isCleanSignalExit = (): boolean =>\n lastExit?.code === null && lastExit.signal != null && lastExit.signal in cleanExitSignals;\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(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"wait for process readiness\", detail: message }),\n ).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n if (port <= 0) return false;\n const ok = yield* probeHttpOk(url);\n if (ok) yield* markReady;\n return ok;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.spaced(`${port > 0 ? LOCAL_PROBE_INTERVAL_MS : 500} millis`),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${LOCAL_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = cmd.pid ?? undefined;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCodeValue = yield* exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") {\n // Post-ready exits must stay visible — a silently dead child (OOM\n // kill included) used to leave the stack answering with nothing.\n // A SIGTERM/SIGINT-signalled exit is the polite-quit path, not a\n // crash, so it logs as a plain shutdown line.\n if (currentStatus === \"ready\") {\n const detail = describeExit(exitCodeValue);\n callbacks.onLog(name, `Process exited after ready (${detail})`, !isCleanSignalExit());\n if (!isCleanSignalExit()) {\n callbacks.onStatus(name, \"error\", `exited after ready (${detail})`);\n }\n yield* markError(`Process exited after ready: ${name}`);\n }\n return;\n }\n callbacks.onLog(\n name,\n `Process exited before ready (${describeExit(exitCodeValue)})`,\n !isCleanSignalExit(),\n );\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !cleanLine.startsWith(\"$\");\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else if (currentStatus !== \"error\") {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n const stdoutStream = cmd.stdout\n ? (Readable.toWeb(cmd.stdout) as unknown as ReadableStream<Uint8Array>)\n : null;\n const stderrStream = cmd.stderr\n ? (Readable.toWeb(cmd.stderr) as unknown as ReadableStream<Uint8Array>)\n : null;\n\n if (stdoutStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stdoutStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stdout\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n if (stderrStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stderrStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stderr\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const groupPid = pid;\n const groupSignal = (signal: NodeJS.Signals) =>\n Effect.try(() => {\n if (groupPid !== undefined) process.kill(-groupPid, signal);\n }).pipe(Effect.ignore);\n yield* groupSignal(\"SIGTERM\");\n const exited = yield* exitCode.pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(exited)) {\n yield* groupSignal(\"SIGKILL\");\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\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 yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({\n operation: \"probe remote process\",\n detail: `Remote ${pkg} unreachable`,\n }),\n ).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (ok) {\n yield* markReady;\n return true;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (fallbackOk) {\n yield* markReady;\n return true;\n }\n return false;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.min([\n Schedule.exponential(`${REMOTE_PROBE_BACKOFF_INITIAL_MS} millis`, 1.5),\n Schedule.spaced(`${REMOTE_PROBE_BACKOFF_MAX_MS} millis`),\n ]),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${REMOTE_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"stop remote process\", detail: \"Killed\" }),\n ).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks).pipe(\n // Overall boot budget: with per-stage deadlines inside, this is the\n // backstop for anything the stage deadlines don't cover (a config\n // fetch, a slow MF internal) — the boot either comes up named-and-\n // ready or fails named-and-loud.\n Effect.timeoutOrElse({\n duration: REMOTE_HOST_BOOT_DEADLINE,\n orElse: () =>\n Effect.fail(\n new OrchestratorError({\n operation: \"boot remote host\",\n detail: `remote host boot exceeded the ${REMOTE_HOST_BOOT_DEADLINE} overall deadline`,\n }),\n ),\n }),\n );\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n uiPort: descriptor?.uiPort,\n };\n });\n}\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
+ import { fetchRaw } from "./http-client.mjs";
1
2
  import { DevGeneratedEnv, DevRuntimeConfig, ServiceDescriptorMap } from "./service-descriptor.mjs";
2
3
  import { stripAnsi } from "./dev-log-pipeline.mjs";
3
- import { patchManifestFetchForSsrPublicPath } from "./mf.mjs";
4
+ import { loadRemoteModule, registerRemote } from "./federation.mjs";
4
5
  import { ShellEnv } from "./env/project-env.mjs";
5
6
  import { Data, Deferred, Effect, Option, Ref, Schedule, Schema, Stream } from "effect";
6
7
  import { spawn } from "node:child_process";
7
8
  import { Readable } from "node:stream";
8
9
 
9
10
  //#region src/orchestrator.ts
10
- const runFetch = (url, init) => fetch(url, init);
11
11
  process.on("unhandledRejection", (reason) => {
12
12
  console.error("[Orchestrator] Unhandled rejection:", reason);
13
13
  });
@@ -32,7 +32,7 @@ const encodeRuntimeConfig = (runtimeConfig) => Schema.encodeUnknownEffect(Schema
32
32
  const probeHttpOk = (url, timeoutMs = 400) => Effect.tryPromise({
33
33
  try: async () => {
34
34
  try {
35
- return (await runFetch(url, { signal: AbortSignal.timeout(timeoutMs) })).ok;
35
+ return (await fetch(url, { signal: AbortSignal.timeout(timeoutMs) })).ok;
36
36
  } catch {
37
37
  return false;
38
38
  }
@@ -40,6 +40,14 @@ const probeHttpOk = (url, timeoutMs = 400) => Effect.tryPromise({
40
40
  catch: () => false
41
41
  });
42
42
  const LOCAL_PROBE_DEADLINE_MS = 9e4;
43
+ /** Remote-host boot budgets: every stage of the CDN-only boot is deadline-
44
+ * bounded so a hung connection or a wedged module load fails loud with the
45
+ * URL and stage — long before the smoke's 240s probe deadline turns the
46
+ * silence into a mystery. */
47
+ const MANIFEST_FETCH_DEADLINE = "10 seconds";
48
+ const LOAD_REMOTE_DEADLINE = "60 seconds";
49
+ const SERVER_READY_DEADLINE = "120 seconds";
50
+ const REMOTE_HOST_BOOT_DEADLINE = "180 seconds";
43
51
  const LOCAL_PROBE_INTERVAL_MS = 200;
44
52
  const cleanExitSignals = {
45
53
  SIGTERM: true,
@@ -130,37 +138,12 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
130
138
  callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);
131
139
  const restoreConsole = patchConsole(descriptor.key, callbacks);
132
140
  callbacks.onLog(descriptor.key, "Loading Module Federation runtime...");
133
- const mfRuntime = yield* Effect.tryPromise({
134
- try: () => import("@module-federation/enhanced/runtime"),
135
- catch: (cause) => new OrchestratorError({
136
- operation: "load module federation runtime",
137
- detail: cause instanceof Error ? cause.message : String(cause),
138
- cause
139
- })
140
- });
141
- const mfCore = yield* Effect.tryPromise({
142
- try: () => import("@module-federation/runtime-core"),
143
- catch: (cause) => new OrchestratorError({
144
- operation: "load module federation core",
145
- detail: cause instanceof Error ? cause.message : String(cause),
146
- cause
147
- })
148
- });
149
- let mf = mfRuntime.getInstance();
150
- if (!mf) {
151
- mf = mfRuntime.createInstance({
152
- name: "cli-host",
153
- remotes: []
154
- });
155
- mfCore.setGlobalFederationInstance(mf);
156
- }
157
- patchManifestFetchForSsrPublicPath(mf);
158
141
  const manifestUrl = `${remoteUrl.replace(/\/remoteEntry\.js$/, "").replace(/\/mf-manifest\.json$/, "").replace(/\/$/, "")}/mf-manifest.json`;
159
142
  const entryUrl = yield* Effect.tryPromise({
160
143
  try: async () => {
161
144
  let res;
162
145
  try {
163
- res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(1e4) });
146
+ res = await fetchRaw(manifestUrl, void 0, MANIFEST_FETCH_DEADLINE);
164
147
  } catch (e) {
165
148
  throw new OrchestratorError({
166
149
  operation: "fetch host manifest",
@@ -184,19 +167,25 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
184
167
  detail: `${manifestUrl} — ${String(cause)}`
185
168
  })
186
169
  });
187
- mf.registerRemotes([{
170
+ yield* Effect.promise(() => registerRemote({
188
171
  name: "host",
189
172
  entry: entryUrl
190
- }]);
173
+ }));
191
174
  callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);
192
175
  const hostModule = yield* Effect.tryPromise({
193
- try: () => mf.loadRemote("host/Server"),
176
+ try: () => loadRemoteModule("host/Server"),
194
177
  catch: (cause) => new OrchestratorError({
195
178
  operation: "load host module",
196
179
  detail: cause instanceof Error ? cause.message : String(cause),
197
180
  cause
198
181
  })
199
- });
182
+ }).pipe(Effect.timeoutOrElse({
183
+ duration: LOAD_REMOTE_DEADLINE,
184
+ orElse: () => Effect.fail(new OrchestratorError({
185
+ operation: "load host module",
186
+ detail: `timed out after ${LOAD_REMOTE_DEADLINE} — the module (or its shared dependencies) did not finish loading from ${entryUrl}`
187
+ }))
188
+ }));
200
189
  if (!hostModule?.runServer) return yield* new HostModuleInvalid();
201
190
  callbacks.onLog(descriptor.key, "Starting server...");
202
191
  const hostPort = runtimeConfig.host?.port;
@@ -213,7 +202,16 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
213
202
  detail: cause instanceof Error ? cause.message : String(cause),
214
203
  cause
215
204
  })
216
- });
205
+ }).pipe(Effect.timeoutOrElse({
206
+ duration: SERVER_READY_DEADLINE,
207
+ orElse: () => Effect.gen(function* () {
208
+ yield* Effect.exit(Effect.promise(() => serverHandle.shutdown()));
209
+ return yield* new OrchestratorError({
210
+ operation: "start server",
211
+ detail: `server did not become ready within ${SERVER_READY_DEADLINE}`
212
+ });
213
+ })
214
+ }));
217
215
  callbacks.onStatus(descriptor.key, "ready");
218
216
  return {
219
217
  name: descriptor.key,
@@ -494,7 +492,13 @@ const makeDevProcess = (pkg, callbacks, portOverride) => Effect.gen(function* ()
494
492
  waitForExit: Effect.never
495
493
  };
496
494
  }
497
- if (pkg === "host" && descriptor.source === "remote") return yield* spawnRemoteHost(descriptor, callbacks);
495
+ if (pkg === "host" && descriptor.source === "remote") return yield* spawnRemoteHost(descriptor, callbacks).pipe(Effect.timeoutOrElse({
496
+ duration: REMOTE_HOST_BOOT_DEADLINE,
497
+ orElse: () => Effect.fail(new OrchestratorError({
498
+ operation: "boot remote host",
499
+ detail: `remote host boot exceeded the ${REMOTE_HOST_BOOT_DEADLINE} overall deadline`
500
+ }))
501
+ }));
498
502
  if (descriptor.source === "remote" || !descriptor.localPath) return yield* spawnRemoteProbe(pkg, descriptor, callbacks);
499
503
  const resolvedDescriptor = portOverride ? {
500
504
  ...descriptor,
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.mjs","names":[],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { Readable } from \"node:stream\";\nimport { Data, Deferred, Effect, Option, Ref, Schedule, Schema, Stream } from \"effect\";\nimport { stripAnsi } from \"./dev-log-pipeline\";\nimport { ShellEnv } from \"./env/project-env\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport {\n DevGeneratedEnv,\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst runFetch = (url: string, init?: RequestInit): Promise<Response> => fetch(url, init);\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\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>;\n waitForReady: Effect.Effect<void, OrchestratorError>;\n waitForExit: Effect.Effect<number, OrchestratorError>;\n}\n\nexport class OrchestratorError extends Data.TaggedError(\"OrchestratorError\")<{\n readonly operation: string;\n readonly detail: string;\n readonly cause?: unknown;\n}> {\n override get message() {\n return `${this.operation}: ${this.detail}`;\n }\n}\n\nconst omitUndefined = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map((item) => (item === undefined ? null : omitUndefined(item)));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, omitUndefined(item)]),\n );\n }\n return value;\n};\n\nexport const encodeRuntimeConfig = (runtimeConfig: unknown) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Json))(omitUndefined(runtimeConfig)).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestratorError({\n operation: \"serialize runtime config\",\n detail: cause.message,\n cause,\n }),\n ),\n );\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n uiPort?: number;\n}\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n try {\n const res = await runFetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n return res.ok;\n } catch {\n return false;\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst cleanExitSignals: Record<string, true> = { SIGTERM: true, SIGINT: true };\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nexport const detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n port?: number;\n env?: Record<string, string>;\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[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) {\n const cause = arg.cause;\n parts.push(\n `(cause: ${cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : (JSON.stringify(cause) ?? \"[Unserializable cause]\")})`,\n );\n }\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n if (arg === null) return \"null\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"bigint\" || typeof arg === \"boolean\")\n return `${arg}`;\n if (typeof arg === \"symbol\") return arg.description ?? \"\";\n if (typeof arg === \"undefined\") return \"undefined\";\n return JSON.stringify(arg, null, 2) ?? \"[Unserializable value]\";\n })\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), 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 class HostRemoteUrlMissing extends Data.TaggedError(\"HostRemoteUrlMissing\")<\n Record<never, never>\n> {\n override get message() {\n return \"remoteUrl not provided on host descriptor\";\n }\n}\n\nexport class HostModuleInvalid extends Data.TaggedError(\"HostModuleInvalid\")<Record<never, never>> {\n override get message() {\n return \"Host module does not export runServer function\";\n }\n}\n\nexport class LocalPathMissing extends Data.TaggedError(\"LocalPathMissing\")<{ key: string }> {\n get message() {\n return `No localPath for local service: ${this.key}`;\n }\n}\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* new HostRemoteUrlMissing();\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load module federation runtime\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load module federation core\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\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 manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n // The manifest IS the entry contract (ADR 0020 amendment: hashed\n // entrypoints, fixed-name `remoteEntry.js` retired — it 404s on the CDN).\n // A failed manifest fetch must fail loud with the URL and status: the old\n // silent fallback to remoteEntry.js turned any transient hiccup (a CDN\n // 403 challenge, a timeout) into a guaranteed loadRemote failure with no\n // named cause.\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n let res: Response;\n try {\n res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(10_000) });\n } catch (e) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${e instanceof Error ? e.message : String(e)}`,\n cause: e,\n });\n }\n if (!res.ok) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : \"\"}`,\n });\n }\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 throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — not a Module Federation manifest (missing metaData/exposes/shared)`,\n });\n }\n return manifestUrl;\n },\n catch: (cause) =>\n cause instanceof OrchestratorError\n ? cause\n : new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${String(cause)}`,\n }),\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(descriptor.key, `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: (cause) =>\n new OrchestratorError({\n operation: \"load host module\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n if (!hostModule?.runServer) {\n return yield* new HostModuleInvalid();\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const hostPort = runtimeConfig.host?.port;\n const hostEnv: Record<string, string> | undefined = hostPort\n ? { PORT: String(hostPort) }\n : undefined;\n const serverHandle = hostModule.runServer({\n config: runtimeConfig,\n port: hostPort,\n env: hostEnv,\n });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (cause) =>\n new OrchestratorError({\n operation: \"start server\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n });\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: undefined,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\n/**\n * Spawn env precedence, three tiers: values explicitly exported by the\n * caller (shell / CI / regression harness — captured by the bootstrap\n * program into the `ShellEnv` service before any `.env` loading) outrank the\n * generated infra env, which outranks `.env`-file values inherited through\n * `processEnv`. The service's resolved port is always authoritative.\n */\nexport function composeSpawnEnv(\n processEnv: Record<string, string>,\n generatedEnv: Record<string, string>,\n port: number,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n return {\n ...processEnv,\n ...mergeGeneratedOverFileEnv(generatedEnv, processEnv, shellEnv),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n}\n\n/**\n * Overlay the generated infra env (ports drift, so stale `.env` values must\n * lose) while keeping every explicitly exported key from `shellEnv` intact.\n * Keys absent from both are untouched.\n *\n * Exception (ADR 0012 / plan 038): the origin keys BASE_URL and CORS_ORIGIN\n * are always generated-owned — a wrapper that sourced a stale `.env` must not\n * win over the resolved host port, in the child env or on disk.\n */\nconst GENERATED_OWNED_KEYS = new Set([\"BASE_URL\", \"CORS_ORIGIN\"]);\n\nexport function mergeGeneratedOverFileEnv(\n generatedEnv: Record<string, string>,\n processEnv: Record<string, string>,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n const result: Record<string, string> = { ...processEnv };\n for (const [key, value] of Object.entries(generatedEnv)) {\n if (!GENERATED_OWNED_KEYS.has(key) && key in shellEnv) {\n result[key] = shellEnv[key]!;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* new LocalPathMissing({ key: descriptor.key });\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"pnpm\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const generatedEnv = yield* DevGeneratedEnv;\n const shellTier = yield* ShellEnv;\n // The descriptor's env joins the generated tier — folding it in before\n // composeSpawnEnv keeps the documented precedence (shell > generated >\n // .env-file); assigning after would let it outrank the shell tier (and\n // the generated-owned keys) silently.\n const envVars = composeSpawnEnv(\n process.env as Record<string, string>,\n { ...generatedEnv, ...descriptor.env },\n port,\n shellTier,\n );\n\n envVars.BOS_RUNTIME_CONFIG = yield* encodeRuntimeConfig(runtimeConfig);\n\n const cmd = spawn(command, args, {\n cwd: fullCwd,\n env: envVars,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n });\n\n let lastExit: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n const exitCode = Effect.callback<number, OrchestratorError>((resume) => {\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n lastExit = { code, signal };\n resume(Effect.succeed(code ?? (signal ? 1 : 0)));\n };\n const onError = (err: Error) => {\n callbacks.onLog(name, `Spawn failed: ${err.message}`, true);\n callbacks.onStatus(name, \"error\", `spawn failed: ${err.message}`);\n resume(\n Effect.fail(\n new OrchestratorError({\n operation: \"spawn process\",\n detail: err.message,\n cause: err,\n }),\n ),\n );\n };\n cmd.once(\"exit\", onExit);\n cmd.once(\"error\", onError);\n return Effect.sync(() => {\n cmd.off(\"exit\", onExit);\n cmd.off(\"error\", onError);\n });\n });\n\n const describeExit = (exitCodeValue: number): string => {\n if (lastExit?.code === null && lastExit.signal) return `signal: ${lastExit.signal}`;\n return `exit code: ${exitCodeValue}`;\n };\n const isCleanSignalExit = (): boolean =>\n lastExit?.code === null && lastExit.signal != null && lastExit.signal in cleanExitSignals;\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(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"wait for process readiness\", detail: message }),\n ).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n if (port <= 0) return false;\n const ok = yield* probeHttpOk(url);\n if (ok) yield* markReady;\n return ok;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.spaced(`${port > 0 ? LOCAL_PROBE_INTERVAL_MS : 500} millis`),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${LOCAL_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = cmd.pid ?? undefined;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCodeValue = yield* exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") {\n // Post-ready exits must stay visible — a silently dead child (OOM\n // kill included) used to leave the stack answering with nothing.\n // A SIGTERM/SIGINT-signalled exit is the polite-quit path, not a\n // crash, so it logs as a plain shutdown line.\n if (currentStatus === \"ready\") {\n const detail = describeExit(exitCodeValue);\n callbacks.onLog(name, `Process exited after ready (${detail})`, !isCleanSignalExit());\n if (!isCleanSignalExit()) {\n callbacks.onStatus(name, \"error\", `exited after ready (${detail})`);\n }\n yield* markError(`Process exited after ready: ${name}`);\n }\n return;\n }\n callbacks.onLog(\n name,\n `Process exited before ready (${describeExit(exitCodeValue)})`,\n !isCleanSignalExit(),\n );\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !cleanLine.startsWith(\"$\");\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else if (currentStatus !== \"error\") {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n const stdoutStream = cmd.stdout\n ? (Readable.toWeb(cmd.stdout) as unknown as ReadableStream<Uint8Array>)\n : null;\n const stderrStream = cmd.stderr\n ? (Readable.toWeb(cmd.stderr) as unknown as ReadableStream<Uint8Array>)\n : null;\n\n if (stdoutStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stdoutStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stdout\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n if (stderrStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stderrStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stderr\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const groupPid = pid;\n const groupSignal = (signal: NodeJS.Signals) =>\n Effect.try(() => {\n if (groupPid !== undefined) process.kill(-groupPid, signal);\n }).pipe(Effect.ignore);\n yield* groupSignal(\"SIGTERM\");\n const exited = yield* exitCode.pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(exited)) {\n yield* groupSignal(\"SIGKILL\");\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\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 yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({\n operation: \"probe remote process\",\n detail: `Remote ${pkg} unreachable`,\n }),\n ).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (ok) {\n yield* markReady;\n return true;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (fallbackOk) {\n yield* markReady;\n return true;\n }\n return false;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.min([\n Schedule.exponential(`${REMOTE_PROBE_BACKOFF_INITIAL_MS} millis`, 1.5),\n Schedule.spaced(`${REMOTE_PROBE_BACKOFF_MAX_MS} millis`),\n ]),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${REMOTE_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"stop remote process\", detail: \"Killed\" }),\n ).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks);\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n uiPort: descriptor?.uiPort,\n };\n });\n}\n"],"mappings":";;;;;;;;;AAcA,MAAM,YAAY,KAAa,SAA0C,MAAM,KAAK,IAAI;AAExF,QAAQ,GAAG,uBAAuB,WAAW;CAC3C,QAAQ,MAAM,uCAAuC,MAAM;AAC7D,CAAC;AAED,QAAQ,GAAG,sBAAsB,QAAQ;CACvC,QAAQ,MAAM,sCAAsC,GAAG;AACzD,CAAC;AAeD,IAAa,oBAAb,cAAuC,KAAK,YAAY,mBAAmB,CAAC,CAIzE;CACD,IAAa,UAAU;EACrB,OAAO,GAAG,KAAK,UAAU,IAAI,KAAK;CACpC;AACF;AAEA,MAAM,iBAAiB,UAA4B;CACjD,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,KAAK,SAAU,SAAS,SAAY,OAAO,cAAc,IAAI,CAAE;CAE9E,IAAI,UAAU,QAAQ,OAAO,UAAU,UACrC,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,CAAC,CAClB,QAAQ,GAAG,UAAU,SAAS,MAAS,CAAC,CACxC,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,cAAc,IAAI,CAAC,CAAC,CACpD;CAEF,OAAO;AACT;AAEA,MAAa,uBAAuB,kBAClC,OAAO,oBAAoB,OAAO,eAAe,OAAO,IAAI,CAAC,CAAC,CAAC,cAAc,aAAa,CAAC,CAAC,CAAC,KAC3F,OAAO,UACJ,UACC,IAAI,kBAAkB;CACpB,WAAW;CACX,QAAQ,MAAM;CACd;AACF,CAAC,CACL,CACF;AAaF,MAAM,eAAe,KAAa,YAAY,QAC5C,OAAO,WAAW;CAChB,KAAK,YAAY;EACf,IAAI;GAEF,QAAO,MADW,SAAS,KAAK,EAAE,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC,EAChE,CAAC;EACb,QAAQ;GACN,OAAO;EACT;CACF;CACA,aAAa;AACf,CAAC;AAEH,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAEhC,MAAM,mBAAyC;CAAE,SAAS;CAAM,QAAQ;AAAK;AAE7E,MAAM,0BAA0B;AAChC,MAAM,2BAA2B;AACjC,MAAM,kCAAkC;AACxC,MAAM,8BAA8B;AAEpC,MAAa,gBACX,MACA,eACuD;CACvD,MAAM,YAAY,UAAU,IAAI;CAChC,MAAM,gBAAgB,WAAW,iBAAiB,CAAC;CACnD,MAAM,gBAAgB,WAAW,iBAAiB,CAAC;CACnD,KAAK,MAAM,WAAW,eACpB,IAAI,QAAQ,KAAK,SAAS,GACxB,OAAO;EAAE,QAAQ;EAAS,SAAS;CAAM;CAG7C,KAAK,MAAM,WAAW,eACpB,IAAI,QAAQ,KAAK,SAAS,GACxB,OAAO;EAAE,QAAQ;EAAS,SAAS;CAAK;CAG5C,OAAO;AACT;AAaA,MAAM,gBAAgB,MAAc,cAA8C;CAChF,MAAM,cAAc,QAAQ;CAC5B,MAAM,gBAAgB,QAAQ;CAC9B,MAAM,eAAe,QAAQ;CAC7B,MAAM,eAAe,QAAQ;CAE7B,MAAM,cAAc,MAAiB,UAAU,UAAkB;EAC/D,OAAO,KACJ,KAAK,QAAQ;GACZ,IAAI,eAAe,OAAO;IACxB,MAAM,QAAQ,CAAC,GAAG,IAAI,KAAK,IAAI,IAAI,SAAS;IAC5C,IAAI,IAAI,iBAAiB,OACvB,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,EAAE;SAC1D,IAAI,IAAI,OAAO;KAClB,MAAM,QAAQ,IAAI;KAClB,MAAM,KACJ,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAS,KAAK,UAAU,KAAK,KAAK,yBAA0B,EAC9I;IACF;IACA,IAAI,WAAW,IAAI,OAAO,MAAM,KAAK,IAAI,KAAK;IAC9C,OAAO,MAAM,KAAK,IAAI;GACxB;GACA,IAAI,QAAQ,MAAM,OAAO;GACzB,IAAI,OAAO,QAAQ,UAAU,OAAO;GACpC,IAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,YAAY,OAAO,QAAQ,WACvE,OAAO,GAAG;GACZ,IAAI,OAAO,QAAQ,UAAU,OAAO,IAAI,eAAe;GACvD,IAAI,OAAO,QAAQ,aAAa,OAAO;GACvC,OAAO,KAAK,UAAU,KAAK,MAAM,CAAC,KAAK;EACzC,CAAC,CAAC,CACD,KAAK,GAAG;CACb;CAEA,QAAQ,OAAO,GAAG,SAAoB;EACpC,UAAU,MAAM,MAAM,WAAW,IAAI,GAAG,KAAK;CAC/C;CACA,QAAQ,SAAS,GAAG,SAAoB;EACtC,UAAU,MAAM,MAAM,WAAW,MAAM,IAAI,GAAG,IAAI;CACpD;CACA,QAAQ,QAAQ,GAAG,SAAoB;EACrC,UAAU,MAAM,MAAM,WAAW,IAAI,GAAG,KAAK;CAC/C;CACA,QAAQ,QAAQ,GAAG,SAAoB;EACrC,UAAU,MAAM,MAAM,WAAW,IAAI,GAAG,KAAK;CAC/C;CAEA,aAAa;EACX,QAAQ,MAAM;EACd,QAAQ,QAAQ;EAChB,QAAQ,OAAO;EACf,QAAQ,OAAO;CACjB;AACF;AAEA,IAAa,uBAAb,cAA0C,KAAK,YAAY,sBAAsB,CAAC,CAEhF;CACA,IAAa,UAAU;EACrB,OAAO;CACT;AACF;AAEA,IAAa,oBAAb,cAAuC,KAAK,YAAY,mBAAmB,CAAC,CAAuB;CACjG,IAAa,UAAU;EACrB,OAAO;CACT;AACF;AAEA,IAAa,mBAAb,cAAsC,KAAK,YAAY,kBAAkB,CAAC,CAAkB;CAC1F,IAAI,UAAU;EACZ,OAAO,mCAAmC,KAAK;CACjD;AACF;AAEA,MAAM,mBAAmB,YAA+B,cACtD,OAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAO;CAC7B,MAAM,YAAY,WAAW;CAC7B,IAAI,CAAC,WACH,OAAO,OAAO,IAAI,qBAAqB;CAGzC,UAAU,SAAS,WAAW,KAAK,UAAU;CAC7C,UAAU,MAAM,WAAW,KAAK,WAAW,WAAW;CACtD,MAAM,iBAAiB,aAAa,WAAW,KAAK,SAAS;CAC7D,UAAU,MAAM,WAAW,KAAK,sCAAsC;CAEtE,MAAM,YAAY,OAAO,OAAO,WAAW;EACzC,WAAW,OAAO;EAClB,QAAQ,UACN,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC7D;EACF,CAAC;CACL,CAAC;CAED,MAAM,SAAS,OAAO,OAAO,WAAW;EACtC,WAAW,OAAO;EAClB,QAAQ,UACN,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC7D;EACF,CAAC;CACL,CAAC;CAED,IAAI,KAAK,UAAU,YAAY;CAC/B,IAAI,CAAC,IAAI;EACP,KAAK,UAAU,eAAe;GAAE,MAAM;GAAY,SAAS,CAAC;EAAE,CAAC;EAC/D,OAAO,4BAA4B,EAAE;CACvC;CACA,mCAAmC,EAAS;CAM5C,MAAM,cAAc,GAJJ,UACb,QAAQ,sBAAsB,EAAE,CAAC,CACjC,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,OAAO,EACW,EAAE;CAQ/B,MAAM,WAAW,OAAO,OAAO,WAAW;EACxC,KAAK,YAAY;GACf,IAAI;GACJ,IAAI;IACF,MAAM,MAAM,SAAS,aAAa,EAAE,QAAQ,YAAY,QAAQ,GAAM,EAAE,CAAC;GAC3E,SAAS,GAAG;IACV,MAAM,IAAI,kBAAkB;KAC1B,WAAW;KACX,QAAQ,GAAG,YAAY,KAAK,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;KACrE,OAAO;IACT,CAAC;GACH;GACA,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,kBAAkB;IAC1B,WAAW;IACX,QAAQ,GAAG,YAAY,UAAU,IAAI,SAAS,IAAI,aAAa,IAAI,IAAI,eAAe;GACxF,CAAC;GAEH,MAAM,OAAQ,MAAM,IAAI,KAAK;GAC7B,IACE,CAAC,QACD,OAAO,SAAS,YAChB,EAAE,cAAc,SAChB,EAAE,aAAa,SACf,EAAE,YAAY,OAEd,MAAM,IAAI,kBAAkB;IAC1B,WAAW;IACX,QAAQ,GAAG,YAAY;GACzB,CAAC;GAEH,OAAO;EACT;EACA,QAAQ,UACN,iBAAiB,oBACb,QACA,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,GAAG,YAAY,KAAK,OAAO,KAAK;EAC1C,CAAC;CACT,CAAC;CAED,AAAC,GAAW,gBAAgB,CAAC;EAAE,MAAM;EAAQ,OAAO;CAAS,CAAC,CAAC;CAC/D,UAAU,MAAM,WAAW,KAAK,qBAAqB,SAAS,IAAI;CAElE,MAAM,aAAa,OAAO,OAAO,WAAW;EAC1C,WACG,GAAW,WAAW,aAAa;EAGtC,QAAQ,UACN,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC7D;EACF,CAAC;CACL,CAAC;CAED,IAAI,CAAC,YAAY,WACf,OAAO,OAAO,IAAI,kBAAkB;CAGtC,UAAU,MAAM,WAAW,KAAK,oBAAoB;CACpD,MAAM,WAAW,cAAc,MAAM;CACrC,MAAM,UAA8C,WAChD,EAAE,MAAM,OAAO,QAAQ,EAAE,IACzB;CACJ,MAAM,eAAe,WAAW,UAAU;EACxC,QAAQ;EACR,MAAM;EACN,KAAK;CACP,CAAC;CACD,OAAO,OAAO,WAAW;EACvB,WAAW,aAAa;EACxB,QAAQ,UACN,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC7D;EACF,CAAC;CACL,CAAC;CAED,UAAU,SAAS,WAAW,KAAK,OAAO;CAE1C,OAAO;EACL,MAAM,WAAW;EACjB,KAAK;EACL,MAAM,OAAO,IAAI,aAAa;GAC5B,UAAU,MAAM,WAAW,KAAK,8BAA8B;GAC9D,eAAe;GACf,OAAO,OAAO,WAAW;IACvB,WAAW,aAAa,SAAS;IACjC,aAAa,CAAC;GAChB,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;EACvB,CAAC;EACD,cAAc,OAAO;EACrB,aAAa,OAAO;CACtB;AACF,CAAC;;;;;;;;AASH,SAAgB,gBACd,YACA,cACA,MACA,WAAmC,CAAC,GACZ;CACxB,OAAO;EACL,GAAG;EACH,GAAG,0BAA0B,cAAc,YAAY,QAAQ;EAC/D,aAAa;EACb,GAAI,OAAO,IAAI,EAAE,MAAM,OAAO,IAAI,EAAE,IAAI,CAAC;CAC3C;AACF;;;;;;;;;;AAWA,MAAM,uCAAuB,IAAI,IAAI,CAAC,YAAY,aAAa,CAAC;AAEhE,SAAgB,0BACd,cACA,YACA,WAAmC,CAAC,GACZ;CACxB,MAAM,SAAiC,EAAE,GAAG,WAAW;CACvD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,GACpD,IAAI,CAAC,qBAAqB,IAAI,GAAG,KAAK,OAAO,UAC3C,OAAO,OAAO,SAAS;MAEvB,OAAO,OAAO;CAGlB,OAAO;AACT;AAEA,MAAM,mBAAmB,YAA+B,cACtD,OAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAO;CAE7B,IAAI,CAAC,WAAW,WACd,OAAO,OAAO,IAAI,iBAAiB,EAAE,KAAK,WAAW,IAAI,CAAC;CAG5D,MAAM,UAAU,WAAW;CAC3B,MAAM,UAAU,WAAW,WAAW;CACtC,MAAM,OAAO,WAAW,QAAQ,CAAC,OAAO,KAAK;CAC7C,MAAM,OAAO,WAAW,QAAQ,WAAW;CAC3C,MAAM,OAAO,WAAW;CAExB,MAAM,gBAAgB,OAAO,SAAS,KAA8B;CACpE,MAAM,YAAY,OAAO,IAAI,KAAoB,UAAU;CAE3D,UAAU,SAAS,MAAM,UAAU;CAEnC,MAAM,eAAe,OAAO;CAC5B,MAAM,YAAY,OAAO;CAKzB,MAAM,UAAU,gBACd,QAAQ,KACR;EAAE,GAAG;EAAc,GAAG,WAAW;CAAI,GACrC,MACA,SACF;CAEA,QAAQ,qBAAqB,OAAO,oBAAoB,aAAa;CAErE,MAAM,MAAM,MAAM,SAAS,MAAM;EAC/B,KAAK;EACL,KAAK;EACL,OAAO;GAAC;GAAU;GAAQ;EAAM;EAChC,UAAU;CACZ,CAAC;CAED,IAAI,WAA0E;CAC9E,MAAM,WAAW,OAAO,UAAqC,WAAW;EACtE,MAAM,UAAU,MAAqB,WAAkC;GACrE,WAAW;IAAE;IAAM;GAAO;GAC1B,OAAO,OAAO,QAAQ,SAAS,SAAS,IAAI,EAAE,CAAC;EACjD;EACA,MAAM,WAAW,QAAe;GAC9B,UAAU,MAAM,MAAM,iBAAiB,IAAI,WAAW,IAAI;GAC1D,UAAU,SAAS,MAAM,SAAS,iBAAiB,IAAI,SAAS;GAChE,OACE,OAAO,KACL,IAAI,kBAAkB;IACpB,WAAW;IACX,QAAQ,IAAI;IACZ,OAAO;GACT,CAAC,CACH,CACF;EACF;EACA,IAAI,KAAK,QAAQ,MAAM;EACvB,IAAI,KAAK,SAAS,OAAO;EACzB,OAAO,OAAO,WAAW;GACvB,IAAI,IAAI,QAAQ,MAAM;GACtB,IAAI,IAAI,SAAS,OAAO;EAC1B,CAAC;CACH,CAAC;CAED,MAAM,gBAAgB,kBAAkC;EACtD,IAAI,UAAU,SAAS,QAAQ,SAAS,QAAQ,OAAO,WAAW,SAAS;EAC3E,OAAO,cAAc;CACvB;CACA,MAAM,0BACJ,UAAU,SAAS,QAAQ,SAAS,UAAU,QAAQ,SAAS,UAAU;CAE3E,MAAM,YAAY,OAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,WAAW,kBAAkB,SAAS;EAC5D,OAAO,IAAI,IAAI,WAAW,OAAO;EACjC,UAAU,SAAS,MAAM,OAAO;EAChC,OAAO,SAAS,QAAQ,eAAe,MAAS,CAAC,CAAC,KAAK,OAAO,MAAM;CACtE,CAAC;CAED,MAAM,aAAa,YACjB,OAAO,IAAI,aAAa;EACtB,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,WAAW,kBAAkB,SAAS;EAC5D,OAAO,IAAI,IAAI,WAAW,OAAO;EACjC,UAAU,SAAS,MAAM,OAAO;EAChC,OAAO,SAAS,KACd,eACA,IAAI,kBAAkB;GAAE,WAAW;GAA8B,QAAQ;EAAQ,CAAC,CACpF,CAAC,CAAC,KAAK,OAAO,MAAM;CACtB,CAAC;CAEH,OAAO,OAAO,WACZ,OAAO,IAAI,aAAa;EACtB,MAAM,gBAAgB,WAAW;EACjC,MAAM,MAAM,oBAAoB,OAAO;EACvC,MAAM,iBAAiB,OAAO,IAAI,aAAa;GAC7C,MAAM,SAAS,OAAO,IAAI,IAAI,SAAS;GACvC,IAAI,WAAW,WAAW,WAAW,SAAS,OAAO;GACrD,IAAI,QAAQ,GAAG,OAAO;GACtB,MAAM,KAAK,OAAO,YAAY,GAAG;GACjC,IAAI,IAAI,OAAO;GACf,OAAO;EACT,CAAC;EAQD,IAAI,OAPiB,OAAO,OAAO,gBAAgB;GACjD,UAAU,SAAS,OAAO,GAAG,OAAO,IAAI,0BAA0B,IAAI,QAAQ;GAC9E,QAAQ,SAAS;EACnB,CAAC,CAAC,CAAC,KACD,OAAO,QAAQ,GAAG,wBAAwB,QAAQ,GAClD,OAAO,SAAS,sBAAsB,OAAO,QAAQ,KAAK,CAAC,CAC7D,GACW;EAEX,MAAM,SAAS,OAAO,IAAI,IAAI,SAAS;EACvC,IAAI,WAAW,WAAW,WAAW,SAAS;GAC5C,UAAU,MAAM,MAAM,qCAAqC,IAAI;GAC/D,OAAO,UAAU,4BAA4B,MAAM;EACrD;CACF,CAAC,CACH;CAEA,MAAM,MAAM,IAAI,OAAO;CAEvB,OAAO,OAAO,WACZ,OAAO,IAAI,aAAa;EACtB,MAAM,gBAAgB,OAAO;EAC7B,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,WAAW,kBAAkB,SAAS;GAK1D,IAAI,kBAAkB,SAAS;IAC7B,MAAM,SAAS,aAAa,aAAa;IACzC,UAAU,MAAM,MAAM,+BAA+B,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACpF,IAAI,CAAC,kBAAkB,GACrB,UAAU,SAAS,MAAM,SAAS,uBAAuB,OAAO,EAAE;IAEpE,OAAO,UAAU,+BAA+B,MAAM;GACxD;GACA;EACF;EACA,UAAU,MACR,MACA,gCAAgC,aAAa,aAAa,EAAE,IAC5D,CAAC,kBAAkB,CACrB;EACA,OAAO,UAAU,gCAAgC,MAAM;CACzD,CAAC,CACH;CAEA,MAAM,cAAc,MAAc,aAChC,OAAO,IAAI,aAAa;EACtB,IAAI,CAAC,KAAK,KAAK,GAAG;EAElB,MAAM,YAAY,UAAU,IAAI;EAChC,MAAM,iBACJ,YACA,kDAAkD,KAAK,SAAS,KAChE,CAAC,UAAU,WAAW,GAAG;EAC3B,UAAU,MAAM,MAAM,MAAM,cAAc;EAE1C,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,SAAS;EAE/B,MAAM,WAAW,aAAa,MAAM,UAAU;EAC9C,IAAI,UAAU;GACZ,IAAI,SAAS,WAAW,SACtB,OAAO;QACF,IAAI,kBAAkB,SAC3B,OAAO,UAAU,mBAAmB,MAAM;EAE9C;CACF,CAAC;CAEH,MAAM,eAAe,IAAI,SACpB,SAAS,MAAM,IAAI,MAAM,IAC1B;CACJ,MAAM,eAAe,IAAI,SACpB,SAAS,MAAM,IAAI,MAAM,IAC1B;CAEJ,IAAI,cACF,OAAO,OAAO,WACZ,OAAO,YAAY,SAAiB,WAAW,MAAM,KAAK,CAAC,CAAC,CAC1D,OAAO,WACL,OAAO,WACL,OAAO,mBAAmB;EACxB,gBAAgB;EAChB,UAAU,UACR,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,OAAO,KAAK;GACpB;EACF,CAAC;CACL,CAAC,CACH,CACF,CACF,CACF;CAGF,IAAI,cACF,OAAO,OAAO,WACZ,OAAO,YAAY,SAAiB,WAAW,MAAM,IAAI,CAAC,CAAC,CACzD,OAAO,WACL,OAAO,WACL,OAAO,mBAAmB;EACxB,gBAAgB;EAChB,UAAU,UACR,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,OAAO,KAAK;GACpB;EACF,CAAC;CACL,CAAC,CACH,CACF,CACF,CACF;CAGF,OAAO;EACL;EACA;EACA,MAAM,OAAO,IAAI,aAAa;GAC5B,MAAM,WAAW;GACjB,MAAM,eAAe,WACnB,OAAO,UAAU;IACf,IAAI,aAAa,QAAW,QAAQ,KAAK,CAAC,UAAU,MAAM;GAC5D,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;GACvB,OAAO,YAAY,SAAS;GAC5B,MAAM,SAAS,OAAO,SAAS,KAAK,OAAO,QAAQ,WAAW,GAAG,OAAO,MAAM;GAC9E,IAAI,OAAO,OAAO,MAAM,GAAG;IACzB,OAAO,YAAY,SAAS;IAC5B,OAAO,OAAO,MAAM,YAAY;GAClC;EACF,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;EACrB,cAAc,SAAS,MAAM,aAAa;EAC1C,aAAa;CACf;AACF,CAAC;AAEH,MAAM,oBACJ,KACA,YACA,cAEA,OAAO,IAAI,aAAa;CACtB,UAAU,SAAS,KAAK,UAAU;CAClC,MAAM,gBAAgB,OAAO,SAAS,KAA8B;CACpE,MAAM,YAAY,OAAO,IAAI,KAAoB,UAAU;CAE3D,MAAM,YAAY,OAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,WAAW,kBAAkB,SAAS;EAC5D,OAAO,IAAI,IAAI,WAAW,OAAO;EACjC,OAAO,SAAS,QAAQ,eAAe,MAAS,CAAC,CAAC,KAAK,OAAO,MAAM;EACpE,UAAU,SAAS,KAAK,SAAS,QAAQ;CAC3C,CAAC;CAED,MAAM,YAAY,OAAO,IAAI,aAAa;EACxC,MAAM,gBAAgB,OAAO,IAAI,IAAI,SAAS;EAC9C,IAAI,kBAAkB,WAAW,kBAAkB,SAAS;EAC5D,OAAO,IAAI,IAAI,WAAW,OAAO;EACjC,OAAO,SAAS,KACd,eACA,IAAI,kBAAkB;GACpB,WAAW;GACX,QAAQ,UAAU,IAAI;EACxB,CAAC,CACH,CAAC,CAAC,KAAK,OAAO,MAAM;EACpB,UAAU,SAAS,KAAK,SAAS,aAAa;CAChD,CAAC;CAED,MAAM,UAAU,WAAW,IAAI,QAAQ,OAAO,EAAE;CAChD,MAAM,cAAc,GAAG,QAAQ;CAC/B,MAAM,WAAW,GAAG,UAAU,WAAW;CACzC,MAAM,WAAW,WAAW,kBAAkB,YAAY,GAAG,QAAQ,WAAW;CAEhF,OAAO,OAAO,WACZ,OAAO,IAAI,aAAa;EACtB,MAAM,iBAAiB,OAAO,IAAI,aAAa;GAC7C,MAAM,SAAS,OAAO,IAAI,IAAI,SAAS;GACvC,IAAI,WAAW,WAAW,WAAW,SAAS,OAAO;GAGrD,IAAI,OADc,YAAY,UAAU,uBAAuB,GACvD;IACN,OAAO;IACP,OAAO;GACT;GAGA,IAAI,OADsB,YAAY,UAAU,uBAAuB,GACvD;IACd,OAAO;IACP,OAAO;GACT;GACA,OAAO;EACT,CAAC;EAWD,IAAI,OAViB,OAAO,OAAO,gBAAgB;GACjD,UAAU,SAAS,IAAI,CACrB,SAAS,YAAY,GAAG,gCAAgC,UAAU,GAAG,GACrE,SAAS,OAAO,GAAG,4BAA4B,QAAQ,CACzD,CAAC;GACD,QAAQ,SAAS;EACnB,CAAC,CAAC,CAAC,KACD,OAAO,QAAQ,GAAG,yBAAyB,QAAQ,GACnD,OAAO,SAAS,sBAAsB,OAAO,QAAQ,KAAK,CAAC,CAC7D,GACW;EAGX,KAAI,OADkB,IAAI,IAAI,SAAS,OACxB,SACb,OAAO;CAEX,CAAC,CACH;CAEA,OAAO;EACL,MAAM;EACN,KAAK;EACL,MAAM,OAAO,IAAI,aAAa;GAC5B,OAAO,IAAI,IAAI,WAAW,OAAO;GACjC,OAAO,SAAS,KACd,eACA,IAAI,kBAAkB;IAAE,WAAW;IAAuB,QAAQ;GAAS,CAAC,CAC9E,CAAC,CAAC,KAAK,OAAO,MAAM;EACtB,CAAC;EACD,cAAc,SAAS,MAAM,aAAa;EAC1C,aAAa,OAAO;CACtB;AACF,CAAC;AAEH,MAAa,kBAAkB,KAAa,WAA6B,iBACvE,OAAO,IAAI,aAAa;CAEtB,MAAM,cAAa,OADK,qBACG,CAAC,IAAI,GAAG;CAEnC,IAAI,CAAC,YAAY;EACf,UAAU,SAAS,KAAK,SAAS,QAAQ;EACzC,OAAO;GACL,MAAM;GACN,KAAK;GACL,MAAM,OAAO;GACb,cAAc,OAAO;GACrB,aAAa,OAAO;EACtB;CACF;CAEA,IAAI,QAAQ,UAAU,WAAW,WAAW,UAC1C,OAAO,OAAO,gBAAgB,YAAY,SAAS;CAGrD,IAAI,WAAW,WAAW,YAAY,CAAC,WAAW,WAChD,OAAO,OAAO,iBAAiB,KAAK,YAAY,SAAS;CAG3D,MAAM,qBAAqB,eAAe;EAAE,GAAG;EAAY,MAAM;CAAa,IAAI;CAElF,OAAO,OAAO,gBAAgB,oBAAoB,SAAS;AAC7D,CAAC;AAEH,SAAgB,iBACd,UACA,UACA,cACgB;CAChB,OAAO,SAAS,KAAK,QAAQ;EAC3B,MAAM,aAAa,SAAS,IAAI,GAAG;EACnC,OAAO;GACL,MAAM;GACN,QAAQ;GACR,MACE,gBAAgB,QAAQ,SACpB,eACC,YAAY,QAAQ,YAAY,eAAe;GACtD,QAAQ,YAAY;GACpB,QAAQ,YAAY;EACtB;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"orchestrator.mjs","names":[],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { Readable } from \"node:stream\";\nimport { Data, Deferred, Effect, Option, Ref, Schedule, Schema, Stream } from \"effect\";\nimport { stripAnsi } from \"./dev-log-pipeline\";\nimport { ShellEnv } from \"./env/project-env\";\nimport { loadRemoteModule, registerRemote } from \"./federation\";\nimport { fetchRaw } from \"./http-client\";\nimport {\n DevGeneratedEnv,\n DevRuntimeConfig,\n type ServiceDescriptor,\n ServiceDescriptorMap,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[Orchestrator] Unhandled rejection:\", reason);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[Orchestrator] Uncaught exception:\", err);\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>;\n waitForReady: Effect.Effect<void, OrchestratorError>;\n waitForExit: Effect.Effect<number, OrchestratorError>;\n}\n\nexport class OrchestratorError extends Data.TaggedError(\"OrchestratorError\")<{\n readonly operation: string;\n readonly detail: string;\n readonly cause?: unknown;\n}> {\n override get message() {\n return `${this.operation}: ${this.detail}`;\n }\n}\n\nconst omitUndefined = (value: unknown): unknown => {\n if (Array.isArray(value)) {\n return value.map((item) => (item === undefined ? null : omitUndefined(item)));\n }\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, omitUndefined(item)]),\n );\n }\n return value;\n};\n\nexport const encodeRuntimeConfig = (runtimeConfig: unknown) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Json))(omitUndefined(runtimeConfig)).pipe(\n Effect.mapError(\n (cause) =>\n new OrchestratorError({\n operation: \"serialize runtime config\",\n detail: cause.message,\n cause,\n }),\n ),\n );\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\nexport interface ProcessState {\n name: string;\n status: ProcessStatus;\n port: number;\n message?: string;\n source?: \"local\" | \"remote\";\n uiPort?: number;\n}\n\nconst probeHttpOk = (url: string, timeoutMs = 400) =>\n Effect.tryPromise({\n try: async () => {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n return res.ok;\n } catch {\n return false;\n }\n },\n catch: () => false,\n });\n\nconst LOCAL_PROBE_DEADLINE_MS = 90_000;\n\n/** Remote-host boot budgets: every stage of the CDN-only boot is deadline-\n * bounded so a hung connection or a wedged module load fails loud with the\n * URL and stage — long before the smoke's 240s probe deadline turns the\n * silence into a mystery. */\nconst MANIFEST_FETCH_DEADLINE = \"10 seconds\";\nconst LOAD_REMOTE_DEADLINE = \"60 seconds\";\nconst SERVER_READY_DEADLINE = \"120 seconds\";\nconst REMOTE_HOST_BOOT_DEADLINE = \"180 seconds\";\nconst LOCAL_PROBE_INTERVAL_MS = 200;\n\nconst cleanExitSignals: Record<string, true> = { SIGTERM: true, SIGINT: true };\n\nconst REMOTE_PROBE_TIMEOUT_MS = 5000;\nconst REMOTE_PROBE_DEADLINE_MS = 60_000;\nconst REMOTE_PROBE_BACKOFF_INITIAL_MS = 1000;\nconst REMOTE_PROBE_BACKOFF_MAX_MS = 15_000;\n\nexport const detectStatus = (\n line: string,\n descriptor: ServiceDescriptor,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n const errorPatterns = descriptor.errorPatterns ?? [];\n const readyPatterns = descriptor.readyPatterns ?? [];\n for (const pattern of readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n for (const pattern of errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n return null;\n};\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n port?: number;\n env?: Record<string, string>;\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[], isError = false): string => {\n return args\n .map((arg) => {\n if (arg instanceof Error) {\n const parts = [`${arg.name}: ${arg.message}`];\n if (arg.cause instanceof Error)\n parts.push(`(cause: ${arg.cause.name}: ${arg.cause.message})`);\n else if (arg.cause) {\n const cause = arg.cause;\n parts.push(\n `(cause: ${cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : (JSON.stringify(cause) ?? \"[Unserializable cause]\")})`,\n );\n }\n if (isError && arg.stack) parts.push(arg.stack);\n return parts.join(\"\\n\");\n }\n if (arg === null) return \"null\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"bigint\" || typeof arg === \"boolean\")\n return `${arg}`;\n if (typeof arg === \"symbol\") return arg.description ?? \"\";\n if (typeof arg === \"undefined\") return \"undefined\";\n return JSON.stringify(arg, null, 2) ?? \"[Unserializable value]\";\n })\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), 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 class HostRemoteUrlMissing extends Data.TaggedError(\"HostRemoteUrlMissing\")<\n Record<never, never>\n> {\n override get message() {\n return \"remoteUrl not provided on host descriptor\";\n }\n}\n\nexport class HostModuleInvalid extends Data.TaggedError(\"HostModuleInvalid\")<Record<never, never>> {\n override get message() {\n return \"Host module does not export runServer function\";\n }\n}\n\nexport class LocalPathMissing extends Data.TaggedError(\"LocalPathMissing\")<{ key: string }> {\n get message() {\n return `No localPath for local service: ${this.key}`;\n }\n}\n\nconst spawnRemoteHost = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n const remoteUrl = descriptor.remoteUrl;\n if (!remoteUrl) {\n return yield* new HostRemoteUrlMissing();\n }\n\n callbacks.onStatus(descriptor.key, \"starting\");\n callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(descriptor.key, callbacks);\n callbacks.onLog(descriptor.key, \"Loading Module Federation runtime...\");\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n // The manifest IS the entry contract (ADR 0020 amendment: hashed\n // entrypoints, fixed-name `remoteEntry.js` retired — it 404s on the CDN).\n // A failed manifest fetch must fail loud with the URL and status: the old\n // silent fallback to remoteEntry.js turned any transient hiccup (a CDN\n // 403 challenge, a timeout) into a guaranteed loadRemote failure with no\n // named cause.\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n let res: Response;\n try {\n res = await fetchRaw(manifestUrl, undefined, MANIFEST_FETCH_DEADLINE);\n } catch (e) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${e instanceof Error ? e.message : String(e)}`,\n cause: e,\n });\n }\n if (!res.ok) {\n throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : \"\"}`,\n });\n }\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 throw new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — not a Module Federation manifest (missing metaData/exposes/shared)`,\n });\n }\n return manifestUrl;\n },\n catch: (cause) =>\n cause instanceof OrchestratorError\n ? cause\n : new OrchestratorError({\n operation: \"fetch host manifest\",\n detail: `${manifestUrl} — ${String(cause)}`,\n }),\n });\n\n yield* Effect.promise(() => registerRemote({ name: \"host\", entry: entryUrl }));\n callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n loadRemoteModule<{\n runServer: (input: ServerInput) => ServerHandle;\n }>(\"host/Server\"),\n catch: (cause) =>\n new OrchestratorError({\n operation: \"load host module\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.timeoutOrElse({\n duration: LOAD_REMOTE_DEADLINE,\n orElse: () =>\n Effect.fail(\n new OrchestratorError({\n operation: \"load host module\",\n detail: `timed out after ${LOAD_REMOTE_DEADLINE} — the module (or its shared dependencies) did not finish loading from ${entryUrl}`,\n }),\n ),\n }),\n );\n\n if (!hostModule?.runServer) {\n return yield* new HostModuleInvalid();\n }\n\n callbacks.onLog(descriptor.key, \"Starting server...\");\n const hostPort = runtimeConfig.host?.port;\n const hostEnv: Record<string, string> | undefined = hostPort\n ? { PORT: String(hostPort) }\n : undefined;\n const serverHandle = hostModule.runServer({\n config: runtimeConfig,\n port: hostPort,\n env: hostEnv,\n });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (cause) =>\n new OrchestratorError({\n operation: \"start server\",\n detail: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.timeoutOrElse({\n duration: SERVER_READY_DEADLINE,\n // A half-started server must not leak its port on the deadline path —\n // the success path hands shutdown to the process handle instead.\n orElse: () =>\n Effect.gen(function* () {\n yield* Effect.exit(Effect.promise(() => serverHandle.shutdown()));\n return yield* new OrchestratorError({\n operation: \"start server\",\n detail: `server did not become ready within ${SERVER_READY_DEADLINE}`,\n });\n }),\n }),\n );\n\n callbacks.onStatus(descriptor.key, \"ready\");\n\n return {\n name: descriptor.key,\n pid: undefined,\n kill: Effect.gen(function* () {\n callbacks.onLog(descriptor.key, \"Shutting down remote host...\");\n restoreConsole();\n yield* Effect.tryPromise({\n try: () => serverHandle.shutdown(),\n catch: () => {},\n }).pipe(Effect.ignore);\n }),\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\n/**\n * Spawn env precedence, three tiers: values explicitly exported by the\n * caller (shell / CI / regression harness — captured by the bootstrap\n * program into the `ShellEnv` service before any `.env` loading) outrank the\n * generated infra env, which outranks `.env`-file values inherited through\n * `processEnv`. The service's resolved port is always authoritative.\n */\nexport function composeSpawnEnv(\n processEnv: Record<string, string>,\n generatedEnv: Record<string, string>,\n port: number,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n return {\n ...processEnv,\n ...mergeGeneratedOverFileEnv(generatedEnv, processEnv, shellEnv),\n FORCE_COLOR: \"1\",\n ...(port > 0 ? { PORT: String(port) } : {}),\n };\n}\n\n/**\n * Overlay the generated infra env (ports drift, so stale `.env` values must\n * lose) while keeping every explicitly exported key from `shellEnv` intact.\n * Keys absent from both are untouched.\n *\n * Exception (ADR 0012 / plan 038): the origin keys BASE_URL and CORS_ORIGIN\n * are always generated-owned — a wrapper that sourced a stale `.env` must not\n * win over the resolved host port, in the child env or on disk.\n */\nconst GENERATED_OWNED_KEYS = new Set([\"BASE_URL\", \"CORS_ORIGIN\"]);\n\nexport function mergeGeneratedOverFileEnv(\n generatedEnv: Record<string, string>,\n processEnv: Record<string, string>,\n shellEnv: Record<string, string> = {},\n): Record<string, string> {\n const result: Record<string, string> = { ...processEnv };\n for (const [key, value] of Object.entries(generatedEnv)) {\n if (!GENERATED_OWNED_KEYS.has(key) && key in shellEnv) {\n result[key] = shellEnv[key]!;\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nconst spawnDevProcess = (descriptor: ServiceDescriptor, callbacks: ProcessCallbacks) =>\n Effect.gen(function* () {\n const runtimeConfig = yield* DevRuntimeConfig;\n\n if (!descriptor.localPath) {\n return yield* new LocalPathMissing({ key: descriptor.key });\n }\n\n const fullCwd = descriptor.localPath;\n const command = descriptor.command ?? \"pnpm\";\n const args = descriptor.args ?? [\"run\", \"dev\"];\n const port = descriptor.port ?? descriptor.defaultPort;\n const name = descriptor.key;\n\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(name, \"starting\");\n\n const generatedEnv = yield* DevGeneratedEnv;\n const shellTier = yield* ShellEnv;\n // The descriptor's env joins the generated tier — folding it in before\n // composeSpawnEnv keeps the documented precedence (shell > generated >\n // .env-file); assigning after would let it outrank the shell tier (and\n // the generated-owned keys) silently.\n const envVars = composeSpawnEnv(\n process.env as Record<string, string>,\n { ...generatedEnv, ...descriptor.env },\n port,\n shellTier,\n );\n\n envVars.BOS_RUNTIME_CONFIG = yield* encodeRuntimeConfig(runtimeConfig);\n\n const cmd = spawn(command, args, {\n cwd: fullCwd,\n env: envVars,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n });\n\n let lastExit: { code: number | null; signal: NodeJS.Signals | null } | null = null;\n const exitCode = Effect.callback<number, OrchestratorError>((resume) => {\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n lastExit = { code, signal };\n resume(Effect.succeed(code ?? (signal ? 1 : 0)));\n };\n const onError = (err: Error) => {\n callbacks.onLog(name, `Spawn failed: ${err.message}`, true);\n callbacks.onStatus(name, \"error\", `spawn failed: ${err.message}`);\n resume(\n Effect.fail(\n new OrchestratorError({\n operation: \"spawn process\",\n detail: err.message,\n cause: err,\n }),\n ),\n );\n };\n cmd.once(\"exit\", onExit);\n cmd.once(\"error\", onError);\n return Effect.sync(() => {\n cmd.off(\"exit\", onExit);\n cmd.off(\"error\", onError);\n });\n });\n\n const describeExit = (exitCodeValue: number): string => {\n if (lastExit?.code === null && lastExit.signal) return `signal: ${lastExit.signal}`;\n return `exit code: ${exitCodeValue}`;\n };\n const isCleanSignalExit = (): boolean =>\n lastExit?.code === null && lastExit.signal != null && lastExit.signal in cleanExitSignals;\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(name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n const markError = (message: string) =>\n Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"wait for process readiness\", detail: message }),\n ).pipe(Effect.ignore);\n });\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessPath = descriptor.readinessPath;\n const url = `http://127.0.0.1:${port}${readinessPath}`;\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n if (port <= 0) return false;\n const ok = yield* probeHttpOk(url);\n if (ok) yield* markReady;\n return ok;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.spaced(`${port > 0 ? LOCAL_PROBE_INTERVAL_MS : 500} millis`),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${LOCAL_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\" && status !== \"error\") {\n callbacks.onLog(name, \"Probe deadline exceeded after 90s\", true);\n yield* markError(`Probe deadline exceeded: ${name}`);\n }\n }),\n );\n\n const pid = cmd.pid ?? undefined;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const exitCodeValue = yield* exitCode;\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") {\n // Post-ready exits must stay visible — a silently dead child (OOM\n // kill included) used to leave the stack answering with nothing.\n // A SIGTERM/SIGINT-signalled exit is the polite-quit path, not a\n // crash, so it logs as a plain shutdown line.\n if (currentStatus === \"ready\") {\n const detail = describeExit(exitCodeValue);\n callbacks.onLog(name, `Process exited after ready (${detail})`, !isCleanSignalExit());\n if (!isCleanSignalExit()) {\n callbacks.onStatus(name, \"error\", `exited after ready (${detail})`);\n }\n yield* markError(`Process exited after ready: ${name}`);\n }\n return;\n }\n callbacks.onLog(\n name,\n `Process exited before ready (${describeExit(exitCodeValue)})`,\n !isCleanSignalExit(),\n );\n yield* markError(`Process exited before ready: ${name}`);\n }),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n const cleanLine = stripAnsi(line);\n const looksLikeError =\n isStderr &&\n /^(error|fail|fatal|exception|unhandled|reject)/i.test(cleanLine) &&\n !cleanLine.startsWith(\"$\");\n callbacks.onLog(name, line, looksLikeError);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, descriptor);\n if (detected) {\n if (detected.status === \"ready\") {\n yield* markReady;\n } else if (currentStatus !== \"error\") {\n yield* markError(`Process failed: ${name}`);\n }\n }\n });\n\n const stdoutStream = cmd.stdout\n ? (Readable.toWeb(cmd.stdout) as unknown as ReadableStream<Uint8Array>)\n : null;\n const stderrStream = cmd.stderr\n ? (Readable.toWeb(cmd.stderr) as unknown as ReadableStream<Uint8Array>)\n : null;\n\n if (stdoutStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, false))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stdoutStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stdout\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n if (stderrStream) {\n yield* Effect.forkScoped(\n Stream.runForEach((line: string) => handleLine(line, true))(\n Stream.splitLines(\n Stream.decodeText(\n Stream.fromReadableStream({\n evaluate: () => stderrStream,\n onError: (cause) =>\n new OrchestratorError({\n operation: \"read process stderr\",\n detail: String(cause),\n cause,\n }),\n }),\n ),\n ),\n ),\n );\n }\n\n return {\n name,\n pid,\n kill: Effect.gen(function* () {\n const groupPid = pid;\n const groupSignal = (signal: NodeJS.Signals) =>\n Effect.try(() => {\n if (groupPid !== undefined) process.kill(-groupPid, signal);\n }).pipe(Effect.ignore);\n yield* groupSignal(\"SIGTERM\");\n const exited = yield* exitCode.pipe(Effect.timeout(\"3 seconds\"), Effect.option);\n if (Option.isNone(exited)) {\n yield* groupSignal(\"SIGKILL\");\n yield* Effect.sleep(\"250 millis\");\n }\n }).pipe(Effect.ignore),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: exitCode,\n } satisfies ProcessHandle;\n });\n\nconst spawnRemoteProbe = (\n pkg: string,\n descriptor: ServiceDescriptor,\n callbacks: ProcessCallbacks,\n) =>\n Effect.gen(function* () {\n callbacks.onStatus(pkg, \"starting\");\n const readyDeferred = yield* Deferred.make<void, OrchestratorError>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\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 yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"ready\", \"loaded\");\n });\n\n const markError = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({\n operation: \"probe remote process\",\n detail: `Remote ${pkg} unreachable`,\n }),\n ).pipe(Effect.ignore);\n callbacks.onStatus(pkg, \"error\", \"unreachable\");\n });\n\n const baseUrl = descriptor.url.replace(/\\/$/, \"\");\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n const entryUrl = `${baseUrl}${descriptor.readinessPath}`;\n const probeUrl = descriptor.readinessPath === \"/health\" ? `${baseUrl}/health` : manifestUrl;\n\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n const readinessCheck = Effect.gen(function* () {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return true;\n\n const ok = yield* probeHttpOk(probeUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (ok) {\n yield* markReady;\n return true;\n }\n\n const fallbackOk = yield* probeHttpOk(entryUrl, REMOTE_PROBE_TIMEOUT_MS);\n if (fallbackOk) {\n yield* markReady;\n return true;\n }\n return false;\n });\n const ready = yield* Effect.repeat(readinessCheck, {\n schedule: Schedule.min([\n Schedule.exponential(`${REMOTE_PROBE_BACKOFF_INITIAL_MS} millis`, 1.5),\n Schedule.spaced(`${REMOTE_PROBE_BACKOFF_MAX_MS} millis`),\n ]),\n until: (done) => done,\n }).pipe(\n Effect.timeout(`${REMOTE_PROBE_DEADLINE_MS} millis`),\n Effect.catchTag(\"TimeoutError\", () => Effect.succeed(false)),\n );\n if (ready) return;\n\n const status = yield* Ref.get(statusRef);\n if (status !== \"ready\") {\n yield* markError;\n }\n }),\n );\n\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.gen(function* () {\n yield* Ref.set(statusRef, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new OrchestratorError({ operation: \"stop remote process\", detail: \"Killed\" }),\n ).pipe(Effect.ignore);\n }),\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const makeDevProcess = (pkg: string, callbacks: ProcessCallbacks, portOverride?: number) =>\n Effect.gen(function* () {\n const services = yield* ServiceDescriptorMap;\n const descriptor = services.get(pkg);\n\n if (!descriptor) {\n callbacks.onStatus(pkg, \"ready\", \"Remote\");\n return {\n name: pkg,\n pid: undefined,\n kill: Effect.void,\n waitForReady: Effect.void,\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n }\n\n if (pkg === \"host\" && descriptor.source === \"remote\") {\n return yield* spawnRemoteHost(descriptor, callbacks).pipe(\n // Overall boot budget: with per-stage deadlines inside, this is the\n // backstop for anything the stage deadlines don't cover (a config\n // fetch, a slow MF internal) — the boot either comes up named-and-\n // ready or fails named-and-loud.\n Effect.timeoutOrElse({\n duration: REMOTE_HOST_BOOT_DEADLINE,\n orElse: () =>\n Effect.fail(\n new OrchestratorError({\n operation: \"boot remote host\",\n detail: `remote host boot exceeded the ${REMOTE_HOST_BOOT_DEADLINE} overall deadline`,\n }),\n ),\n }),\n );\n }\n\n if (descriptor.source === \"remote\" || !descriptor.localPath) {\n return yield* spawnRemoteProbe(pkg, descriptor, callbacks);\n }\n\n const resolvedDescriptor = portOverride ? { ...descriptor, port: portOverride } : descriptor;\n\n return yield* spawnDevProcess(resolvedDescriptor, callbacks);\n });\n\nexport function getProcessStates(\n packages: string[],\n services: Map<string, ServiceDescriptor>,\n portOverride?: number,\n): ProcessState[] {\n return packages.map((pkg) => {\n const descriptor = services.get(pkg);\n return {\n name: pkg,\n status: \"pending\" as const,\n port:\n portOverride && pkg === \"host\"\n ? portOverride\n : (descriptor?.port ?? descriptor?.defaultPort ?? 0),\n source: descriptor?.source,\n uiPort: descriptor?.uiPort,\n };\n });\n}\n"],"mappings":"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"}
package/dist/plugin.cjs CHANGED
@@ -16,6 +16,7 @@ const require_init = require('./commands/init.cjs');
16
16
  const require_keys = require('./commands/keys.cjs');
17
17
  const require_ops = require('./commands/ops.cjs');
18
18
  const require_plugins = require('./commands/plugins.cjs');
19
+ const require_smoke = require('./commands/smoke.cjs');
19
20
  const require_upgrade = require('./commands/upgrade.cjs');
20
21
  let effect = require("effect");
21
22
  let every_plugin = require("every-plugin");
@@ -58,6 +59,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
58
59
  ...require_dev.registerDev(builder),
59
60
  ...require_build.registerBuild(builder),
60
61
  ...require_deploy.registerDeploy(builder),
62
+ ...require_smoke.registerSmoke(builder),
61
63
  ...require_keys.registerKeys(builder),
62
64
  ...require_init.registerInit(builder),
63
65
  ...require_upgrade.registerUpgrade(builder),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs","names":["createPlugin","z","bosContract","Effect","openResolution","buildScoped","ProjectEnv","ProjectEnvLive","process","buildScopedContext","Layer","makeDatabaseBindings","makeDrizzleKitLive","p","BosDepsTag","Context","DatabaseBindings","DrizzleKit","registerConfig","registerPlugins","registerDev","registerBuild","registerDeploy","registerKeys","registerInit","registerUpgrade","registerDb","registerOps"],"sources":["../src/plugin.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport { Context, Effect, Layer } from \"effect\";\nimport { buildScoped, buildScopedContext } from \"every-plugin\";\nimport { registerBuild } from \"./commands/build\";\nimport { registerConfig } from \"./commands/config\";\nimport { registerDb } from \"./commands/db\";\nimport { registerDeploy } from \"./commands/deploy\";\nimport { registerDev } from \"./commands/dev\";\nimport { registerInit } from \"./commands/init\";\nimport { registerKeys } from \"./commands/keys\";\nimport { registerOps } from \"./commands/ops\";\nimport { registerPlugins } from \"./commands/plugins\";\nimport { type BosDeps, BosDepsTag } from \"./commands/shared\";\nimport { registerUpgrade } from \"./commands/upgrade\";\nimport { bosContract } from \"./contract\";\nimport { DatabaseBindings, DrizzleKit, makeDatabaseBindings, makeDrizzleKitLive } from \"./db\";\nimport { ProjectEnv, ProjectEnvLive } from \"./env/project-env\";\nimport { openResolution } from \"./resolution/session\";\nimport { createPlugin, z } from \"./sdk\";\n\nexport { resolveRemoteConfigChain } from \"./commands/config\";\nexport type { DevSessionData, StartSummary } from \"./dev-program\";\nexport { type ProgressEvent, pluginEvents } from \"./progress\";\n\nexport default createPlugin({\n variables: z.object({\n configPath: z.string().optional(),\n // The artifact root (cwd-derived) — decoupled from configPath so an\n // explicit boot config (--config-path fixture) validates and loads\n // without redirecting where the CLI writes generated artifacts.\n configDir: z.string().optional(),\n }),\n secrets: z.object({}),\n contract: bosContract,\n initialize: (config, _plugins) =>\n Effect.gen(function* () {\n const session = yield* Effect.promise(() =>\n openResolution({ path: config.variables.configPath }),\n );\n\n const projectEnv = yield* buildScoped(ProjectEnv, ProjectEnvLive);\n const effectContext = yield* Effect.context();\n\n const configDir = config.variables.configDir ?? session?.root ?? process.cwd();\n\n const services = yield* buildScopedContext(\n Layer.mergeAll(\n makeDatabaseBindings({\n projectDir: configDir,\n loadRuntimeConfig: async () => (await session?.buildRuntime()) ?? null,\n loadEnv: () => Effect.runPromiseWith(effectContext)(projectEnv.load(configDir)),\n }),\n makeDrizzleKitLive({\n projectDir: configDir,\n onLog: (message) => p.log.info(message),\n }),\n ),\n );\n\n return Layer.succeed(BosDepsTag, {\n session,\n databaseBindings: Context.get(services, DatabaseBindings),\n drizzleKit: Context.get(services, DrizzleKit),\n } satisfies BosDeps);\n }),\n createRouter: (builder) => ({\n ...registerConfig(builder),\n ...registerPlugins(builder),\n ...registerDev(builder),\n ...registerBuild(builder),\n ...registerDeploy(builder),\n ...registerKeys(builder),\n ...registerInit(builder),\n ...registerUpgrade(builder),\n ...registerDb(builder),\n ...registerOps(builder),\n }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,yBAAeA,2BAAa;CAC1B,WAAWC,MAAE,OAAO;EAClB,YAAYA,MAAE,OAAO,CAAC,CAAC,SAAS;EAIhC,WAAWA,MAAE,OAAO,CAAC,CAAC,SAAS;CACjC,CAAC;CACD,SAASA,MAAE,OAAO,CAAC,CAAC;CACpB,UAAUC;CACV,aAAa,QAAQ,aACnBC,cAAO,IAAI,aAAa;EACtB,MAAM,UAAU,OAAOA,cAAO,cAC5BC,0CAAe,EAAE,MAAM,OAAO,UAAU,WAAW,CAAC,CACtD;EAEA,MAAM,aAAa,WAAOC,0BAAYC,gCAAYC,kCAAc;EAChE,MAAM,gBAAgB,OAAOJ,cAAO,QAAQ;EAE5C,MAAM,YAAY,OAAO,UAAU,aAAa,SAAS,QAAQK,qBAAQ,IAAI;EAE7E,MAAM,WAAW,WAAOC,iCACtBC,aAAM,SACJC,sCAAqB;GACnB,YAAY;GACZ,mBAAmB,YAAa,MAAM,SAAS,aAAa,KAAM;GAClE,eAAeR,cAAO,eAAe,aAAa,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC;EAChF,CAAC,GACDS,uCAAmB;GACjB,YAAY;GACZ,QAAQ,YAAYC,eAAE,IAAI,KAAK,OAAO;EACxC,CAAC,CACH,CACF;EAEA,OAAOH,aAAM,QAAQI,2BAAY;GAC/B;GACA,kBAAkBC,eAAQ,IAAI,UAAUC,iCAAgB;GACxD,YAAYD,eAAQ,IAAI,UAAUE,8BAAU;EAC9C,CAAmB;CACrB,CAAC;CACH,eAAe,aAAa;EAC1B,GAAGC,8BAAe,OAAO;EACzB,GAAGC,gCAAgB,OAAO;EAC1B,GAAGC,wBAAY,OAAO;EACtB,GAAGC,4BAAc,OAAO;EACxB,GAAGC,8BAAe,OAAO;EACzB,GAAGC,0BAAa,OAAO;EACvB,GAAGC,0BAAa,OAAO;EACvB,GAAGC,gCAAgB,OAAO;EAC1B,GAAGC,sBAAW,OAAO;EACrB,GAAGC,wBAAY,OAAO;CACxB;AACF,CAAC"}
1
+ {"version":3,"file":"plugin.cjs","names":["createPlugin","z","bosContract","Effect","openResolution","buildScoped","ProjectEnv","ProjectEnvLive","process","buildScopedContext","Layer","makeDatabaseBindings","makeDrizzleKitLive","p","BosDepsTag","Context","DatabaseBindings","DrizzleKit","registerConfig","registerPlugins","registerDev","registerBuild","registerDeploy","registerSmoke","registerKeys","registerInit","registerUpgrade","registerDb","registerOps"],"sources":["../src/plugin.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport { Context, Effect, Layer } from \"effect\";\nimport { buildScoped, buildScopedContext } from \"every-plugin\";\nimport { registerBuild } from \"./commands/build\";\nimport { registerConfig } from \"./commands/config\";\nimport { registerDb } from \"./commands/db\";\nimport { registerDeploy } from \"./commands/deploy\";\nimport { registerDev } from \"./commands/dev\";\nimport { registerInit } from \"./commands/init\";\nimport { registerKeys } from \"./commands/keys\";\nimport { registerOps } from \"./commands/ops\";\nimport { registerPlugins } from \"./commands/plugins\";\nimport { type BosDeps, BosDepsTag } from \"./commands/shared\";\nimport { registerSmoke } from \"./commands/smoke\";\nimport { registerUpgrade } from \"./commands/upgrade\";\nimport { bosContract } from \"./contract\";\nimport { DatabaseBindings, DrizzleKit, makeDatabaseBindings, makeDrizzleKitLive } from \"./db\";\nimport { ProjectEnv, ProjectEnvLive } from \"./env/project-env\";\nimport { openResolution } from \"./resolution/session\";\nimport { createPlugin, z } from \"./sdk\";\n\nexport { resolveRemoteConfigChain } from \"./commands/config\";\nexport type { DevSessionData, StartSummary } from \"./dev-program\";\nexport { type ProgressEvent, pluginEvents } from \"./progress\";\n\nexport default createPlugin({\n variables: z.object({\n configPath: z.string().optional(),\n // The artifact root (cwd-derived) — decoupled from configPath so an\n // explicit boot config (--config-path fixture) validates and loads\n // without redirecting where the CLI writes generated artifacts.\n configDir: z.string().optional(),\n }),\n secrets: z.object({}),\n contract: bosContract,\n initialize: (config, _plugins) =>\n Effect.gen(function* () {\n const session = yield* Effect.promise(() =>\n openResolution({ path: config.variables.configPath }),\n );\n\n const projectEnv = yield* buildScoped(ProjectEnv, ProjectEnvLive);\n const effectContext = yield* Effect.context();\n\n const configDir = config.variables.configDir ?? session?.root ?? process.cwd();\n\n const services = yield* buildScopedContext(\n Layer.mergeAll(\n makeDatabaseBindings({\n projectDir: configDir,\n loadRuntimeConfig: async () => (await session?.buildRuntime()) ?? null,\n loadEnv: () => Effect.runPromiseWith(effectContext)(projectEnv.load(configDir)),\n }),\n makeDrizzleKitLive({\n projectDir: configDir,\n onLog: (message) => p.log.info(message),\n }),\n ),\n );\n\n return Layer.succeed(BosDepsTag, {\n session,\n databaseBindings: Context.get(services, DatabaseBindings),\n drizzleKit: Context.get(services, DrizzleKit),\n } satisfies BosDeps);\n }),\n createRouter: (builder) => ({\n ...registerConfig(builder),\n ...registerPlugins(builder),\n ...registerDev(builder),\n ...registerBuild(builder),\n ...registerDeploy(builder),\n ...registerSmoke(builder),\n ...registerKeys(builder),\n ...registerInit(builder),\n ...registerUpgrade(builder),\n ...registerDb(builder),\n ...registerOps(builder),\n }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,yBAAeA,2BAAa;CAC1B,WAAWC,MAAE,OAAO;EAClB,YAAYA,MAAE,OAAO,CAAC,CAAC,SAAS;EAIhC,WAAWA,MAAE,OAAO,CAAC,CAAC,SAAS;CACjC,CAAC;CACD,SAASA,MAAE,OAAO,CAAC,CAAC;CACpB,UAAUC;CACV,aAAa,QAAQ,aACnBC,cAAO,IAAI,aAAa;EACtB,MAAM,UAAU,OAAOA,cAAO,cAC5BC,0CAAe,EAAE,MAAM,OAAO,UAAU,WAAW,CAAC,CACtD;EAEA,MAAM,aAAa,WAAOC,0BAAYC,gCAAYC,kCAAc;EAChE,MAAM,gBAAgB,OAAOJ,cAAO,QAAQ;EAE5C,MAAM,YAAY,OAAO,UAAU,aAAa,SAAS,QAAQK,qBAAQ,IAAI;EAE7E,MAAM,WAAW,WAAOC,iCACtBC,aAAM,SACJC,sCAAqB;GACnB,YAAY;GACZ,mBAAmB,YAAa,MAAM,SAAS,aAAa,KAAM;GAClE,eAAeR,cAAO,eAAe,aAAa,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC;EAChF,CAAC,GACDS,uCAAmB;GACjB,YAAY;GACZ,QAAQ,YAAYC,eAAE,IAAI,KAAK,OAAO;EACxC,CAAC,CACH,CACF;EAEA,OAAOH,aAAM,QAAQI,2BAAY;GAC/B;GACA,kBAAkBC,eAAQ,IAAI,UAAUC,iCAAgB;GACxD,YAAYD,eAAQ,IAAI,UAAUE,8BAAU;EAC9C,CAAmB;CACrB,CAAC;CACH,eAAe,aAAa;EAC1B,GAAGC,8BAAe,OAAO;EACzB,GAAGC,gCAAgB,OAAO;EAC1B,GAAGC,wBAAY,OAAO;EACtB,GAAGC,4BAAc,OAAO;EACxB,GAAGC,8BAAe,OAAO;EACzB,GAAGC,4BAAc,OAAO;EACxB,GAAGC,0BAAa,OAAO;EACvB,GAAGC,0BAAa,OAAO;EACvB,GAAGC,gCAAgB,OAAO;EAC1B,GAAGC,sBAAW,OAAO;EACrB,GAAGC,wBAAY,OAAO;CACxB;AACF,CAAC"}