{"version":3,"file":"dev-session.cjs","names":["Effect","getProjectRoot","ServiceDescriptorMap","getProcessStates","createDevLogger","Deferred","renderDevView","renderStreamingView","makeDevProcess","ServiceDescriptorMapLive","DevRuntimeConfigLive","NodeContext","Exit"],"sources":["../src/dev-session.ts"],"sourcesContent":["import * as NodeContext from \"@effect/platform-node/NodeContext\";\nimport { Deferred, Effect, Exit } from \"effect\";\nimport {\n  type DevViewHandle,\n  type LogEntry,\n  type ProcessState,\n  renderDevView,\n} from \"./components/dev-view\";\nimport { renderStreamingView } from \"./components/streaming-view\";\nimport { getProjectRoot } from \"./config\";\nimport { createDevLogger } from \"./dev-logs\";\nimport {\n  getProcessStates,\n  makeDevProcess,\n  type ProcessCallbacks,\n  type ProcessHandle,\n} from \"./orchestrator\";\nimport {\n  type AppOrchestrator,\n  DevRuntimeConfigLive,\n  type ServiceDescriptor,\n  ServiceDescriptorMap,\n  ServiceDescriptorMapLive,\n} from \"./service-descriptor\";\nimport type { RuntimeConfig } from \"./types\";\n\nconst LOG_NOISE_PATTERNS = [\n  /\\[ Federation Runtime \\] Version .* from (host|ui) of shared singleton module/,\n  /Executing an Effect versioned \\d+\\.\\d+\\.\\d+ with a Runtime of version/,\n  /you may want to dedupe the effect dependencies/,\n];\n\nconst SSR_LOG_ALLOWLIST = [\n  /\\bready\\s+built in\\b/i,\n  /\\bcompiled\\b.*successfully/i,\n  /\\berror\\b/i,\n  /\\bfailed\\b/i,\n  /\\bexception\\b/i,\n];\n\nconst shouldDisplayLog = (source: string, line: string, isError?: boolean): boolean => {\n  if (process.env.DEBUG === \"true\" || process.env.DEBUG === \"1\") return true;\n  if (source === \"ui-ssr\") {\n    if (isError) return true;\n    return SSR_LOG_ALLOWLIST.some((pattern) => pattern.test(line));\n  }\n  return !LOG_NOISE_PATTERNS.some((pattern) => pattern.test(line));\n};\n\nconst isInteractiveSupported = (): boolean => {\n  return process.stdin.isTTY === true && process.stdout.isTTY === true;\n};\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"auth\", \"api\", \"plugin\", \"host-build\", \"host\"];\n\nconst sortByOrder = (packages: string[]): string[] => {\n  return [...packages].sort((a, b) => {\n    const aIdx = a.startsWith(\"plugin:\")\n      ? STARTUP_ORDER.indexOf(\"plugin\")\n      : STARTUP_ORDER.indexOf(a);\n    const bIdx = b.startsWith(\"plugin:\")\n      ? STARTUP_ORDER.indexOf(\"plugin\")\n      : STARTUP_ORDER.indexOf(b);\n    if (aIdx === -1 && bIdx === -1) return 0;\n    if (aIdx === -1) return 1;\n    if (bIdx === -1) return -1;\n    return aIdx - bIdx;\n  });\n};\n\nfunction formatLogLine(entry: LogEntry): string {\n  const ts = new Date(entry.timestamp).toISOString();\n  const prefix = entry.isError ? \"ERR\" : \"OUT\";\n  return `[${ts}] [${entry.source}] [${prefix}] ${entry.line}`;\n}\n\nexport const runDevSession = (\n  orchestrator: AppOrchestrator,\n  onShutdownReady?: (requestShutdown: () => void) => void,\n) =>\n  Effect.gen(function* () {\n    const configDir = getProjectRoot();\n    const services = yield* ServiceDescriptorMap;\n    const orderedPackages = sortByOrder(orchestrator.packages);\n    const initialProcesses: ProcessState[] = getProcessStates(\n      orderedPackages,\n      services,\n      orchestrator.port,\n    );\n\n    const logger = yield* Effect.promise(() =>\n      createDevLogger(configDir, orchestrator.description),\n    );\n\n    const shutdown = yield* Deferred.make<void>();\n\n    onShutdownReady?.(() => {\n      void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n    });\n\n    const allLogs: LogEntry[] = [];\n    let view: DevViewHandle | null = null;\n    let shouldExportLogs = false;\n\n    const requestShutdownAndExport = () => {\n      shouldExportLogs = true;\n      void Effect.runPromise(Deferred.succeed(shutdown, undefined));\n    };\n\n    const useInteractive = orchestrator.interactive ?? isInteractiveSupported();\n    view = useInteractive\n      ? renderDevView(\n          initialProcesses,\n          orchestrator.description,\n          orchestrator.env,\n          () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n          requestShutdownAndExport,\n        )\n      : renderStreamingView(\n          initialProcesses,\n          orchestrator.description,\n          orchestrator.env,\n          () => void Effect.runPromise(Deferred.succeed(shutdown, undefined)),\n        );\n\n    const callbacks: ProcessCallbacks = {\n      onStatus: (name, status, message) => {\n        view?.updateProcess(name, status, message);\n      },\n      onLog: (name, line, isError) => {\n        const entry: LogEntry = {\n          id: `${Date.now()}-${allLogs.length + 1}`,\n          source: name,\n          line,\n          timestamp: Date.now(),\n          isError,\n        };\n        allLogs.push(entry);\n        if (shouldDisplayLog(name, line, isError)) {\n          view?.addLog(name, line, isError);\n        }\n        if (!orchestrator.noLogs) {\n          void logger.write(entry);\n        }\n      },\n    };\n\n    const startProcess = (pkg: string) => {\n      const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n      return makeDevProcess(pkg, callbacks, portOverride).pipe(\n        Effect.tapError((err) =>\n          Effect.sync(() => {\n            callbacks.onLog(pkg, `Failed to start: ${err}`, true);\n            callbacks.onStatus(pkg, \"error\");\n          }),\n        ),\n        Effect.catchAll(() =>\n          Effect.succeed({\n            name: pkg,\n            pid: undefined,\n            kill: Effect.void,\n            waitForReady: Effect.void,\n            waitForExit: Effect.never,\n          } satisfies ProcessHandle),\n        ),\n      );\n    };\n\n    const startGroup = (packages: string[]) =>\n      Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n    const awaitReady = (_pkg: string, handle: ProcessHandle) =>\n      handle.waitForReady.pipe(Effect.catchAll(() => Effect.void));\n\n    const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n    const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n    const nonHostHandles = yield* startGroup(nonHostPackages);\n\n    yield* Effect.forEach(\n      nonHostHandles.map((handle, index) => ({\n        handle,\n        pkg: nonHostPackages[index] ?? handle.name,\n      })),\n      ({ handle, pkg }) => awaitReady(pkg, handle),\n      { concurrency: \"unbounded\" },\n    );\n\n    const hostHandles = yield* startGroup(hostPackages);\n\n    yield* Effect.forEach(\n      hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n      ({ handle, pkg }) => awaitReady(pkg, handle),\n      { concurrency: \"unbounded\" },\n    );\n\n    const allHandles = [...nonHostHandles, ...hostHandles];\n\n    yield* Effect.addFinalizer(() =>\n      Effect.gen(function* () {\n        yield* Effect.forEach(allHandles, (h) => h.kill.pipe(Effect.ignore), {\n          concurrency: \"unbounded\",\n        });\n\n        yield* Effect.sleep(\"200 millis\");\n\n        view?.unmount();\n\n        if (shouldExportLogs) {\n          console.log(\"\\n\");\n          console.log(\"═\".repeat(70));\n          console.log(`  SESSION LOGS: ${orchestrator.description}`);\n          console.log(`  Started: ${new Date(allLogs[0]?.timestamp || Date.now()).toISOString()}`);\n          console.log(`  Total entries: ${allLogs.length}`);\n          console.log(\"═\".repeat(70));\n          console.log(\"\");\n          for (const entry of allLogs) {\n            console.log(formatLogLine(entry));\n          }\n          console.log(\"\");\n          console.log(\"═\".repeat(70));\n          console.log(`  Full logs saved to: ${logger.logFile}`);\n          console.log(\"═\".repeat(70));\n          console.log(\"\");\n        }\n      }),\n    );\n\n    yield* Deferred.await(shutdown);\n  });\n\nconst runApp = (\n  orchestrator: AppOrchestrator,\n  services: Map<string, ServiceDescriptor>,\n  runtimeConfig: RuntimeConfig,\n) => {\n  let requestShutdown: (() => void) | null = null;\n  let signalCount = 0;\n  let forceExitTimer: ReturnType<typeof setTimeout> | null = null;\n\n  const forceExit = () => {\n    console.log(\"\\n[Dev] Force exit\");\n    process.exit(0);\n  };\n\n  const program = Effect.scoped(\n    runDevSession(orchestrator, (shutdown) => {\n      requestShutdown = shutdown;\n    }),\n  ).pipe(\n    Effect.provide(ServiceDescriptorMapLive(services)),\n    Effect.provide(DevRuntimeConfigLive(runtimeConfig)),\n    Effect.provide(NodeContext.layer),\n    Effect.catchAllDefect((defect) =>\n      Effect.sync(() => {\n        console.error(\"[Dev] Unhandled defect in orchestrator:\", defect);\n      }),\n    ),\n  );\n\n  const handleSignal = () => {\n    signalCount++;\n    if (signalCount > 1) {\n      forceExit();\n      return;\n    }\n    console.log(\"\\n[Dev] Shutting down...\");\n    forceExitTimer = setTimeout(forceExit, 5000);\n    requestShutdown?.();\n  };\n\n  process.on(\"SIGINT\", handleSignal);\n  process.on(\"SIGTERM\", handleSignal);\n\n  Effect.runPromiseExit(program).then((exit) => {\n    if (forceExitTimer) clearTimeout(forceExitTimer);\n    process.exit(Exit.isSuccess(exit) ? 0 : 0);\n  });\n};\n\nexport const devApp = runApp;\n\nexport const startApp = runApp;\n"],"mappings":"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"}