everything-dev 2.0.0-rc.5 → 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 (120) 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/infra.cjs +4 -2
  9. package/dist/cli/infra.cjs.map +1 -1
  10. package/dist/cli/infra.mjs +4 -2
  11. package/dist/cli/infra.mjs.map +1 -1
  12. package/dist/cli.cjs +2 -2
  13. package/dist/cli.cjs.map +1 -1
  14. package/dist/cli.mjs +1 -1
  15. package/dist/cli.mjs.map +1 -1
  16. package/dist/commands/deploy.cjs +111 -1
  17. package/dist/commands/deploy.cjs.map +1 -1
  18. package/dist/commands/deploy.mjs +112 -2
  19. package/dist/commands/deploy.mjs.map +1 -1
  20. package/dist/commands/smoke.cjs +41 -0
  21. package/dist/commands/smoke.cjs.map +1 -0
  22. package/dist/commands/smoke.mjs +41 -0
  23. package/dist/commands/smoke.mjs.map +1 -0
  24. package/dist/commands/upgrade.cjs +2 -2
  25. package/dist/commands/upgrade.cjs.map +1 -1
  26. package/dist/commands/upgrade.mjs +1 -1
  27. package/dist/commands/upgrade.mjs.map +1 -1
  28. package/dist/contract.cjs +27 -1
  29. package/dist/contract.cjs.map +1 -1
  30. package/dist/contract.d.cts +65 -1
  31. package/dist/contract.d.mts +65 -1
  32. package/dist/contract.meta.cjs +13 -1
  33. package/dist/contract.meta.cjs.map +1 -1
  34. package/dist/contract.meta.d.cts +23 -1
  35. package/dist/contract.meta.d.mts +23 -1
  36. package/dist/contract.meta.mjs +13 -1
  37. package/dist/contract.meta.mjs.map +1 -1
  38. package/dist/contract.mjs +26 -2
  39. package/dist/contract.mjs.map +1 -1
  40. package/dist/dev-log-pipeline.cjs +6 -0
  41. package/dist/dev-log-pipeline.cjs.map +1 -1
  42. package/dist/dev-log-pipeline.mjs +6 -0
  43. package/dist/dev-log-pipeline.mjs.map +1 -1
  44. package/dist/dev-program.cjs +21 -5
  45. package/dist/dev-program.cjs.map +1 -1
  46. package/dist/dev-program.mjs +21 -6
  47. package/dist/dev-program.mjs.map +1 -1
  48. package/dist/dev-session.cjs +1 -0
  49. package/dist/dev-session.cjs.map +1 -1
  50. package/dist/dev-session.mjs +1 -0
  51. package/dist/dev-session.mjs.map +1 -1
  52. package/dist/fastkv.cjs +21 -3
  53. package/dist/fastkv.cjs.map +1 -1
  54. package/dist/fastkv.d.cts +14 -1
  55. package/dist/fastkv.d.mts +14 -1
  56. package/dist/fastkv.mjs +21 -5
  57. package/dist/fastkv.mjs.map +1 -1
  58. package/dist/{mf.cjs → federation.cjs} +6 -13
  59. package/dist/federation.cjs.map +1 -0
  60. package/dist/{mf.d.cts → federation.d.cts} +2 -2
  61. package/dist/{mf.d.mts → federation.d.mts} +2 -2
  62. package/dist/{mf.mjs → federation.mjs} +6 -13
  63. package/dist/federation.mjs.map +1 -0
  64. package/dist/http-client.cjs +70 -53
  65. package/dist/http-client.cjs.map +1 -1
  66. package/dist/http-client.mjs +70 -54
  67. package/dist/http-client.mjs.map +1 -1
  68. package/dist/image-deploy.cjs +9 -0
  69. package/dist/image-deploy.cjs.map +1 -1
  70. package/dist/image-deploy.mjs +9 -1
  71. package/dist/image-deploy.mjs.map +1 -1
  72. package/dist/index.cjs +4 -0
  73. package/dist/index.d.cts +3 -3
  74. package/dist/index.d.mts +3 -3
  75. package/dist/index.mjs +3 -3
  76. package/dist/orchestrator.cjs +60 -52
  77. package/dist/orchestrator.cjs.map +1 -1
  78. package/dist/orchestrator.mjs +60 -52
  79. package/dist/orchestrator.mjs.map +1 -1
  80. package/dist/plugin.cjs +2 -0
  81. package/dist/plugin.cjs.map +1 -1
  82. package/dist/plugin.d.cts +24 -0
  83. package/dist/plugin.d.mts +24 -0
  84. package/dist/plugin.mjs +2 -0
  85. package/dist/plugin.mjs.map +1 -1
  86. package/dist/process-registry.cjs +1 -1
  87. package/dist/process-registry.mjs +1 -1
  88. package/dist/publish.cjs +3 -3
  89. package/dist/publish.cjs.map +1 -1
  90. package/dist/publish.mjs +4 -4
  91. package/dist/publish.mjs.map +1 -1
  92. package/dist/resolver.cjs +293 -0
  93. package/dist/resolver.cjs.map +1 -0
  94. package/dist/resolver.d.cts +99 -0
  95. package/dist/resolver.d.mts +99 -0
  96. package/dist/resolver.mjs +284 -0
  97. package/dist/resolver.mjs.map +1 -0
  98. package/dist/smoke.cjs +262 -0
  99. package/dist/smoke.cjs.map +1 -0
  100. package/dist/smoke.mjs +260 -0
  101. package/dist/smoke.mjs.map +1 -0
  102. package/dist/version-manifest-resolve.cjs +3 -3
  103. package/dist/version-manifest-resolve.cjs.map +1 -1
  104. package/dist/version-manifest-resolve.mjs +1 -1
  105. package/dist/version-manifest-resolve.mjs.map +1 -1
  106. package/dist/workspace.cjs +1 -1
  107. package/dist/workspace.mjs +1 -1
  108. package/package.json +9 -9
  109. package/dist/bundle-fs-resolve.cjs +0 -201
  110. package/dist/bundle-fs-resolve.cjs.map +0 -1
  111. package/dist/bundle-fs-resolve.d.cts +0 -82
  112. package/dist/bundle-fs-resolve.d.mts +0 -82
  113. package/dist/bundle-fs-resolve.mjs +0 -194
  114. package/dist/bundle-fs-resolve.mjs.map +0 -1
  115. package/dist/bundle-path.cjs +0 -48
  116. package/dist/bundle-path.cjs.map +0 -1
  117. package/dist/bundle-path.mjs +0 -45
  118. package/dist/bundle-path.mjs.map +0 -1
  119. package/dist/mf.cjs.map +0 -1
  120. 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 warnOutsideEffect = (...args: unknown[]): void => {\n console.warn(...args);\n};\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 remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n let res: Response;\n try {\n res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(10_000) });\n } catch {\n throw new Error(\"manifest fetch failed\");\n }\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch (e) {\n warnOutsideEffect(\n `[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${String(e)}`,\n );\n }\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\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,16 +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 warnOutsideEffect = (...args) => {
11
- console.warn(...args);
12
- };
13
- const runFetch = (url, init) => fetch(url, init);
14
11
  process.on("unhandledRejection", (reason) => {
15
12
  console.error("[Orchestrator] Unhandled rejection:", reason);
16
13
  });
@@ -35,7 +32,7 @@ const encodeRuntimeConfig = (runtimeConfig) => Schema.encodeUnknownEffect(Schema
35
32
  const probeHttpOk = (url, timeoutMs = 400) => Effect.tryPromise({
36
33
  try: async () => {
37
34
  try {
38
- return (await runFetch(url, { signal: AbortSignal.timeout(timeoutMs) })).ok;
35
+ return (await fetch(url, { signal: AbortSignal.timeout(timeoutMs) })).ok;
39
36
  } catch {
40
37
  return false;
41
38
  }
@@ -43,6 +40,14 @@ const probeHttpOk = (url, timeoutMs = 400) => Effect.tryPromise({
43
40
  catch: () => false
44
41
  });
45
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";
46
51
  const LOCAL_PROBE_INTERVAL_MS = 200;
47
52
  const cleanExitSignals = {
48
53
  SIGTERM: true,
@@ -133,66 +138,54 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
133
138
  callbacks.onLog(descriptor.key, `Remote: ${remoteUrl}`);
134
139
  const restoreConsole = patchConsole(descriptor.key, callbacks);
135
140
  callbacks.onLog(descriptor.key, "Loading Module Federation runtime...");
136
- const mfRuntime = yield* Effect.tryPromise({
137
- try: () => import("@module-federation/enhanced/runtime"),
138
- catch: (cause) => new OrchestratorError({
139
- operation: "load module federation runtime",
140
- detail: cause instanceof Error ? cause.message : String(cause),
141
- cause
142
- })
143
- });
144
- const mfCore = yield* Effect.tryPromise({
145
- try: () => import("@module-federation/runtime-core"),
146
- catch: (cause) => new OrchestratorError({
147
- operation: "load module federation core",
148
- detail: cause instanceof Error ? cause.message : String(cause),
149
- cause
150
- })
151
- });
152
- let mf = mfRuntime.getInstance();
153
- if (!mf) {
154
- mf = mfRuntime.createInstance({
155
- name: "cli-host",
156
- remotes: []
157
- });
158
- mfCore.setGlobalFederationInstance(mf);
159
- }
160
- patchManifestFetchForSsrPublicPath(mf);
161
- const baseUrl = remoteUrl.replace(/\/remoteEntry\.js$/, "").replace(/\/mf-manifest\.json$/, "").replace(/\/$/, "");
162
- const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;
163
- const manifestUrl = `${baseUrl}/mf-manifest.json`;
141
+ const manifestUrl = `${remoteUrl.replace(/\/remoteEntry\.js$/, "").replace(/\/mf-manifest\.json$/, "").replace(/\/$/, "")}/mf-manifest.json`;
164
142
  const entryUrl = yield* Effect.tryPromise({
165
143
  try: async () => {
144
+ let res;
166
145
  try {
167
- let res;
168
- try {
169
- res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(1e4) });
170
- } catch {
171
- throw new Error("manifest fetch failed");
172
- }
173
- if (!res.ok) return remoteEntryUrl;
174
- const json = await res.json();
175
- if (json && typeof json === "object" && "metaData" in json && "exposes" in json && "shared" in json) return manifestUrl;
146
+ res = await fetchRaw(manifestUrl, void 0, MANIFEST_FETCH_DEADLINE);
176
147
  } catch (e) {
177
- warnOutsideEffect(`[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${String(e)}`);
148
+ throw new OrchestratorError({
149
+ operation: "fetch host manifest",
150
+ detail: `${manifestUrl} — ${e instanceof Error ? e.message : String(e)}`,
151
+ cause: e
152
+ });
178
153
  }
179
- return remoteEntryUrl;
154
+ if (!res.ok) throw new OrchestratorError({
155
+ operation: "fetch host manifest",
156
+ detail: `${manifestUrl} — HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : ""}`
157
+ });
158
+ const json = await res.json();
159
+ if (!json || typeof json !== "object" || !("metaData" in json) || !("exposes" in json) || !("shared" in json)) throw new OrchestratorError({
160
+ operation: "fetch host manifest",
161
+ detail: `${manifestUrl} — not a Module Federation manifest (missing metaData/exposes/shared)`
162
+ });
163
+ return manifestUrl;
180
164
  },
181
- catch: () => remoteEntryUrl
165
+ catch: (cause) => cause instanceof OrchestratorError ? cause : new OrchestratorError({
166
+ operation: "fetch host manifest",
167
+ detail: `${manifestUrl} — ${String(cause)}`
168
+ })
182
169
  });
183
- mf.registerRemotes([{
170
+ yield* Effect.promise(() => registerRemote({
184
171
  name: "host",
185
172
  entry: entryUrl
186
- }]);
173
+ }));
187
174
  callbacks.onLog(descriptor.key, `Loading host from ${entryUrl}...`);
188
175
  const hostModule = yield* Effect.tryPromise({
189
- try: () => mf.loadRemote("host/Server"),
176
+ try: () => loadRemoteModule("host/Server"),
190
177
  catch: (cause) => new OrchestratorError({
191
178
  operation: "load host module",
192
179
  detail: cause instanceof Error ? cause.message : String(cause),
193
180
  cause
194
181
  })
195
- });
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
+ }));
196
189
  if (!hostModule?.runServer) return yield* new HostModuleInvalid();
197
190
  callbacks.onLog(descriptor.key, "Starting server...");
198
191
  const hostPort = runtimeConfig.host?.port;
@@ -209,7 +202,16 @@ const spawnRemoteHost = (descriptor, callbacks) => Effect.gen(function* () {
209
202
  detail: cause instanceof Error ? cause.message : String(cause),
210
203
  cause
211
204
  })
212
- });
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
+ }));
213
215
  callbacks.onStatus(descriptor.key, "ready");
214
216
  return {
215
217
  name: descriptor.key,
@@ -490,7 +492,13 @@ const makeDevProcess = (pkg, callbacks, portOverride) => Effect.gen(function* ()
490
492
  waitForExit: Effect.never
491
493
  };
492
494
  }
493
- 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
+ }));
494
502
  if (descriptor.source === "remote" || !descriptor.localPath) return yield* spawnRemoteProbe(pkg, descriptor, callbacks);
495
503
  const resolvedDescriptor = portOverride ? {
496
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 warnOutsideEffect = (...args: unknown[]): void => {\n console.warn(...args);\n};\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 remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n let res: Response;\n try {\n res = await runFetch(manifestUrl, { signal: AbortSignal.timeout(10_000) });\n } catch {\n throw new Error(\"manifest fetch failed\");\n }\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch (e) {\n warnOutsideEffect(\n `[Orchestrator] Failed to fetch or parse manifest from ${manifestUrl}, falling back to remoteEntryUrl: ${String(e)}`,\n );\n }\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\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,qBAAqB,GAAG,SAA0B;CACtD,QAAQ,KAAK,GAAG,IAAI;AACtB;AAEA,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;CAE5C,MAAM,UAAU,UACb,QAAQ,sBAAsB,EAAE,CAAC,CACjC,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,OAAO,EAAE;CACpB,MAAM,iBAAiB,GAAG,QAAQ;CAClC,MAAM,cAAc,GAAG,QAAQ;CAE/B,MAAM,WAAW,OAAO,OAAO,WAAW;EACxC,KAAK,YAAY;GACf,IAAI;IACF,IAAI;IACJ,IAAI;KACF,MAAM,MAAM,SAAS,aAAa,EAAE,QAAQ,YAAY,QAAQ,GAAM,EAAE,CAAC;IAC3E,QAAQ;KACN,MAAM,IAAI,MAAM,uBAAuB;IACzC;IACA,IAAI,CAAC,IAAI,IAAI,OAAO;IACpB,MAAM,OAAQ,MAAM,IAAI,KAAK;IAC7B,IACE,QACA,OAAO,SAAS,YAChB,cAAc,QACd,aAAa,QACb,YAAY,MAEZ,OAAO;GAEX,SAAS,GAAG;IACV,kBACE,yDAAyD,YAAY,oCAAoC,OAAO,CAAC,GACnH;GACF;GACA,OAAO;EACT;EACA,aAAa;CACf,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),