theokit 0.11.3 → 0.11.4

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 (52) hide show
  1. package/dist/{aws-lambda-EC74AYN4.js → aws-lambda-7GSCNLPY.js} +3 -3
  2. package/dist/{build-LVN3KIE3.js → build-QFRLSEZ4.js} +6 -6
  3. package/dist/{bun-FUYLUP62.js → bun-KP2KES6S.js} +3 -3
  4. package/dist/{chunk-BYS3OYZV.js → chunk-43D6XNDR.js} +4 -4
  5. package/dist/{chunk-CCVC6P6B.js → chunk-45C3WUQ7.js} +5 -4
  6. package/dist/{chunk-CCVC6P6B.js.map → chunk-45C3WUQ7.js.map} +1 -1
  7. package/dist/{chunk-IHMJV2OK.js → chunk-7YZHAQU7.js} +2 -2
  8. package/dist/{chunk-EQV67HZL.js → chunk-FOZIR3TG.js} +2 -2
  9. package/dist/{chunk-BNGBG2SQ.js → chunk-YJAUJXZS.js} +2 -2
  10. package/dist/cli/index.js +6 -6
  11. package/dist/{cloudflare-KHF7JJZ7.js → cloudflare-C6E5SPAE.js} +3 -3
  12. package/dist/{deno-deploy-O4JP56BM.js → deno-deploy-RFZN56X4.js} +3 -3
  13. package/dist/{dev-HFOVZWYL.js → dev-GBXOTXUP.js} +5 -5
  14. package/dist/{info-DWUBVHHF.js → info-OUEUZOT7.js} +4 -4
  15. package/dist/{netlify-E63264H6.js → netlify-PMLHVPN4.js} +3 -3
  16. package/dist/node-BPJ3Z4DT.js +10 -0
  17. package/dist/{openapi-NPFP4WZY.js → openapi-VR6AFBLJ.js} +4 -4
  18. package/dist/registry-Q2TZQLUH.js +24 -0
  19. package/dist/{routes-GHMCCV7V.js → routes-LRYOIIAI.js} +4 -4
  20. package/dist/{schema-7K4SFSA3.js → schema-7CAY6IZR.js} +3 -3
  21. package/dist/{services-typed-client-6JPFJJ56.js → services-typed-client-32KMTTXR.js} +2 -2
  22. package/dist/{start-N7K7J5OE.js → start-3ZHAXSJE.js} +5 -5
  23. package/dist/{static-3JXPPDIH.js → static-55G3LX2I.js} +3 -3
  24. package/dist/{theo-cloud-I3KQE3JN.js → theo-cloud-DQRP6S6M.js} +2 -2
  25. package/dist/{vercel-6VWQTIUL.js → vercel-J6G7ZHYQ.js} +3 -3
  26. package/dist/{vite-plugin-V5PVDJZW.js → vite-plugin-WO72VLYR.js} +5 -5
  27. package/package.json +2 -2
  28. package/dist/node-XVZAGVVO.js +0 -10
  29. package/dist/registry-WHMRQG5F.js +0 -24
  30. /package/dist/{aws-lambda-EC74AYN4.js.map → aws-lambda-7GSCNLPY.js.map} +0 -0
  31. /package/dist/{build-LVN3KIE3.js.map → build-QFRLSEZ4.js.map} +0 -0
  32. /package/dist/{bun-FUYLUP62.js.map → bun-KP2KES6S.js.map} +0 -0
  33. /package/dist/{chunk-BYS3OYZV.js.map → chunk-43D6XNDR.js.map} +0 -0
  34. /package/dist/{chunk-IHMJV2OK.js.map → chunk-7YZHAQU7.js.map} +0 -0
  35. /package/dist/{chunk-EQV67HZL.js.map → chunk-FOZIR3TG.js.map} +0 -0
  36. /package/dist/{chunk-BNGBG2SQ.js.map → chunk-YJAUJXZS.js.map} +0 -0
  37. /package/dist/{cloudflare-KHF7JJZ7.js.map → cloudflare-C6E5SPAE.js.map} +0 -0
  38. /package/dist/{deno-deploy-O4JP56BM.js.map → deno-deploy-RFZN56X4.js.map} +0 -0
  39. /package/dist/{dev-HFOVZWYL.js.map → dev-GBXOTXUP.js.map} +0 -0
  40. /package/dist/{info-DWUBVHHF.js.map → info-OUEUZOT7.js.map} +0 -0
  41. /package/dist/{netlify-E63264H6.js.map → netlify-PMLHVPN4.js.map} +0 -0
  42. /package/dist/{node-XVZAGVVO.js.map → node-BPJ3Z4DT.js.map} +0 -0
  43. /package/dist/{openapi-NPFP4WZY.js.map → openapi-VR6AFBLJ.js.map} +0 -0
  44. /package/dist/{registry-WHMRQG5F.js.map → registry-Q2TZQLUH.js.map} +0 -0
  45. /package/dist/{routes-GHMCCV7V.js.map → routes-LRYOIIAI.js.map} +0 -0
  46. /package/dist/{schema-7K4SFSA3.js.map → schema-7CAY6IZR.js.map} +0 -0
  47. /package/dist/{services-typed-client-6JPFJJ56.js.map → services-typed-client-32KMTTXR.js.map} +0 -0
  48. /package/dist/{start-N7K7J5OE.js.map → start-3ZHAXSJE.js.map} +0 -0
  49. /package/dist/{static-3JXPPDIH.js.map → static-55G3LX2I.js.map} +0 -0
  50. /package/dist/{theo-cloud-I3KQE3JN.js.map → theo-cloud-DQRP6S6M.js.map} +0 -0
  51. /package/dist/{vercel-6VWQTIUL.js.map → vercel-J6G7ZHYQ.js.map} +0 -0
  52. /package/dist/{vite-plugin-V5PVDJZW.js.map → vite-plugin-WO72VLYR.js.map} +0 -0
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/aws-lambda.ts
12
12
  import { mkdirSync, writeFileSync } from "fs";
@@ -169,4 +169,4 @@ export {
169
169
  renderAwsLambdaEntry,
170
170
  responseToLambdaResultV2
171
171
  };
172
- //# sourceMappingURL=aws-lambda-EC74AYN4.js.map
172
+ //# sourceMappingURL=aws-lambda-7GSCNLPY.js.map
@@ -10,12 +10,12 @@ import {
10
10
  importUserModule,
11
11
  loadConfig,
12
12
  loadEnv
13
- } from "./chunk-IHMJV2OK.js";
14
- import "./chunk-BNGBG2SQ.js";
13
+ } from "./chunk-7YZHAQU7.js";
14
+ import "./chunk-YJAUJXZS.js";
15
15
  import {
16
16
  buildManifest,
17
17
  writeManifest
18
- } from "./chunk-CCVC6P6B.js";
18
+ } from "./chunk-45C3WUQ7.js";
19
19
  import {
20
20
  emitOpenApi,
21
21
  loadRoutesForOpenApi
@@ -527,7 +527,7 @@ async function buildCommand(options) {
527
527
  `);
528
528
  }
529
529
  async function runAdapterBuild(target, config, cwd) {
530
- const { theoPluginAsync } = await import("./vite-plugin-V5PVDJZW.js");
530
+ const { theoPluginAsync } = await import("./vite-plugin-WO72VLYR.js");
531
531
  const { default: react } = await import("@vitejs/plugin-react");
532
532
  const ctx = {
533
533
  // `react()` may return Plugin or Plugin[] depending on version; spread the
@@ -535,7 +535,7 @@ async function runAdapterBuild(target, config, cwd) {
535
535
  // type updated to `Plugin[] | Promise<Plugin[]>`).
536
536
  makeVitePlugins: async (opts) => [react(), ...await theoPluginAsync(opts)].flat()
537
537
  };
538
- const { resolveAdapter } = await import("./registry-WHMRQG5F.js");
538
+ const { resolveAdapter } = await import("./registry-Q2TZQLUH.js");
539
539
  const adapter = await resolveAdapter(target);
540
540
  await adapter.build(config, cwd, ctx);
541
541
  }
@@ -602,4 +602,4 @@ function relativize3(absPath, root) {
602
602
  export {
603
603
  buildCommand
604
604
  };
605
- //# sourceMappingURL=build-LVN3KIE3.js.map
605
+ //# sourceMappingURL=build-QFRLSEZ4.js.map
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/bun.ts
12
12
  import { mkdirSync, writeFileSync } from "fs";
@@ -136,4 +136,4 @@ export {
136
136
  bunAdapter,
137
137
  renderBunEntry
138
138
  };
139
- //# sourceMappingURL=bun-FUYLUP62.js.map
139
+ //# sourceMappingURL=bun-KP2KES6S.js.map
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-PBEH6NXR.js";
6
6
  import {
7
7
  loadConfig
8
- } from "./chunk-IHMJV2OK.js";
8
+ } from "./chunk-7YZHAQU7.js";
9
9
  import {
10
10
  BATCH_PATH,
11
11
  CSP_REPORT_PATH,
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunk-GFMQJHXX.js";
32
32
  import {
33
33
  buildServicesProxyConfig
34
- } from "./chunk-CCVC6P6B.js";
34
+ } from "./chunk-45C3WUQ7.js";
35
35
  import {
36
36
  broadcastToDevtools
37
37
  } from "./chunk-5ODOE6EF.js";
@@ -1730,7 +1730,7 @@ async function theoPluginAsync(rootOrOptions) {
1730
1730
  });
1731
1731
  const servicesPlugins = [];
1732
1732
  if (options.services && Object.keys(options.services).length > 0) {
1733
- const { servicesTypedClientPlugin } = await import("./services-typed-client-6JPFJJ56.js");
1733
+ const { servicesTypedClientPlugin } = await import("./services-typed-client-32KMTTXR.js");
1734
1734
  servicesPlugins.push(
1735
1735
  servicesTypedClientPlugin({
1736
1736
  cwd: projectRoot,
@@ -1910,4 +1910,4 @@ export {
1910
1910
  theoPluginAsync,
1911
1911
  theoPlugin
1912
1912
  };
1913
- //# sourceMappingURL=chunk-BYS3OYZV.js.map
1913
+ //# sourceMappingURL=chunk-43D6XNDR.js.map
@@ -595,13 +595,14 @@ function prepareTheoCloudArtifacts(manifest) {
595
595
  if (manifest === null) {
596
596
  return { manifestVersion: 1, services: [] };
597
597
  }
598
- if (manifest.version !== 1) {
598
+ const version = manifest.version;
599
+ if (version !== 1 && version !== 2) {
599
600
  throw new Error(
600
- `TheoCloud adapter: unsupported manifest version ${String(manifest.version)}. Wave 2/3 expects schemaVersion 1. Update the adapter before bumping.`
601
+ `TheoCloud adapter: unsupported manifest version ${String(version)}. Supported: schemaVersion 1 (deprecated) or 2. Update the adapter before bumping.`
601
602
  );
602
603
  }
603
604
  return {
604
- manifestVersion: 1,
605
+ manifestVersion: manifest.version,
605
606
  services: manifest.services.map((s) => s.name)
606
607
  };
607
608
  }
@@ -637,4 +638,4 @@ export {
637
638
  buildServicesProxyConfig,
638
639
  prepareTheoCloudArtifacts
639
640
  };
640
- //# sourceMappingURL=chunk-CCVC6P6B.js.map
641
+ //# sourceMappingURL=chunk-45C3WUQ7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/adapters-bridge/adapter-support.ts","../src/services/generators/caddy-generator.ts","../src/services/generators/compose-generator.ts","../src/services/generators/openapi-client-gen.ts","../src/services/adapters-bridge/manifest.ts","../src/services/schema.ts","../src/services/runtime/orchestrator.ts","../src/services/runtime/healthcheck-poller.ts","../src/services/runtime/log-merge.ts","../src/services/runtime/process-spawn-helpers.ts","../src/services/adapters-bridge/theo-cloud-adapter-stub.ts","../src/services/adapters-bridge/vite-proxy-builder.ts"],"sourcesContent":["/**\n * Adapter support gates (Wave 2 — TheoCloud-first focus).\n *\n * Wave 2 SUPPORTS polyglot `services: {}` on TWO targets ONLY:\n * - `node` (local docker-compose harness — TheoCloud-shaped)\n * - `theo-cloud` (the principal deploy target — Wave 3 adapter)\n *\n * All other in-tree deploy adapters (vercel, cloudflare, bun, deno-deploy,\n * aws-lambda, netlify, static) ARE STILL FIRST-CLASS DEPLOY TARGETS for\n * the TS app, but `services: {}` Wave 2 is NOT yet wired through them.\n * They reject loudly with an actionable message when the manifest has\n * non-empty services — pointing the user at `node` (local) or TheoCloud.\n *\n * Per owner decision 2026-05-27: TheoKit's polyglot services energy is\n * 100% TheoCloud; Vercel/Cloudflare/etc. polyglot-services wire-ups are\n * out of Wave 2 scope and deferred to fresh ADRs if demand emerges.\n */\nimport type { ServicesManifest } from './manifest.js'\n\nconst SUPPORTED_IN_WAVE_2 = ['node (local)', 'theo-cloud (Wave 3)'] as const\n\n/**\n * Reject if the adapter does not support polyglot services. Adapters\n * outside `node` + `theo-cloud` call this; the message points to the\n * supported alternatives.\n *\n * Throws when manifest has non-empty services. No-op when manifest is null\n * or empty (Wave 1 BC — the app still deploys, just without sidecars).\n */\nexport function assertServicesUnsupported(\n adapterName: string,\n manifest: ServicesManifest | null,\n): void {\n if (!manifest || manifest.services.length === 0) return\n const names = manifest.services.map((s) => s.name).join(', ')\n throw new Error(\n `Adapter '${adapterName}' does not support polyglot services in Wave 2.\\n` +\n `Detected services in theo.config.ts: ${names}.\\n\\n` +\n `Wave 2 supports: ${SUPPORTED_IN_WAVE_2.join(', ')}.\\n` +\n `TheoCloud is the strategic deploy target — the adapter ships in Wave 3.\\n` +\n `For local dev/prod-like validation today, use \\`theokit build --target node\\`\\n` +\n `(emits docker-compose + Caddyfile — TheoCloud-shaped harness).\\n\\n` +\n `See docs/concepts/services.md.`,\n )\n}\n","/**\n * Caddyfile generator (T3.3).\n *\n * Emits a Caddyfile that fronts the TheoKit web app + declared services\n * with W3C trace context propagation enabled (Caddy 2.11+ `tracing` directive).\n *\n * Generated output sits at `<dist>/.theokit/node/Caddyfile`, consumed by the\n * docker-compose stack (T3.3 compose-generator).\n *\n * EC-23: `reverse_proxy` directives are ordered by prefix length DESC.\n * Caddy matches longest-prefix-first when written in order.\n */\nimport type { ServicesManifest } from '../adapters-bridge/manifest.js'\n\nexport interface CaddyfileOptions {\n /** Port Caddy listens on (TheoKit web port; default 3000). */\n port: number\n /** TheoKit web container hostname (compose service name). Default 'web'. */\n webHost: string\n}\n\nfunction reverseProxyLines(servicePath: string, target: string, cors: boolean): string[] {\n const out = [`\\treverse_proxy ${servicePath}* ${target}`]\n if (cors) {\n out.push(\n `\\theader ${servicePath}* Access-Control-Allow-Origin \"*\"`,\n `\\theader ${servicePath}* Access-Control-Allow-Methods \"GET, POST, PUT, DELETE, OPTIONS\"`,\n `\\theader ${servicePath}* Access-Control-Allow-Headers \"Content-Type, Authorization, traceparent, tracestate, baggage\"`,\n )\n }\n return out\n}\n\nexport function generateCaddyfile(\n manifest: ServicesManifest | null,\n options: CaddyfileOptions,\n): string {\n // EC-23: sort services by proxy prefix length DESC so longest matches first\n const services = (manifest?.services ?? [])\n .slice()\n .sort((a, b) => b.proxy.length - a.proxy.length)\n\n const serviceLines = services.flatMap((svc) =>\n reverseProxyLines(svc.proxy, `${svc.name}:${String(svc.port)}`, svc.cors),\n )\n\n const lines: string[] = [\n `:${String(options.port)} {`,\n `\\t# W3C Trace Context propagation (Caddy 2.11+)`,\n `\\ttracing`,\n `\\theader -Server`,\n ...serviceLines,\n `\\treverse_proxy ${options.webHost}:${String(options.port)}`,\n `}`,\n '',\n ]\n return lines.join('\\n')\n}\n","/**\n * docker-compose.yml generator (T3.3).\n *\n * Emits the \"TheoCloud-shaped\" local harness — Caddy ingress in front of\n * web + declared services. Each service has a healthcheck and Caddy\n * `depends_on: service_healthy`.\n *\n * Used by the Node adapter: `theokit build --target node` writes the\n * compose stack to `.theokit/node/docker-compose.yml`.\n */\nimport type { ManifestServiceEntry, ServicesManifest } from '../adapters-bridge/manifest.js'\n\nexport interface ComposeOptions {\n /** Port for the web container (TheoKit). Default 3000. */\n webPort: number\n /** Caddy listening port (default same as webPort — Caddy fronts everything). */\n caddyPort?: number\n /** Project name (compose file `name:` field). */\n projectName?: string\n}\n\nfunction indent(level: number): string {\n return ' '.repeat(level)\n}\n\nfunction healthcheckLines(svc: ManifestServiceEntry): string[] {\n const checker =\n svc.runtime === 'python'\n ? `curl -f http://localhost:${String(svc.port)}${svc.healthcheck} || exit 1`\n : `wget --spider -q http://localhost:${String(svc.port)}${svc.healthcheck} || exit 1`\n return [\n `${indent(2)}healthcheck:`,\n `${indent(3)}test: [\"CMD-SHELL\", \"${checker}\"]`,\n `${indent(3)}interval: 10s`,\n `${indent(3)}timeout: 5s`,\n `${indent(3)}retries: 3`,\n ]\n}\n\nfunction envLines(env: Record<string, string>): string[] {\n const lines: string[] = [`${indent(2)}environment:`]\n for (const [k, v] of Object.entries(env)) {\n lines.push(`${indent(3)}${k}: ${JSON.stringify(v)}`)\n }\n return lines\n}\n\nfunction serviceBlockLines(svc: ManifestServiceEntry): string[] {\n // EC-8: auto-inject convention env vars in the container too\n const env: Record<string, string> = {\n THEOKIT_SERVICE_NAME: svc.name,\n THEOKIT_SERVICE_PORT: String(svc.port),\n ...(svc.env ?? {}),\n }\n return [\n `${indent(1)}${svc.name}:`,\n `${indent(2)}build:`,\n `${indent(3)}context: ./services/${svc.name}`,\n `${indent(2)}expose:`,\n `${indent(3)}- \"${String(svc.port)}\"`,\n ...envLines(env),\n ...healthcheckLines(svc),\n ]\n}\n\nfunction caddyBlockLines(caddyPort: number, services: ManifestServiceEntry[]): string[] {\n const depends: string[] = [\n `${indent(2)}depends_on:`,\n `${indent(3)}web:`,\n `${indent(4)}condition: service_healthy`,\n ]\n for (const svc of services) {\n depends.push(`${indent(3)}${svc.name}:`, `${indent(4)}condition: service_healthy`)\n }\n return [\n `${indent(1)}caddy:`,\n `${indent(2)}image: caddy:2.11`,\n `${indent(2)}ports:`,\n `${indent(3)}- \"${String(caddyPort)}:${String(caddyPort)}\"`,\n `${indent(2)}volumes:`,\n `${indent(3)}- ./Caddyfile:/etc/caddy/Caddyfile:ro`,\n ...depends,\n ]\n}\n\nfunction webBlockLines(webPort: number): string[] {\n return [\n `${indent(1)}web:`,\n `${indent(2)}build:`,\n `${indent(3)}context: .`,\n `${indent(3)}dockerfile: Dockerfile`,\n `${indent(2)}expose:`,\n `${indent(3)}- \"${String(webPort)}\"`,\n `${indent(2)}healthcheck:`,\n `${indent(3)}test: [\"CMD-SHELL\", \"wget --spider -q http://localhost:${String(webPort)}/api/health || exit 1\"]`,\n `${indent(3)}interval: 10s`,\n `${indent(3)}timeout: 5s`,\n `${indent(3)}retries: 3`,\n ]\n}\n\nexport function generateComposeYaml(\n manifest: ServicesManifest | null,\n options: ComposeOptions,\n): string {\n const services = manifest?.services ?? []\n const webPort = options.webPort\n const caddyPort = options.caddyPort ?? webPort\n\n const projectLines = options.projectName ? [`name: ${options.projectName}`] : []\n\n const lines: string[] = [\n ...projectLines,\n `services:`,\n ...caddyBlockLines(caddyPort, services),\n ...webBlockLines(webPort),\n ...services.flatMap(serviceBlockLines),\n '',\n ]\n return lines.join('\\n')\n}\n","/**\n * OpenAPI → TypeScript client generation (T5.1).\n *\n * Thin wrapper around `@hey-api/openapi-ts` (the de facto 2026 generator\n * used by Vercel/OpenCode/PayPal). Called by the Vite plugin\n * `services-typed-client.ts` at dev startup and when an OpenAPI URL\n * changes.\n *\n * Production behavior:\n * - For each service with a `openapi` URL, fetch the spec\n * - Run Hey API generator to write `<cwd>/clients/<service-name>.ts`\n * - On any failure: log warning, do NOT crash dev (best-effort)\n *\n * The actual `@hey-api/openapi-ts` invocation is dynamic-imported so\n * that consumers without the dep (TS-only Wave 1 apps) don't pay\n * the bundle cost.\n */\nimport type { ManifestServiceEntry } from '../adapters-bridge/manifest.js'\n\nexport interface GenerateClientOptions {\n service: ManifestServiceEntry\n /** Directory to write `<service-name>.ts` into. */\n outputDir: string\n /** Logger for warnings/info. */\n log?: (level: 'info' | 'warn' | 'error', msg: string) => void\n /** Test injection — replace fetch (so tests don't hit the network). */\n customFetch?: typeof fetch\n}\n\nexport interface GenerateClientResult {\n generated: boolean\n outputFile?: string\n skippedReason?: string\n}\n\n/**\n * Generate a typed client for one service. No-op (returns skipped=true)\n * if the service has no `openapi` URL.\n *\n * The generator runs the Hey API tool. If the tool import fails (not\n * installed), the function logs a warning and returns `{ generated: false }`.\n */\nexport async function generateTypedClient(\n options: GenerateClientOptions,\n): Promise<GenerateClientResult> {\n const log =\n options.log ??\n ((_level: 'info' | 'warn' | 'error', _msg: string) => {\n // default: silent in production; tests inject their own\n })\n const { service, outputDir } = options\n\n if (!service.openapi) {\n return { generated: false, skippedReason: 'no openapi URL declared' }\n }\n\n const f = options.customFetch ?? fetch\n let spec: unknown\n try {\n const res = await f(service.openapi)\n if (!res.ok) {\n log('warn', `[${service.name}] openapi fetch returned ${String(res.status)}; skipping`)\n return { generated: false, skippedReason: `fetch returned ${String(res.status)}` }\n }\n spec = await res.json()\n } catch (err) {\n log(\n 'warn',\n `[${service.name}] openapi fetch failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n return { generated: false, skippedReason: 'fetch failed' }\n }\n\n // Dynamic import — soft dep. We pass through a variable so the typechecker\n // doesn't resolve the literal at build time (the dep is optional;\n // consumers without it get a graceful skip).\n let createClient: unknown\n try {\n // Soft-dep resolution. We pass the module name through a String wrapper\n // call site that the typechecker cannot statically resolve — so missing\n // dep at typecheck time does not break the build. Runtime behavior is\n // identical to `import('@hey-api/openapi-ts')`.\n const segment1 = '@hey-api/'\n const segment2 = 'openapi-ts'\n const moduleName = `${segment1}${segment2}`\n const dyn: Promise<unknown> = import(moduleName).catch(() => null)\n const mod = (await dyn) as { createClient?: unknown } | null\n createClient = mod?.createClient\n } catch {\n createClient = undefined\n }\n\n if (typeof createClient !== 'function') {\n log(\n 'warn',\n `[${service.name}] @hey-api/openapi-ts not installed; typed client not generated. ` +\n `Run \\`pnpm add -D @hey-api/openapi-ts @hey-api/client-fetch\\` to enable.`,\n )\n return { generated: false, skippedReason: 'hey-api not installed' }\n }\n\n const outputFile = `${outputDir}/${service.name}.ts`\n try {\n await (createClient as (cfg: unknown) => Promise<unknown>)({\n input: spec,\n output: { path: outputDir, format: 'prettier' },\n plugins: [{ name: '@hey-api/client-fetch' }],\n })\n log('info', `[${service.name}] typed client generated at ${outputFile}`)\n return { generated: true, outputFile }\n } catch (err) {\n log(\n 'warn',\n `[${service.name}] Hey API generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n return { generated: false, skippedReason: 'generator threw' }\n }\n}\n","/**\n * Neutral cross-product manifest (T1.4).\n *\n * Emitted by `theokit build` at `<cwd>/.theokit/services.json` (schemaVersion 1).\n * Consumed by EVERY deploy adapter (Vercel, Node, Cloudflare, future TheoCloud).\n *\n * Shape is INTENTIONALLY platform-neutral (ADR-0015 invariant + D5). No\n * `vercel`/`cloudflare`/`theoCloud` keys — platform-specific tuning lives in\n * `theo.config.ts` and is read by each adapter's own code, NOT serialized\n * into this manifest.\n *\n * Topological ordering enforced (dependsOn-resolved deps first) so adapters\n * that need boot order (docker-compose, K8s) can consume the array verbatim.\n */\n/* eslint-disable security/detect-non-literal-fs-filename --\n * Manifest read/write paths are derived from the trusted `cwd` plus a fixed\n * subpath (`.theokit/services.json`). No user input flows into the path.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nimport type { ServiceDefinition, ServicesConfig } from '../schema.js'\n\n/**\n * Plan v1.2 T2.2 — service shape enum, mirrored from\n * `theo-cloud/api/internal/source/services.schema.json`. Optional in\n * services.json v2; TheoCloud Go-side defaults to `server` when absent.\n */\n// `frontend` removed in simplify-deploy-theokit-only v2.0 (D5) — TheoCloud\n// serves no static frontends; service shape is server | worker only.\nexport type ManifestServiceType = 'server' | 'worker'\n\nexport interface ManifestServiceEntry {\n name: string\n runtime: 'python' | 'node'\n /** Plan v1.2 T2.2 — service shape. Omit to keep default `server`. */\n type?: ManifestServiceType\n port: number\n proxy: string\n dev: string\n build?: string\n start: string\n openapi?: string\n healthcheck: string\n cors: boolean\n env?: Record<string, string>\n dependsOn?: string[]\n passSetCookie: boolean\n}\n\n/**\n * Plan v1.2 T2.1 — services.json now ships in 2 shapes:\n *\n * v1 (deprecated, sunset theokit 0.6.0): { version: 1, services: [...] }\n * v2 (current): { version: 2, project: <name>, services: [...] }\n *\n * `buildManifest()` selects which version to emit based on whether a\n * project name is supplied. Consumers (TheoCloud Go-side validator)\n * accept both via the JSON Schema 7 `oneOf` block.\n */\nexport interface ServicesManifestV1 {\n version: 1\n services: ManifestServiceEntry[]\n}\n\nexport interface ServicesManifestV2 {\n version: 2\n project: string\n services: ManifestServiceEntry[]\n}\n\nexport type ServicesManifest = ServicesManifestV1 | ServicesManifestV2\n\nconst MANIFEST_RELATIVE_PATH = ['.theokit', 'services.json'] as const\n\n/**\n * Topological sort using Kahn's algorithm.\n * Returns service names in dependency order (deps before dependants).\n * Schema validation guarantees no cycles, no self-deps, no missing references —\n * but we still defensively handle missing deps as no-op.\n */\nfunction topoSort(services: ServicesConfig): string[] {\n const names = Object.keys(services)\n const indeg: Record<string, number> = Object.fromEntries(names.map((n) => [n, 0]))\n const adj: Record<string, string[]> = Object.fromEntries(names.map((n) => [n, []]))\n\n const cmp = (a: string, b: string) => a.localeCompare(b)\n\n for (const name of names) {\n const deps = services[name].dependsOn ?? []\n for (const dep of deps) {\n if (!(dep in indeg)) continue\n adj[dep].push(name)\n indeg[name] = (indeg[name] ?? 0) + 1\n }\n }\n\n // Sort initial roots for determinism\n const queue: string[] = names.filter((n) => indeg[n] === 0).sort(cmp)\n const result: string[] = []\n while (queue.length > 0) {\n const cur = queue.shift()\n if (cur === undefined) break\n result.push(cur)\n const adjacent = (adj[cur] ?? []).slice().sort(cmp)\n for (const next of adjacent) {\n indeg[next] = (indeg[next] ?? 0) - 1\n if (indeg[next] === 0) {\n queue.push(next)\n }\n }\n }\n return result.length === names.length ? result : names // fallback (should not hit; schema rejects cycles)\n}\n\nfunction definitionToEntry(name: string, def: ServiceDefinition): ManifestServiceEntry {\n const entry: ManifestServiceEntry = {\n name,\n runtime: def.runtime,\n port: def.port,\n proxy: def.proxy,\n dev: def.dev,\n start: def.start,\n healthcheck: def.healthcheck,\n cors: def.cors,\n passSetCookie: def.passSetCookie,\n }\n // Plan v1.2 T2.2 — only emit `type` when explicitly set so v1 fixtures\n // (no type field at all) stay byte-identical.\n if (def.type !== undefined) entry.type = def.type\n if (def.build !== undefined) entry.build = def.build\n if (def.openapi !== undefined) entry.openapi = def.openapi\n if (def.env !== undefined) entry.env = def.env\n if (def.dependsOn !== undefined) entry.dependsOn = [...def.dependsOn]\n return entry\n}\n\n/**\n * Build a services manifest. Plan v1.2 T2.1: pass a `project` name to emit\n * v2; omit it to emit v1 (deprecated, accepted by TheoCloud until 0.6.0\n * sunset).\n */\nexport function buildManifest(services: ServicesConfig, project?: string): ServicesManifest {\n const ordered = topoSort(services)\n const entries = ordered.map((name) => definitionToEntry(name, services[name]))\n if (project !== undefined && project.length > 0) {\n return { version: 2, project, services: entries }\n }\n return { version: 1, services: entries }\n}\n\nfunction manifestPath(cwd: string): string {\n return join(cwd, ...MANIFEST_RELATIVE_PATH)\n}\n\n/**\n * Write the manifest to `<cwd>/.theokit/services.json`.\n *\n * EC-6 fix: creates `.theokit/` recursively if absent (fresh project on first\n * `pnpm build` would otherwise hit ENOENT).\n */\nexport function writeManifest(cwd: string, manifest: ServicesManifest): void {\n const file = manifestPath(cwd)\n mkdirSync(dirname(file), { recursive: true })\n writeFileSync(file, JSON.stringify(manifest, null, 2), 'utf-8')\n}\n\n/**\n * Read the manifest from `<cwd>/.theokit/services.json`.\n *\n * Returns null if the file does not exist (adapter's job to handle).\n * Throws with an actionable message if the file is malformed JSON.\n */\nexport function readManifest(cwd: string): ServicesManifest | null {\n const file = manifestPath(cwd)\n if (!existsSync(file)) return null\n const raw = readFileSync(file, 'utf-8')\n try {\n return JSON.parse(raw) as ServicesManifest\n } catch (err) {\n throw new Error(\n `failed to parse services.json at ${file}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n }\n}\n","/**\n * Wave 2 — Polyglot Services Orchestration (T1.1).\n *\n * Declarative `services: {}` primitive for `theo.config.ts`. Each entry\n * declares an external sidecar process (Python FastAPI / Node Hono) that\n * boots alongside the TheoKit TS app. Empty `services: {}` is the default\n * and preserves Wave 1 behavior (no impact on TS-only apps).\n *\n * See ADRs 0012-0015 + plan: docs/plans/wave-2-polyglot-services-plan.md\n */\nimport { z } from 'zod'\n\n/** Wave 2 runtime kinds. Go/Rust/Java/Ruby/PHP archived; deferred per ADR-0012 invariant #2/#3. */\nconst ServiceRuntimeSchema = z.enum(['python', 'node'])\n\n/**\n * Service shape enum, mirrored from `services.schema.json`: server | worker.\n * Optional; emitters default to \"server\". `frontend` removed in\n * simplify-deploy-theokit-only v2.0 (D5) — TheoCloud serves no static frontends.\n */\nconst ServiceTypeSchema = z.enum(['server', 'worker'])\n\n/** EC-3 fix: names that conflict with generated docker-compose entries. */\nconst RESERVED_SERVICE_NAMES = ['web', 'caddy', 'postgres', 'redis'] as const\n\n/**\n * EC-12 fix: service names must be docker-compose-safe — lowercase,\n * start with a letter, contain only a-z 0-9 -. Reserved names rejected.\n */\nconst ServiceNameSchema = z\n .string()\n .min(1)\n .regex(\n /^[a-z][a-z0-9-]*$/,\n 'service name must be lowercase, start with letter, contain only a-z 0-9 -',\n )\n .refine((n) => !(RESERVED_SERVICE_NAMES as readonly string[]).includes(n), {\n message: `service name conflicts with reserved name (${RESERVED_SERVICE_NAMES.join('/')})`,\n })\n\n/**\n * Single service definition. All commands run from `services/<name>/` cwd.\n *\n * EC-4 fix: `proxy` regex requires NON-EMPTY path after `/` (the `+` quantifier)\n * to reject `/` which would catch-all and conflict with TheoKit's own routing.\n */\nconst ServiceDefinitionSchema = z.object({\n runtime: ServiceRuntimeSchema,\n type: ServiceTypeSchema.optional(),\n port: z.number().int().min(1).max(65535),\n proxy: z.string().regex(/^\\/[a-zA-Z0-9\\-_/]+$/, 'proxy must be a non-root path starting with /'),\n dev: z.string().min(1),\n build: z.string().optional(),\n start: z.string().min(1),\n openapi: z.url().optional(),\n healthcheck: z.string().regex(/^\\//, 'healthcheck must start with /').default('/health'),\n cors: z.boolean().default(false),\n env: z.record(z.string(), z.string()).optional(),\n dependsOn: z.array(z.string()).optional(),\n /**\n * EC-25 + ref doc §8: by default the proxy strips upstream Set-Cookie\n * to prevent the polyglot service from issuing cookies that conflict\n * with TheoKit's encrypted session. Set to true to opt-in.\n */\n passSetCookie: z.boolean().default(false),\n})\n\nexport type ServiceDefinition = z.infer<typeof ServiceDefinitionSchema>\nexport type ServicesConfig = Record<string, ServiceDefinition>\n\n/**\n * Topological-order helper used by `dependsOn` cycle detection refine.\n * Returns true iff `graph` is a DAG. Each node's deps must all reference\n * existing nodes; cycles return false.\n */\nfunction isDag(graph: Record<string, readonly string[]>): boolean {\n const WHITE = 0\n const GRAY = 1\n const BLACK = 2\n const colors: Record<string, 0 | 1 | 2> = {}\n for (const node of Object.keys(graph)) colors[node] = WHITE\n\n function visit(node: string): boolean {\n if (colors[node] === GRAY) return false // cycle\n if (colors[node] === BLACK) return true\n colors[node] = GRAY\n for (const dep of graph[node] ?? []) {\n if (!(dep in graph)) return false // missing reference\n if (!visit(dep)) return false\n }\n colors[node] = BLACK\n return true\n }\n\n for (const node of Object.keys(graph)) {\n if (colors[node] === WHITE && !visit(node)) return false\n }\n return true\n}\n\n/**\n * Full services config schema with cross-service refines.\n *\n * EC-1 fix: detect duplicate ports across services.\n * EC-13: empty `dependsOn: []` accepted as no-deps.\n * Self-dep, missing-ref, and cycles rejected via topological check.\n */\nexport const servicesConfigSchema = z\n .record(ServiceNameSchema, ServiceDefinitionSchema)\n .default({})\n // EC-1: duplicate port detection across services\n .refine(\n (s) => {\n const ports = Object.values(s).map((v) => v.port)\n return new Set(ports).size === ports.length\n },\n {\n message: 'duplicate port across services — each service must bind a unique port',\n },\n )\n // duplicate proxy prefix detection\n .refine(\n (s) => {\n const prefixes = Object.values(s).map((v) => v.proxy)\n return new Set(prefixes).size === prefixes.length\n },\n { message: 'duplicate proxy prefix across services' },\n )\n // dependsOn correctness (self-dep, missing reference, cycle)\n .refine(\n (s) => {\n // Build graph\n const graph: Record<string, readonly string[]> = {}\n for (const [name, def] of Object.entries(s)) {\n graph[name] = def.dependsOn ?? []\n }\n // Self-dep: a service mentioning itself is rejected as part of cycle detection\n for (const [name, deps] of Object.entries(graph)) {\n if (deps.includes(name)) return false\n }\n return isDag(graph)\n },\n {\n message: 'invalid dependsOn — must reference existing services, no self-deps, no cycles',\n },\n )\n\nexport type ServicesConfigInput = z.input<typeof servicesConfigSchema>\nexport type ServicesConfigOutput = z.output<typeof servicesConfigSchema>\n","/**\n * Dev orchestration entry point (T2.4).\n *\n * Spawns declared polyglot services, waits for all healthchecks to pass,\n * then signals readiness. The `theokit dev` CLI calls `orchestrateDev`\n * BEFORE starting Vite — Vite only boots after all services healthy.\n *\n * Empty `services: {}` → no-op (Wave 1 BC).\n *\n * Single composable entry that the CLI consumes. Spawn/healthcheck/log\n * primitives live in their own modules; this file ties them together.\n */\nimport type { ChildProcess, SpawnOptions } from 'node:child_process'\nimport { spawn } from 'node:child_process'\nimport { resolve } from 'node:path'\n\nimport type { ServiceDefinition, ServicesConfig } from '../schema.js'\n\nimport { pollHealthcheck } from './healthcheck-poller.js'\nimport { createLogMerger } from './log-merge.js'\nimport { buildSpawnEnv, installLifecycleHandlers } from './process-spawn-helpers.js'\n\nexport interface SpawnedService {\n name: string\n port: number\n process: ChildProcess\n}\n\nexport interface OrchestrateDevOptions {\n cwd: string\n services: ServicesConfig\n /** Defaults to `process.stdout.write.bind(process.stdout)`. */\n write?: (s: string) => void\n /** Test injection — replace child_process.spawn. */\n spawnFn?: typeof spawn\n /** Test injection — replace global fetch (for healthchecks). */\n customFetch?: typeof fetch\n /** Healthcheck timeout per service. Default 30_000. */\n healthcheckTimeoutMs?: number\n /** Whether to install parent lifecycle handlers (EC-7). Default true. */\n installSignalHandlers?: boolean\n}\n\nexport interface OrchestrateDevResult {\n spawned: SpawnedService[]\n /** Whether ALL services passed healthcheck. */\n allHealthy: boolean\n /** Services that timed out (only populated when !allHealthy). */\n unhealthy: string[]\n /** Call to gracefully stop all spawned services. */\n stop: () => Promise<void>\n}\n\nfunction spawnService(\n name: string,\n service: ServiceDefinition,\n cwd: string,\n options: {\n spawnFn: typeof spawn\n onLog: (s: string, stream: 'stdout' | 'stderr', line: string) => void\n },\n): SpawnedService {\n const env = buildSpawnEnv(name, service, process.env)\n const spawnOpts: SpawnOptions = {\n cwd,\n shell: true,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n }\n const child = options.spawnFn(service.dev, spawnOpts)\n child.stdout?.setEncoding('utf-8')\n child.stderr?.setEncoding('utf-8')\n child.stdout?.on('data', (chunk: string) => {\n options.onLog(name, 'stdout', chunk)\n })\n child.stderr?.on('data', (chunk: string) => {\n options.onLog(name, 'stderr', chunk)\n })\n return { name, port: service.port, process: child }\n}\n\nasync function stopSpawned(s: SpawnedService): Promise<void> {\n return new Promise<void>((resolve) => {\n if (s.process.killed || s.process.exitCode !== null) {\n resolve()\n return\n }\n const timer = setTimeout(() => {\n s.process.kill('SIGKILL')\n resolve()\n }, 5_000)\n s.process.once('exit', () => {\n clearTimeout(timer)\n resolve()\n })\n s.process.kill('SIGTERM')\n })\n}\n\nexport async function orchestrateDev(\n options: OrchestrateDevOptions,\n): Promise<OrchestrateDevResult> {\n const entries = Object.entries(options.services)\n if (entries.length === 0) {\n return {\n spawned: [],\n allHealthy: true,\n unhealthy: [],\n stop: () => Promise.resolve(),\n }\n }\n\n const write =\n options.write ??\n ((s: string) => {\n process.stdout.write(s)\n })\n const spawnFn = options.spawnFn ?? spawn\n const merger = createLogMerger({ write })\n\n const spawned: SpawnedService[] = entries.map(([name, def]) =>\n spawnService(name, def, resolve(options.cwd, 'services', name), {\n spawnFn,\n onLog: merger.onLog,\n }),\n )\n\n const stop = async (): Promise<void> => {\n await Promise.all(spawned.map(stopSpawned))\n }\n\n if (options.installSignalHandlers !== false) {\n installLifecycleHandlers(process, stop)\n }\n\n // Parallel healthcheck\n const results = await Promise.all(\n entries.map(([name, def]) =>\n pollHealthcheck({\n url: `http://localhost:${String(def.port)}${def.healthcheck}`,\n timeoutMs: options.healthcheckTimeoutMs ?? 30_000,\n intervalMs: 500,\n customFetch: options.customFetch,\n }).then((r) => ({ name, result: r })),\n ),\n )\n\n const unhealthy = results.filter((r) => !r.result.healthy).map((r) => r.name)\n return {\n spawned,\n allHealthy: unhealthy.length === 0,\n unhealthy,\n stop,\n }\n}\n","/**\n * Healthcheck poller (T1.5).\n *\n * Polls `GET <url>` with backoff until 200 OR timeout. Used by `pnpm dev`\n * (T2.4) to gate readiness on declared services being healthy before\n * starting Vite.\n *\n * Invariants:\n * - Returns within `timeoutMs + intervalMs` (no hang)\n * - Never throws (returns `{ healthy: false }` on any error)\n * - `attempts >= 1` always\n * - Respects external AbortSignal (pre-aborted → immediate return, EC-18)\n */\n\nexport interface HealthcheckOptions {\n /** Full URL to poll, e.g. 'http://localhost:8001/health' */\n url: string\n /** Total time budget in ms. Default 30_000. */\n timeoutMs?: number\n /** Sleep between attempts in ms. Default 500. */\n intervalMs?: number\n /** Optional external cancel. Aborted signal causes early return. */\n signal?: AbortSignal\n /** Test injection — replace global fetch. */\n customFetch?: typeof fetch\n}\n\nexport interface HealthcheckResult {\n healthy: boolean\n attempts: number\n durationMs: number\n lastError?: string\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve) => {\n if (signal?.aborted) {\n resolve()\n return\n }\n const t = setTimeout(() => {\n resolve()\n }, ms)\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(t)\n resolve()\n },\n { once: true },\n )\n })\n}\n\nexport async function pollHealthcheck(options: HealthcheckOptions): Promise<HealthcheckResult> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const intervalMs = options.intervalMs ?? 500\n const f = options.customFetch ?? fetch\n const start = Date.now()\n let attempts = 0\n let lastError: string | undefined\n\n // EC-18: signal already aborted → return immediately with at least 1 attempt counted\n if (options.signal?.aborted) {\n return {\n healthy: false,\n attempts: 1,\n durationMs: Date.now() - start,\n lastError: 'aborted',\n }\n }\n\n // Infinite poll loop terminated by status === 200 OR timeout OR abort.\n for (;;) {\n if (options.signal?.aborted) {\n return {\n healthy: false,\n attempts: Math.max(attempts, 1),\n durationMs: Date.now() - start,\n lastError: 'aborted',\n }\n }\n attempts++\n try {\n const res = await f(options.url, { method: 'GET', signal: options.signal })\n if (res.status === 200) {\n return { healthy: true, attempts, durationMs: Date.now() - start }\n }\n lastError = `status ${res.status}`\n } catch (err) {\n lastError = err instanceof Error ? err.message : String(err)\n }\n\n if (Date.now() - start >= timeoutMs) {\n return {\n healthy: false,\n attempts,\n durationMs: Date.now() - start,\n lastError,\n }\n }\n await sleep(intervalMs, options.signal)\n }\n}\n","/**\n * Log merger (T2.3).\n *\n * Combines stdout/stderr from multiple polyglot services into TheoKit's\n * dev terminal, prefixed with `[service-name]`. Parses JSON-line logs\n * (ADR-0015 invariant #5) for pretty-printing; falls back to raw line on\n * non-JSON.\n *\n * Pure / synchronous. The Vite plugin (T2.1) wires this as the `onLog`\n * callback passed to spawnServices.\n */\n\ninterface LogEntry {\n level?: string\n message?: string\n timestamp?: string\n traceparent?: string\n service?: string\n}\n\nexport interface LogMergerOptions {\n write: (s: string) => void\n}\n\nexport interface LogMerger {\n onLog: (service: string, stream: 'stdout' | 'stderr', chunk: string) => void\n}\n\n/**\n * Try to parse a log line as JSON. Returns parsed object on success,\n * undefined on failure (will fall back to raw rendering).\n */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v)\n}\n\nfunction tryParseJson(line: string): LogEntry | undefined {\n const trimmed = line.trim()\n if (!trimmed.startsWith('{')) return undefined\n try {\n const parsed: unknown = JSON.parse(trimmed)\n if (!isPlainObject(parsed)) return undefined\n const entry: LogEntry = {}\n if (typeof parsed.level === 'string') entry.level = parsed.level\n if (typeof parsed.message === 'string') entry.message = parsed.message\n if (typeof parsed.timestamp === 'string') entry.timestamp = parsed.timestamp\n if (typeof parsed.traceparent === 'string') entry.traceparent = parsed.traceparent\n if (typeof parsed.service === 'string') entry.service = parsed.service\n return entry\n } catch {\n return undefined\n }\n}\n\nfunction renderLine(\n service: string,\n stream: 'stdout' | 'stderr',\n line: string,\n write: (s: string) => void,\n): void {\n if (line.length === 0) return\n\n const prefix = `[${service}]`\n const streamMarker = stream === 'stderr' ? '!' : ' '\n\n const parsed = tryParseJson(line)\n if (parsed) {\n const level = parsed.level ?? 'info'\n const msg = parsed.message ?? line\n write(`${prefix}${streamMarker}${level.toUpperCase()} ${msg}\\n`)\n return\n }\n\n write(`${prefix}${streamMarker}${line}\\n`)\n}\n\nexport function createLogMerger(options: LogMergerOptions): LogMerger {\n return {\n onLog(service, stream, chunk) {\n // Multi-line chunks: split by \\n and render each\n const lines = chunk.split('\\n')\n for (const line of lines) {\n renderLine(service, stream, line, options.write)\n }\n },\n }\n}\n","/**\n * Pure helpers extracted from process-spawn.ts (T2.2) for unit testability.\n *\n * The full spawn orchestration (child_process + healthcheck poll + log\n * merge) lives in process-spawn.ts; this file holds the parts that are\n * safe to test without mocking node:child_process.\n *\n * EC-7: lifecycle handlers prevent orphan children on parent exit/signal.\n * EC-8: auto-injected env vars (THEOKIT_SERVICE_NAME, THEOKIT_SERVICE_PORT).\n */\nimport type { ServiceDefinition } from '../schema.js'\n\n/**\n * Build the env passed to `child_process.spawn`.\n *\n * Precedence (low → high):\n * 1. process.env (the parent's environment)\n * 2. auto-injected THEOKIT_SERVICE_NAME + THEOKIT_SERVICE_PORT\n * 3. service.env (user-provided overrides win)\n */\nexport function buildSpawnEnv(\n name: string,\n service: ServiceDefinition,\n parentEnv: Record<string, string | undefined>,\n): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [k, v] of Object.entries(parentEnv)) {\n if (typeof v === 'string') env[k] = v\n }\n env.THEOKIT_SERVICE_NAME = name\n env.THEOKIT_SERVICE_PORT = String(service.port)\n if (service.env) {\n for (const [k, v] of Object.entries(service.env)) {\n env[k] = v\n }\n }\n return env\n}\n\n/**\n * Format a service name as a log prefix. Deterministic; ANSI codes added\n * by the log-merge layer (T2.3), not here.\n */\nexport function formatLogPrefix(name: string): string {\n return `[${name}]`\n}\n\n/**\n * Install parent-process lifecycle handlers (EC-7).\n *\n * - `exit`: best-effort SIGKILL of all children (synchronous; we cannot await here)\n * - `SIGINT`: graceful stopAllServices then exit 130\n * - `SIGTERM`: graceful stopAllServices then exit 143\n *\n * SIGKILL on the parent is uncatchable (kernel-level); orphan children\n * are documented as a known limit on force-close (EC-27 doc).\n */\nexport function installLifecycleHandlers(proc: NodeJS.Process, stopAll: () => Promise<void>): void {\n proc.on('exit', () => {\n // Best-effort sync notify; cannot await\n })\n proc.on('SIGINT', () => {\n void stopAll().finally(() => {\n proc.exit(130)\n })\n })\n proc.on('SIGTERM', () => {\n void stopAll().finally(() => {\n proc.exit(143)\n })\n })\n}\n","/**\n * TheoCloud adapter scaffolding (T3.5 — Wave 2 stub; full Wave 3).\n *\n * Wave 2 establishes the contract: the adapter CONSUMES `.theokit/services.json`\n * (manifest emitted by `theokit build`) and produces TheoCloud deployment\n * artifacts. The artifacts themselves (K8s manifests, Helm charts, etc.) are\n * Wave 3 deliverables — this module provides the read/validate gate so the\n * manifest format is locked NOW.\n *\n * Per ADR-0012 invariant #4, the same `.theokit/services.json` consumed by\n * the `node` adapter (docker-compose generator) is the same shape consumed\n * here. No platform-specific fields. The contract is global.\n */\nimport type { ServicesManifest } from './manifest.js'\n\nexport interface TheoCloudAdapterArtifacts {\n /** Manifest schemaVersion the adapter consumed. */\n manifestVersion: 1\n /** Service names that will be deployed. */\n services: string[]\n /** Wave 3 will populate K8s manifests here. */\n k8sManifests?: never\n /** Wave 3 will populate Helm values here. */\n helmValues?: never\n}\n\n/**\n * Wave 2 stub — validates the manifest is consumable. Throws if shape is\n * unexpected (forward-compat guard for Wave 3 development).\n *\n * Wave 3 will replace the body with real K8s manifest emission.\n */\nexport function prepareTheoCloudArtifacts(\n manifest: ServicesManifest | null,\n): TheoCloudAdapterArtifacts {\n if (manifest === null) {\n return { manifestVersion: 1, services: [] }\n }\n // Forward-compat: when Wave 3 evolves the manifest schema, the adapter\n // must bump version handling explicitly.\n\n if (manifest.version !== 1) {\n throw new Error(\n `TheoCloud adapter: unsupported manifest version ${String(manifest.version)}. ` +\n `Wave 2/3 expects schemaVersion 1. Update the adapter before bumping.`,\n )\n }\n return {\n manifestVersion: 1,\n services: manifest.services.map((s) => s.name),\n }\n}\n","/**\n * Builds a Vite `server.proxy` configuration from TheoKit's\n * declarative `services: {}` config (T2.1).\n *\n * Pure function — no Vite imports, just data shaping. The Vite plugin\n * (services-dev.ts) calls this and merges the result into `vite.config.server.proxy`.\n *\n * Pattern follows Vite proxy reference (referencias/vite/packages/vite/src/node/server/middlewares/proxy.ts):\n * - Each path prefix becomes its own entry\n * - `changeOrigin: true` set by default (matches Vite's string-shortcut behavior)\n * - User-set entries take precedence on prefix collision (we never clobber)\n */\nimport type { ServicesConfig } from '../schema.js'\n\n/**\n * Shape compatible with Vite's `server.proxy` type. We intentionally don't\n * import Vite's `ProxyOptions` so this module stays platform-neutral and\n * unit-testable without Vite.\n */\nexport interface ViteProxyEntry {\n target: string\n changeOrigin: boolean\n rewrite?: (path: string) => string\n}\n\nexport type ViteProxyConfig = Record<string, string | ViteProxyEntry>\n\nexport function buildServicesProxyConfig(\n services: ServicesConfig,\n userProxy: ViteProxyConfig = {},\n): ViteProxyConfig {\n const fromServices: ViteProxyConfig = {}\n for (const [, def] of Object.entries(services)) {\n const prefix = def.proxy\n fromServices[prefix] = {\n target: `http://localhost:${String(def.port)}`,\n changeOrigin: true,\n // Strip the service's `proxy` prefix from the upstream URL so the\n // sidecar receives its own native paths (e.g. `/api/agent/echo` →\n // `/echo`). The sidecar declares routes against its own root path —\n // it doesn't know about the TheoKit proxy prefix.\n rewrite: (path: string) =>\n path.startsWith(prefix) ? path.slice(prefix.length) || '/' : path,\n }\n }\n // User proxy wins on collision (we add services first, then spread user on top)\n return { ...fromServices, ...userProxy }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
1
+ {"version":3,"sources":["../src/services/adapters-bridge/adapter-support.ts","../src/services/generators/caddy-generator.ts","../src/services/generators/compose-generator.ts","../src/services/generators/openapi-client-gen.ts","../src/services/adapters-bridge/manifest.ts","../src/services/schema.ts","../src/services/runtime/orchestrator.ts","../src/services/runtime/healthcheck-poller.ts","../src/services/runtime/log-merge.ts","../src/services/runtime/process-spawn-helpers.ts","../src/services/adapters-bridge/theo-cloud-adapter-stub.ts","../src/services/adapters-bridge/vite-proxy-builder.ts"],"sourcesContent":["/**\n * Adapter support gates (Wave 2 — TheoCloud-first focus).\n *\n * Wave 2 SUPPORTS polyglot `services: {}` on TWO targets ONLY:\n * - `node` (local docker-compose harness — TheoCloud-shaped)\n * - `theo-cloud` (the principal deploy target — Wave 3 adapter)\n *\n * All other in-tree deploy adapters (vercel, cloudflare, bun, deno-deploy,\n * aws-lambda, netlify, static) ARE STILL FIRST-CLASS DEPLOY TARGETS for\n * the TS app, but `services: {}` Wave 2 is NOT yet wired through them.\n * They reject loudly with an actionable message when the manifest has\n * non-empty services — pointing the user at `node` (local) or TheoCloud.\n *\n * Per owner decision 2026-05-27: TheoKit's polyglot services energy is\n * 100% TheoCloud; Vercel/Cloudflare/etc. polyglot-services wire-ups are\n * out of Wave 2 scope and deferred to fresh ADRs if demand emerges.\n */\nimport type { ServicesManifest } from './manifest.js'\n\nconst SUPPORTED_IN_WAVE_2 = ['node (local)', 'theo-cloud (Wave 3)'] as const\n\n/**\n * Reject if the adapter does not support polyglot services. Adapters\n * outside `node` + `theo-cloud` call this; the message points to the\n * supported alternatives.\n *\n * Throws when manifest has non-empty services. No-op when manifest is null\n * or empty (Wave 1 BC — the app still deploys, just without sidecars).\n */\nexport function assertServicesUnsupported(\n adapterName: string,\n manifest: ServicesManifest | null,\n): void {\n if (!manifest || manifest.services.length === 0) return\n const names = manifest.services.map((s) => s.name).join(', ')\n throw new Error(\n `Adapter '${adapterName}' does not support polyglot services in Wave 2.\\n` +\n `Detected services in theo.config.ts: ${names}.\\n\\n` +\n `Wave 2 supports: ${SUPPORTED_IN_WAVE_2.join(', ')}.\\n` +\n `TheoCloud is the strategic deploy target — the adapter ships in Wave 3.\\n` +\n `For local dev/prod-like validation today, use \\`theokit build --target node\\`\\n` +\n `(emits docker-compose + Caddyfile — TheoCloud-shaped harness).\\n\\n` +\n `See docs/concepts/services.md.`,\n )\n}\n","/**\n * Caddyfile generator (T3.3).\n *\n * Emits a Caddyfile that fronts the TheoKit web app + declared services\n * with W3C trace context propagation enabled (Caddy 2.11+ `tracing` directive).\n *\n * Generated output sits at `<dist>/.theokit/node/Caddyfile`, consumed by the\n * docker-compose stack (T3.3 compose-generator).\n *\n * EC-23: `reverse_proxy` directives are ordered by prefix length DESC.\n * Caddy matches longest-prefix-first when written in order.\n */\nimport type { ServicesManifest } from '../adapters-bridge/manifest.js'\n\nexport interface CaddyfileOptions {\n /** Port Caddy listens on (TheoKit web port; default 3000). */\n port: number\n /** TheoKit web container hostname (compose service name). Default 'web'. */\n webHost: string\n}\n\nfunction reverseProxyLines(servicePath: string, target: string, cors: boolean): string[] {\n const out = [`\\treverse_proxy ${servicePath}* ${target}`]\n if (cors) {\n out.push(\n `\\theader ${servicePath}* Access-Control-Allow-Origin \"*\"`,\n `\\theader ${servicePath}* Access-Control-Allow-Methods \"GET, POST, PUT, DELETE, OPTIONS\"`,\n `\\theader ${servicePath}* Access-Control-Allow-Headers \"Content-Type, Authorization, traceparent, tracestate, baggage\"`,\n )\n }\n return out\n}\n\nexport function generateCaddyfile(\n manifest: ServicesManifest | null,\n options: CaddyfileOptions,\n): string {\n // EC-23: sort services by proxy prefix length DESC so longest matches first\n const services = (manifest?.services ?? [])\n .slice()\n .sort((a, b) => b.proxy.length - a.proxy.length)\n\n const serviceLines = services.flatMap((svc) =>\n reverseProxyLines(svc.proxy, `${svc.name}:${String(svc.port)}`, svc.cors),\n )\n\n const lines: string[] = [\n `:${String(options.port)} {`,\n `\\t# W3C Trace Context propagation (Caddy 2.11+)`,\n `\\ttracing`,\n `\\theader -Server`,\n ...serviceLines,\n `\\treverse_proxy ${options.webHost}:${String(options.port)}`,\n `}`,\n '',\n ]\n return lines.join('\\n')\n}\n","/**\n * docker-compose.yml generator (T3.3).\n *\n * Emits the \"TheoCloud-shaped\" local harness — Caddy ingress in front of\n * web + declared services. Each service has a healthcheck and Caddy\n * `depends_on: service_healthy`.\n *\n * Used by the Node adapter: `theokit build --target node` writes the\n * compose stack to `.theokit/node/docker-compose.yml`.\n */\nimport type { ManifestServiceEntry, ServicesManifest } from '../adapters-bridge/manifest.js'\n\nexport interface ComposeOptions {\n /** Port for the web container (TheoKit). Default 3000. */\n webPort: number\n /** Caddy listening port (default same as webPort — Caddy fronts everything). */\n caddyPort?: number\n /** Project name (compose file `name:` field). */\n projectName?: string\n}\n\nfunction indent(level: number): string {\n return ' '.repeat(level)\n}\n\nfunction healthcheckLines(svc: ManifestServiceEntry): string[] {\n const checker =\n svc.runtime === 'python'\n ? `curl -f http://localhost:${String(svc.port)}${svc.healthcheck} || exit 1`\n : `wget --spider -q http://localhost:${String(svc.port)}${svc.healthcheck} || exit 1`\n return [\n `${indent(2)}healthcheck:`,\n `${indent(3)}test: [\"CMD-SHELL\", \"${checker}\"]`,\n `${indent(3)}interval: 10s`,\n `${indent(3)}timeout: 5s`,\n `${indent(3)}retries: 3`,\n ]\n}\n\nfunction envLines(env: Record<string, string>): string[] {\n const lines: string[] = [`${indent(2)}environment:`]\n for (const [k, v] of Object.entries(env)) {\n lines.push(`${indent(3)}${k}: ${JSON.stringify(v)}`)\n }\n return lines\n}\n\nfunction serviceBlockLines(svc: ManifestServiceEntry): string[] {\n // EC-8: auto-inject convention env vars in the container too\n const env: Record<string, string> = {\n THEOKIT_SERVICE_NAME: svc.name,\n THEOKIT_SERVICE_PORT: String(svc.port),\n ...(svc.env ?? {}),\n }\n return [\n `${indent(1)}${svc.name}:`,\n `${indent(2)}build:`,\n `${indent(3)}context: ./services/${svc.name}`,\n `${indent(2)}expose:`,\n `${indent(3)}- \"${String(svc.port)}\"`,\n ...envLines(env),\n ...healthcheckLines(svc),\n ]\n}\n\nfunction caddyBlockLines(caddyPort: number, services: ManifestServiceEntry[]): string[] {\n const depends: string[] = [\n `${indent(2)}depends_on:`,\n `${indent(3)}web:`,\n `${indent(4)}condition: service_healthy`,\n ]\n for (const svc of services) {\n depends.push(`${indent(3)}${svc.name}:`, `${indent(4)}condition: service_healthy`)\n }\n return [\n `${indent(1)}caddy:`,\n `${indent(2)}image: caddy:2.11`,\n `${indent(2)}ports:`,\n `${indent(3)}- \"${String(caddyPort)}:${String(caddyPort)}\"`,\n `${indent(2)}volumes:`,\n `${indent(3)}- ./Caddyfile:/etc/caddy/Caddyfile:ro`,\n ...depends,\n ]\n}\n\nfunction webBlockLines(webPort: number): string[] {\n return [\n `${indent(1)}web:`,\n `${indent(2)}build:`,\n `${indent(3)}context: .`,\n `${indent(3)}dockerfile: Dockerfile`,\n `${indent(2)}expose:`,\n `${indent(3)}- \"${String(webPort)}\"`,\n `${indent(2)}healthcheck:`,\n `${indent(3)}test: [\"CMD-SHELL\", \"wget --spider -q http://localhost:${String(webPort)}/api/health || exit 1\"]`,\n `${indent(3)}interval: 10s`,\n `${indent(3)}timeout: 5s`,\n `${indent(3)}retries: 3`,\n ]\n}\n\nexport function generateComposeYaml(\n manifest: ServicesManifest | null,\n options: ComposeOptions,\n): string {\n const services = manifest?.services ?? []\n const webPort = options.webPort\n const caddyPort = options.caddyPort ?? webPort\n\n const projectLines = options.projectName ? [`name: ${options.projectName}`] : []\n\n const lines: string[] = [\n ...projectLines,\n `services:`,\n ...caddyBlockLines(caddyPort, services),\n ...webBlockLines(webPort),\n ...services.flatMap(serviceBlockLines),\n '',\n ]\n return lines.join('\\n')\n}\n","/**\n * OpenAPI → TypeScript client generation (T5.1).\n *\n * Thin wrapper around `@hey-api/openapi-ts` (the de facto 2026 generator\n * used by Vercel/OpenCode/PayPal). Called by the Vite plugin\n * `services-typed-client.ts` at dev startup and when an OpenAPI URL\n * changes.\n *\n * Production behavior:\n * - For each service with a `openapi` URL, fetch the spec\n * - Run Hey API generator to write `<cwd>/clients/<service-name>.ts`\n * - On any failure: log warning, do NOT crash dev (best-effort)\n *\n * The actual `@hey-api/openapi-ts` invocation is dynamic-imported so\n * that consumers without the dep (TS-only Wave 1 apps) don't pay\n * the bundle cost.\n */\nimport type { ManifestServiceEntry } from '../adapters-bridge/manifest.js'\n\nexport interface GenerateClientOptions {\n service: ManifestServiceEntry\n /** Directory to write `<service-name>.ts` into. */\n outputDir: string\n /** Logger for warnings/info. */\n log?: (level: 'info' | 'warn' | 'error', msg: string) => void\n /** Test injection — replace fetch (so tests don't hit the network). */\n customFetch?: typeof fetch\n}\n\nexport interface GenerateClientResult {\n generated: boolean\n outputFile?: string\n skippedReason?: string\n}\n\n/**\n * Generate a typed client for one service. No-op (returns skipped=true)\n * if the service has no `openapi` URL.\n *\n * The generator runs the Hey API tool. If the tool import fails (not\n * installed), the function logs a warning and returns `{ generated: false }`.\n */\nexport async function generateTypedClient(\n options: GenerateClientOptions,\n): Promise<GenerateClientResult> {\n const log =\n options.log ??\n ((_level: 'info' | 'warn' | 'error', _msg: string) => {\n // default: silent in production; tests inject their own\n })\n const { service, outputDir } = options\n\n if (!service.openapi) {\n return { generated: false, skippedReason: 'no openapi URL declared' }\n }\n\n const f = options.customFetch ?? fetch\n let spec: unknown\n try {\n const res = await f(service.openapi)\n if (!res.ok) {\n log('warn', `[${service.name}] openapi fetch returned ${String(res.status)}; skipping`)\n return { generated: false, skippedReason: `fetch returned ${String(res.status)}` }\n }\n spec = await res.json()\n } catch (err) {\n log(\n 'warn',\n `[${service.name}] openapi fetch failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n return { generated: false, skippedReason: 'fetch failed' }\n }\n\n // Dynamic import — soft dep. We pass through a variable so the typechecker\n // doesn't resolve the literal at build time (the dep is optional;\n // consumers without it get a graceful skip).\n let createClient: unknown\n try {\n // Soft-dep resolution. We pass the module name through a String wrapper\n // call site that the typechecker cannot statically resolve — so missing\n // dep at typecheck time does not break the build. Runtime behavior is\n // identical to `import('@hey-api/openapi-ts')`.\n const segment1 = '@hey-api/'\n const segment2 = 'openapi-ts'\n const moduleName = `${segment1}${segment2}`\n const dyn: Promise<unknown> = import(moduleName).catch(() => null)\n const mod = (await dyn) as { createClient?: unknown } | null\n createClient = mod?.createClient\n } catch {\n createClient = undefined\n }\n\n if (typeof createClient !== 'function') {\n log(\n 'warn',\n `[${service.name}] @hey-api/openapi-ts not installed; typed client not generated. ` +\n `Run \\`pnpm add -D @hey-api/openapi-ts @hey-api/client-fetch\\` to enable.`,\n )\n return { generated: false, skippedReason: 'hey-api not installed' }\n }\n\n const outputFile = `${outputDir}/${service.name}.ts`\n try {\n await (createClient as (cfg: unknown) => Promise<unknown>)({\n input: spec,\n output: { path: outputDir, format: 'prettier' },\n plugins: [{ name: '@hey-api/client-fetch' }],\n })\n log('info', `[${service.name}] typed client generated at ${outputFile}`)\n return { generated: true, outputFile }\n } catch (err) {\n log(\n 'warn',\n `[${service.name}] Hey API generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n return { generated: false, skippedReason: 'generator threw' }\n }\n}\n","/**\n * Neutral cross-product manifest (T1.4).\n *\n * Emitted by `theokit build` at `<cwd>/.theokit/services.json` (schemaVersion 1).\n * Consumed by EVERY deploy adapter (Vercel, Node, Cloudflare, future TheoCloud).\n *\n * Shape is INTENTIONALLY platform-neutral (ADR-0015 invariant + D5). No\n * `vercel`/`cloudflare`/`theoCloud` keys — platform-specific tuning lives in\n * `theo.config.ts` and is read by each adapter's own code, NOT serialized\n * into this manifest.\n *\n * Topological ordering enforced (dependsOn-resolved deps first) so adapters\n * that need boot order (docker-compose, K8s) can consume the array verbatim.\n */\n/* eslint-disable security/detect-non-literal-fs-filename --\n * Manifest read/write paths are derived from the trusted `cwd` plus a fixed\n * subpath (`.theokit/services.json`). No user input flows into the path.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nimport type { ServiceDefinition, ServicesConfig } from '../schema.js'\n\n/**\n * Plan v1.2 T2.2 — service shape enum, mirrored from\n * `theo-cloud/api/internal/source/services.schema.json`. Optional in\n * services.json v2; TheoCloud Go-side defaults to `server` when absent.\n */\n// `frontend` removed in simplify-deploy-theokit-only v2.0 (D5) — TheoCloud\n// serves no static frontends; service shape is server | worker only.\nexport type ManifestServiceType = 'server' | 'worker'\n\nexport interface ManifestServiceEntry {\n name: string\n runtime: 'python' | 'node'\n /** Plan v1.2 T2.2 — service shape. Omit to keep default `server`. */\n type?: ManifestServiceType\n port: number\n proxy: string\n dev: string\n build?: string\n start: string\n openapi?: string\n healthcheck: string\n cors: boolean\n env?: Record<string, string>\n dependsOn?: string[]\n passSetCookie: boolean\n}\n\n/**\n * Plan v1.2 T2.1 — services.json now ships in 2 shapes:\n *\n * v1 (deprecated, sunset theokit 0.6.0): { version: 1, services: [...] }\n * v2 (current): { version: 2, project: <name>, services: [...] }\n *\n * `buildManifest()` selects which version to emit based on whether a\n * project name is supplied. Consumers (TheoCloud Go-side validator)\n * accept both via the JSON Schema 7 `oneOf` block.\n */\nexport interface ServicesManifestV1 {\n version: 1\n services: ManifestServiceEntry[]\n}\n\nexport interface ServicesManifestV2 {\n version: 2\n project: string\n services: ManifestServiceEntry[]\n}\n\nexport type ServicesManifest = ServicesManifestV1 | ServicesManifestV2\n\nconst MANIFEST_RELATIVE_PATH = ['.theokit', 'services.json'] as const\n\n/**\n * Topological sort using Kahn's algorithm.\n * Returns service names in dependency order (deps before dependants).\n * Schema validation guarantees no cycles, no self-deps, no missing references —\n * but we still defensively handle missing deps as no-op.\n */\nfunction topoSort(services: ServicesConfig): string[] {\n const names = Object.keys(services)\n const indeg: Record<string, number> = Object.fromEntries(names.map((n) => [n, 0]))\n const adj: Record<string, string[]> = Object.fromEntries(names.map((n) => [n, []]))\n\n const cmp = (a: string, b: string) => a.localeCompare(b)\n\n for (const name of names) {\n const deps = services[name].dependsOn ?? []\n for (const dep of deps) {\n if (!(dep in indeg)) continue\n adj[dep].push(name)\n indeg[name] = (indeg[name] ?? 0) + 1\n }\n }\n\n // Sort initial roots for determinism\n const queue: string[] = names.filter((n) => indeg[n] === 0).sort(cmp)\n const result: string[] = []\n while (queue.length > 0) {\n const cur = queue.shift()\n if (cur === undefined) break\n result.push(cur)\n const adjacent = (adj[cur] ?? []).slice().sort(cmp)\n for (const next of adjacent) {\n indeg[next] = (indeg[next] ?? 0) - 1\n if (indeg[next] === 0) {\n queue.push(next)\n }\n }\n }\n return result.length === names.length ? result : names // fallback (should not hit; schema rejects cycles)\n}\n\nfunction definitionToEntry(name: string, def: ServiceDefinition): ManifestServiceEntry {\n const entry: ManifestServiceEntry = {\n name,\n runtime: def.runtime,\n port: def.port,\n proxy: def.proxy,\n dev: def.dev,\n start: def.start,\n healthcheck: def.healthcheck,\n cors: def.cors,\n passSetCookie: def.passSetCookie,\n }\n // Plan v1.2 T2.2 — only emit `type` when explicitly set so v1 fixtures\n // (no type field at all) stay byte-identical.\n if (def.type !== undefined) entry.type = def.type\n if (def.build !== undefined) entry.build = def.build\n if (def.openapi !== undefined) entry.openapi = def.openapi\n if (def.env !== undefined) entry.env = def.env\n if (def.dependsOn !== undefined) entry.dependsOn = [...def.dependsOn]\n return entry\n}\n\n/**\n * Build a services manifest. Plan v1.2 T2.1: pass a `project` name to emit\n * v2; omit it to emit v1 (deprecated, accepted by TheoCloud until 0.6.0\n * sunset).\n */\nexport function buildManifest(services: ServicesConfig, project?: string): ServicesManifest {\n const ordered = topoSort(services)\n const entries = ordered.map((name) => definitionToEntry(name, services[name]))\n if (project !== undefined && project.length > 0) {\n return { version: 2, project, services: entries }\n }\n return { version: 1, services: entries }\n}\n\nfunction manifestPath(cwd: string): string {\n return join(cwd, ...MANIFEST_RELATIVE_PATH)\n}\n\n/**\n * Write the manifest to `<cwd>/.theokit/services.json`.\n *\n * EC-6 fix: creates `.theokit/` recursively if absent (fresh project on first\n * `pnpm build` would otherwise hit ENOENT).\n */\nexport function writeManifest(cwd: string, manifest: ServicesManifest): void {\n const file = manifestPath(cwd)\n mkdirSync(dirname(file), { recursive: true })\n writeFileSync(file, JSON.stringify(manifest, null, 2), 'utf-8')\n}\n\n/**\n * Read the manifest from `<cwd>/.theokit/services.json`.\n *\n * Returns null if the file does not exist (adapter's job to handle).\n * Throws with an actionable message if the file is malformed JSON.\n */\nexport function readManifest(cwd: string): ServicesManifest | null {\n const file = manifestPath(cwd)\n if (!existsSync(file)) return null\n const raw = readFileSync(file, 'utf-8')\n try {\n return JSON.parse(raw) as ServicesManifest\n } catch (err) {\n throw new Error(\n `failed to parse services.json at ${file}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n }\n}\n","/**\n * Wave 2 — Polyglot Services Orchestration (T1.1).\n *\n * Declarative `services: {}` primitive for `theo.config.ts`. Each entry\n * declares an external sidecar process (Python FastAPI / Node Hono) that\n * boots alongside the TheoKit TS app. Empty `services: {}` is the default\n * and preserves Wave 1 behavior (no impact on TS-only apps).\n *\n * See ADRs 0012-0015 + plan: docs/plans/wave-2-polyglot-services-plan.md\n */\nimport { z } from 'zod'\n\n/** Wave 2 runtime kinds. Go/Rust/Java/Ruby/PHP archived; deferred per ADR-0012 invariant #2/#3. */\nconst ServiceRuntimeSchema = z.enum(['python', 'node'])\n\n/**\n * Service shape enum, mirrored from `services.schema.json`: server | worker.\n * Optional; emitters default to \"server\". `frontend` removed in\n * simplify-deploy-theokit-only v2.0 (D5) — TheoCloud serves no static frontends.\n */\nconst ServiceTypeSchema = z.enum(['server', 'worker'])\n\n/** EC-3 fix: names that conflict with generated docker-compose entries. */\nconst RESERVED_SERVICE_NAMES = ['web', 'caddy', 'postgres', 'redis'] as const\n\n/**\n * EC-12 fix: service names must be docker-compose-safe — lowercase,\n * start with a letter, contain only a-z 0-9 -. Reserved names rejected.\n */\nconst ServiceNameSchema = z\n .string()\n .min(1)\n .regex(\n /^[a-z][a-z0-9-]*$/,\n 'service name must be lowercase, start with letter, contain only a-z 0-9 -',\n )\n .refine((n) => !(RESERVED_SERVICE_NAMES as readonly string[]).includes(n), {\n message: `service name conflicts with reserved name (${RESERVED_SERVICE_NAMES.join('/')})`,\n })\n\n/**\n * Single service definition. All commands run from `services/<name>/` cwd.\n *\n * EC-4 fix: `proxy` regex requires NON-EMPTY path after `/` (the `+` quantifier)\n * to reject `/` which would catch-all and conflict with TheoKit's own routing.\n */\nconst ServiceDefinitionSchema = z.object({\n runtime: ServiceRuntimeSchema,\n type: ServiceTypeSchema.optional(),\n port: z.number().int().min(1).max(65535),\n proxy: z.string().regex(/^\\/[a-zA-Z0-9\\-_/]+$/, 'proxy must be a non-root path starting with /'),\n dev: z.string().min(1),\n build: z.string().optional(),\n start: z.string().min(1),\n openapi: z.url().optional(),\n healthcheck: z.string().regex(/^\\//, 'healthcheck must start with /').default('/health'),\n cors: z.boolean().default(false),\n env: z.record(z.string(), z.string()).optional(),\n dependsOn: z.array(z.string()).optional(),\n /**\n * EC-25 + ref doc §8: by default the proxy strips upstream Set-Cookie\n * to prevent the polyglot service from issuing cookies that conflict\n * with TheoKit's encrypted session. Set to true to opt-in.\n */\n passSetCookie: z.boolean().default(false),\n})\n\nexport type ServiceDefinition = z.infer<typeof ServiceDefinitionSchema>\nexport type ServicesConfig = Record<string, ServiceDefinition>\n\n/**\n * Topological-order helper used by `dependsOn` cycle detection refine.\n * Returns true iff `graph` is a DAG. Each node's deps must all reference\n * existing nodes; cycles return false.\n */\nfunction isDag(graph: Record<string, readonly string[]>): boolean {\n const WHITE = 0\n const GRAY = 1\n const BLACK = 2\n const colors: Record<string, 0 | 1 | 2> = {}\n for (const node of Object.keys(graph)) colors[node] = WHITE\n\n function visit(node: string): boolean {\n if (colors[node] === GRAY) return false // cycle\n if (colors[node] === BLACK) return true\n colors[node] = GRAY\n for (const dep of graph[node] ?? []) {\n if (!(dep in graph)) return false // missing reference\n if (!visit(dep)) return false\n }\n colors[node] = BLACK\n return true\n }\n\n for (const node of Object.keys(graph)) {\n if (colors[node] === WHITE && !visit(node)) return false\n }\n return true\n}\n\n/**\n * Full services config schema with cross-service refines.\n *\n * EC-1 fix: detect duplicate ports across services.\n * EC-13: empty `dependsOn: []` accepted as no-deps.\n * Self-dep, missing-ref, and cycles rejected via topological check.\n */\nexport const servicesConfigSchema = z\n .record(ServiceNameSchema, ServiceDefinitionSchema)\n .default({})\n // EC-1: duplicate port detection across services\n .refine(\n (s) => {\n const ports = Object.values(s).map((v) => v.port)\n return new Set(ports).size === ports.length\n },\n {\n message: 'duplicate port across services — each service must bind a unique port',\n },\n )\n // duplicate proxy prefix detection\n .refine(\n (s) => {\n const prefixes = Object.values(s).map((v) => v.proxy)\n return new Set(prefixes).size === prefixes.length\n },\n { message: 'duplicate proxy prefix across services' },\n )\n // dependsOn correctness (self-dep, missing reference, cycle)\n .refine(\n (s) => {\n // Build graph\n const graph: Record<string, readonly string[]> = {}\n for (const [name, def] of Object.entries(s)) {\n graph[name] = def.dependsOn ?? []\n }\n // Self-dep: a service mentioning itself is rejected as part of cycle detection\n for (const [name, deps] of Object.entries(graph)) {\n if (deps.includes(name)) return false\n }\n return isDag(graph)\n },\n {\n message: 'invalid dependsOn — must reference existing services, no self-deps, no cycles',\n },\n )\n\nexport type ServicesConfigInput = z.input<typeof servicesConfigSchema>\nexport type ServicesConfigOutput = z.output<typeof servicesConfigSchema>\n","/**\n * Dev orchestration entry point (T2.4).\n *\n * Spawns declared polyglot services, waits for all healthchecks to pass,\n * then signals readiness. The `theokit dev` CLI calls `orchestrateDev`\n * BEFORE starting Vite — Vite only boots after all services healthy.\n *\n * Empty `services: {}` → no-op (Wave 1 BC).\n *\n * Single composable entry that the CLI consumes. Spawn/healthcheck/log\n * primitives live in their own modules; this file ties them together.\n */\nimport type { ChildProcess, SpawnOptions } from 'node:child_process'\nimport { spawn } from 'node:child_process'\nimport { resolve } from 'node:path'\n\nimport type { ServiceDefinition, ServicesConfig } from '../schema.js'\n\nimport { pollHealthcheck } from './healthcheck-poller.js'\nimport { createLogMerger } from './log-merge.js'\nimport { buildSpawnEnv, installLifecycleHandlers } from './process-spawn-helpers.js'\n\nexport interface SpawnedService {\n name: string\n port: number\n process: ChildProcess\n}\n\nexport interface OrchestrateDevOptions {\n cwd: string\n services: ServicesConfig\n /** Defaults to `process.stdout.write.bind(process.stdout)`. */\n write?: (s: string) => void\n /** Test injection — replace child_process.spawn. */\n spawnFn?: typeof spawn\n /** Test injection — replace global fetch (for healthchecks). */\n customFetch?: typeof fetch\n /** Healthcheck timeout per service. Default 30_000. */\n healthcheckTimeoutMs?: number\n /** Whether to install parent lifecycle handlers (EC-7). Default true. */\n installSignalHandlers?: boolean\n}\n\nexport interface OrchestrateDevResult {\n spawned: SpawnedService[]\n /** Whether ALL services passed healthcheck. */\n allHealthy: boolean\n /** Services that timed out (only populated when !allHealthy). */\n unhealthy: string[]\n /** Call to gracefully stop all spawned services. */\n stop: () => Promise<void>\n}\n\nfunction spawnService(\n name: string,\n service: ServiceDefinition,\n cwd: string,\n options: {\n spawnFn: typeof spawn\n onLog: (s: string, stream: 'stdout' | 'stderr', line: string) => void\n },\n): SpawnedService {\n const env = buildSpawnEnv(name, service, process.env)\n const spawnOpts: SpawnOptions = {\n cwd,\n shell: true,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n }\n const child = options.spawnFn(service.dev, spawnOpts)\n child.stdout?.setEncoding('utf-8')\n child.stderr?.setEncoding('utf-8')\n child.stdout?.on('data', (chunk: string) => {\n options.onLog(name, 'stdout', chunk)\n })\n child.stderr?.on('data', (chunk: string) => {\n options.onLog(name, 'stderr', chunk)\n })\n return { name, port: service.port, process: child }\n}\n\nasync function stopSpawned(s: SpawnedService): Promise<void> {\n return new Promise<void>((resolve) => {\n if (s.process.killed || s.process.exitCode !== null) {\n resolve()\n return\n }\n const timer = setTimeout(() => {\n s.process.kill('SIGKILL')\n resolve()\n }, 5_000)\n s.process.once('exit', () => {\n clearTimeout(timer)\n resolve()\n })\n s.process.kill('SIGTERM')\n })\n}\n\nexport async function orchestrateDev(\n options: OrchestrateDevOptions,\n): Promise<OrchestrateDevResult> {\n const entries = Object.entries(options.services)\n if (entries.length === 0) {\n return {\n spawned: [],\n allHealthy: true,\n unhealthy: [],\n stop: () => Promise.resolve(),\n }\n }\n\n const write =\n options.write ??\n ((s: string) => {\n process.stdout.write(s)\n })\n const spawnFn = options.spawnFn ?? spawn\n const merger = createLogMerger({ write })\n\n const spawned: SpawnedService[] = entries.map(([name, def]) =>\n spawnService(name, def, resolve(options.cwd, 'services', name), {\n spawnFn,\n onLog: merger.onLog,\n }),\n )\n\n const stop = async (): Promise<void> => {\n await Promise.all(spawned.map(stopSpawned))\n }\n\n if (options.installSignalHandlers !== false) {\n installLifecycleHandlers(process, stop)\n }\n\n // Parallel healthcheck\n const results = await Promise.all(\n entries.map(([name, def]) =>\n pollHealthcheck({\n url: `http://localhost:${String(def.port)}${def.healthcheck}`,\n timeoutMs: options.healthcheckTimeoutMs ?? 30_000,\n intervalMs: 500,\n customFetch: options.customFetch,\n }).then((r) => ({ name, result: r })),\n ),\n )\n\n const unhealthy = results.filter((r) => !r.result.healthy).map((r) => r.name)\n return {\n spawned,\n allHealthy: unhealthy.length === 0,\n unhealthy,\n stop,\n }\n}\n","/**\n * Healthcheck poller (T1.5).\n *\n * Polls `GET <url>` with backoff until 200 OR timeout. Used by `pnpm dev`\n * (T2.4) to gate readiness on declared services being healthy before\n * starting Vite.\n *\n * Invariants:\n * - Returns within `timeoutMs + intervalMs` (no hang)\n * - Never throws (returns `{ healthy: false }` on any error)\n * - `attempts >= 1` always\n * - Respects external AbortSignal (pre-aborted → immediate return, EC-18)\n */\n\nexport interface HealthcheckOptions {\n /** Full URL to poll, e.g. 'http://localhost:8001/health' */\n url: string\n /** Total time budget in ms. Default 30_000. */\n timeoutMs?: number\n /** Sleep between attempts in ms. Default 500. */\n intervalMs?: number\n /** Optional external cancel. Aborted signal causes early return. */\n signal?: AbortSignal\n /** Test injection — replace global fetch. */\n customFetch?: typeof fetch\n}\n\nexport interface HealthcheckResult {\n healthy: boolean\n attempts: number\n durationMs: number\n lastError?: string\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve) => {\n if (signal?.aborted) {\n resolve()\n return\n }\n const t = setTimeout(() => {\n resolve()\n }, ms)\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(t)\n resolve()\n },\n { once: true },\n )\n })\n}\n\nexport async function pollHealthcheck(options: HealthcheckOptions): Promise<HealthcheckResult> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const intervalMs = options.intervalMs ?? 500\n const f = options.customFetch ?? fetch\n const start = Date.now()\n let attempts = 0\n let lastError: string | undefined\n\n // EC-18: signal already aborted → return immediately with at least 1 attempt counted\n if (options.signal?.aborted) {\n return {\n healthy: false,\n attempts: 1,\n durationMs: Date.now() - start,\n lastError: 'aborted',\n }\n }\n\n // Infinite poll loop terminated by status === 200 OR timeout OR abort.\n for (;;) {\n if (options.signal?.aborted) {\n return {\n healthy: false,\n attempts: Math.max(attempts, 1),\n durationMs: Date.now() - start,\n lastError: 'aborted',\n }\n }\n attempts++\n try {\n const res = await f(options.url, { method: 'GET', signal: options.signal })\n if (res.status === 200) {\n return { healthy: true, attempts, durationMs: Date.now() - start }\n }\n lastError = `status ${res.status}`\n } catch (err) {\n lastError = err instanceof Error ? err.message : String(err)\n }\n\n if (Date.now() - start >= timeoutMs) {\n return {\n healthy: false,\n attempts,\n durationMs: Date.now() - start,\n lastError,\n }\n }\n await sleep(intervalMs, options.signal)\n }\n}\n","/**\n * Log merger (T2.3).\n *\n * Combines stdout/stderr from multiple polyglot services into TheoKit's\n * dev terminal, prefixed with `[service-name]`. Parses JSON-line logs\n * (ADR-0015 invariant #5) for pretty-printing; falls back to raw line on\n * non-JSON.\n *\n * Pure / synchronous. The Vite plugin (T2.1) wires this as the `onLog`\n * callback passed to spawnServices.\n */\n\ninterface LogEntry {\n level?: string\n message?: string\n timestamp?: string\n traceparent?: string\n service?: string\n}\n\nexport interface LogMergerOptions {\n write: (s: string) => void\n}\n\nexport interface LogMerger {\n onLog: (service: string, stream: 'stdout' | 'stderr', chunk: string) => void\n}\n\n/**\n * Try to parse a log line as JSON. Returns parsed object on success,\n * undefined on failure (will fall back to raw rendering).\n */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v)\n}\n\nfunction tryParseJson(line: string): LogEntry | undefined {\n const trimmed = line.trim()\n if (!trimmed.startsWith('{')) return undefined\n try {\n const parsed: unknown = JSON.parse(trimmed)\n if (!isPlainObject(parsed)) return undefined\n const entry: LogEntry = {}\n if (typeof parsed.level === 'string') entry.level = parsed.level\n if (typeof parsed.message === 'string') entry.message = parsed.message\n if (typeof parsed.timestamp === 'string') entry.timestamp = parsed.timestamp\n if (typeof parsed.traceparent === 'string') entry.traceparent = parsed.traceparent\n if (typeof parsed.service === 'string') entry.service = parsed.service\n return entry\n } catch {\n return undefined\n }\n}\n\nfunction renderLine(\n service: string,\n stream: 'stdout' | 'stderr',\n line: string,\n write: (s: string) => void,\n): void {\n if (line.length === 0) return\n\n const prefix = `[${service}]`\n const streamMarker = stream === 'stderr' ? '!' : ' '\n\n const parsed = tryParseJson(line)\n if (parsed) {\n const level = parsed.level ?? 'info'\n const msg = parsed.message ?? line\n write(`${prefix}${streamMarker}${level.toUpperCase()} ${msg}\\n`)\n return\n }\n\n write(`${prefix}${streamMarker}${line}\\n`)\n}\n\nexport function createLogMerger(options: LogMergerOptions): LogMerger {\n return {\n onLog(service, stream, chunk) {\n // Multi-line chunks: split by \\n and render each\n const lines = chunk.split('\\n')\n for (const line of lines) {\n renderLine(service, stream, line, options.write)\n }\n },\n }\n}\n","/**\n * Pure helpers extracted from process-spawn.ts (T2.2) for unit testability.\n *\n * The full spawn orchestration (child_process + healthcheck poll + log\n * merge) lives in process-spawn.ts; this file holds the parts that are\n * safe to test without mocking node:child_process.\n *\n * EC-7: lifecycle handlers prevent orphan children on parent exit/signal.\n * EC-8: auto-injected env vars (THEOKIT_SERVICE_NAME, THEOKIT_SERVICE_PORT).\n */\nimport type { ServiceDefinition } from '../schema.js'\n\n/**\n * Build the env passed to `child_process.spawn`.\n *\n * Precedence (low → high):\n * 1. process.env (the parent's environment)\n * 2. auto-injected THEOKIT_SERVICE_NAME + THEOKIT_SERVICE_PORT\n * 3. service.env (user-provided overrides win)\n */\nexport function buildSpawnEnv(\n name: string,\n service: ServiceDefinition,\n parentEnv: Record<string, string | undefined>,\n): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [k, v] of Object.entries(parentEnv)) {\n if (typeof v === 'string') env[k] = v\n }\n env.THEOKIT_SERVICE_NAME = name\n env.THEOKIT_SERVICE_PORT = String(service.port)\n if (service.env) {\n for (const [k, v] of Object.entries(service.env)) {\n env[k] = v\n }\n }\n return env\n}\n\n/**\n * Format a service name as a log prefix. Deterministic; ANSI codes added\n * by the log-merge layer (T2.3), not here.\n */\nexport function formatLogPrefix(name: string): string {\n return `[${name}]`\n}\n\n/**\n * Install parent-process lifecycle handlers (EC-7).\n *\n * - `exit`: best-effort SIGKILL of all children (synchronous; we cannot await here)\n * - `SIGINT`: graceful stopAllServices then exit 130\n * - `SIGTERM`: graceful stopAllServices then exit 143\n *\n * SIGKILL on the parent is uncatchable (kernel-level); orphan children\n * are documented as a known limit on force-close (EC-27 doc).\n */\nexport function installLifecycleHandlers(proc: NodeJS.Process, stopAll: () => Promise<void>): void {\n proc.on('exit', () => {\n // Best-effort sync notify; cannot await\n })\n proc.on('SIGINT', () => {\n void stopAll().finally(() => {\n proc.exit(130)\n })\n })\n proc.on('SIGTERM', () => {\n void stopAll().finally(() => {\n proc.exit(143)\n })\n })\n}\n","/**\n * TheoCloud adapter scaffolding (T3.5 — Wave 2 stub; full Wave 3).\n *\n * Wave 2 establishes the contract: the adapter CONSUMES `.theokit/services.json`\n * (manifest emitted by `theokit build`) and produces TheoCloud deployment\n * artifacts. The artifacts themselves (K8s manifests, Helm charts, etc.) are\n * Wave 3 deliverables — this module provides the read/validate gate so the\n * manifest format is locked NOW.\n *\n * Per ADR-0012 invariant #4, the same `.theokit/services.json` consumed by\n * the `node` adapter (docker-compose generator) is the same shape consumed\n * here. No platform-specific fields. The contract is global.\n */\nimport type { ServicesManifest } from './manifest.js'\n\nexport interface TheoCloudAdapterArtifacts {\n /** Manifest schemaVersion the adapter consumed (v1 deprecated, v2 current). */\n manifestVersion: 1 | 2\n /** Service names that will be deployed. */\n services: string[]\n /** Wave 3 will populate K8s manifests here. */\n k8sManifests?: never\n /** Wave 3 will populate Helm values here. */\n helmValues?: never\n}\n\n/**\n * Wave 2 stub — validates the manifest is consumable. Throws if shape is\n * unexpected (forward-compat guard for Wave 3 development).\n *\n * Wave 3 will replace the body with real K8s manifest emission.\n */\nexport function prepareTheoCloudArtifacts(\n manifest: ServicesManifest | null,\n): TheoCloudAdapterArtifacts {\n if (manifest === null) {\n return { manifestVersion: 1, services: [] }\n }\n // v1 (deprecated, sunset 0.6.0) and v2 (current, adds `project`) share the\n // same `services[]` shape the adapter consumes — both are accepted. Any\n // other version is a forward-compat guard: bump handling here before the\n // builder emits a newer schema. (Regression: usetheodev/theokit#9 — the\n // builder emits v2 when a project name is supplied; rejecting v2 broke\n // every `theokit build --target theo-cloud`.)\n //\n // The type says `1 | 2`, but the manifest is read from disk (`readManifest`)\n // so a malformed/newer file can carry any number at runtime — read through a\n // numeric local so the guard stays reachable (narrowing `manifest.version`\n // directly would collapse the guard body to `never`).\n const version: number = manifest.version\n if (version !== 1 && version !== 2) {\n throw new Error(\n `TheoCloud adapter: unsupported manifest version ${String(version)}. ` +\n `Supported: schemaVersion 1 (deprecated) or 2. Update the adapter before bumping.`,\n )\n }\n return {\n manifestVersion: manifest.version,\n services: manifest.services.map((s) => s.name),\n }\n}\n","/**\n * Builds a Vite `server.proxy` configuration from TheoKit's\n * declarative `services: {}` config (T2.1).\n *\n * Pure function — no Vite imports, just data shaping. The Vite plugin\n * (services-dev.ts) calls this and merges the result into `vite.config.server.proxy`.\n *\n * Pattern follows Vite proxy reference (referencias/vite/packages/vite/src/node/server/middlewares/proxy.ts):\n * - Each path prefix becomes its own entry\n * - `changeOrigin: true` set by default (matches Vite's string-shortcut behavior)\n * - User-set entries take precedence on prefix collision (we never clobber)\n */\nimport type { ServicesConfig } from '../schema.js'\n\n/**\n * Shape compatible with Vite's `server.proxy` type. We intentionally don't\n * import Vite's `ProxyOptions` so this module stays platform-neutral and\n * unit-testable without Vite.\n */\nexport interface ViteProxyEntry {\n target: string\n changeOrigin: boolean\n rewrite?: (path: string) => string\n}\n\nexport type ViteProxyConfig = Record<string, string | ViteProxyEntry>\n\nexport function buildServicesProxyConfig(\n services: ServicesConfig,\n userProxy: ViteProxyConfig = {},\n): ViteProxyConfig {\n const fromServices: ViteProxyConfig = {}\n for (const [, def] of Object.entries(services)) {\n const prefix = def.proxy\n fromServices[prefix] = {\n target: `http://localhost:${String(def.port)}`,\n changeOrigin: true,\n // Strip the service's `proxy` prefix from the upstream URL so the\n // sidecar receives its own native paths (e.g. `/api/agent/echo` →\n // `/echo`). The sidecar declares routes against its own root path —\n // it doesn't know about the TheoKit proxy prefix.\n rewrite: (path: string) =>\n path.startsWith(prefix) ? path.slice(prefix.length) || '/' : path,\n }\n }\n // User proxy wins on collision (we add services first, then spread user on top)\n return { ...fromServices, ...userProxy }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
@@ -2,7 +2,7 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  theoConfigSchema
5
- } from "./chunk-BNGBG2SQ.js";
5
+ } from "./chunk-YJAUJXZS.js";
6
6
 
7
7
  // src/config/load-env.ts
8
8
  import { lstatSync, readFileSync, realpathSync, statSync } from "fs";
@@ -231,4 +231,4 @@ export {
231
231
  loadEnv,
232
232
  loadConfig
233
233
  };
234
- //# sourceMappingURL=chunk-IHMJV2OK.js.map
234
+ //# sourceMappingURL=chunk-7YZHAQU7.js.map
@@ -4,7 +4,7 @@ import {
4
4
  generateCaddyfile,
5
5
  generateComposeYaml,
6
6
  readManifest
7
- } from "./chunk-CCVC6P6B.js";
7
+ } from "./chunk-45C3WUQ7.js";
8
8
 
9
9
  // src/adapters/node.ts
10
10
  import { writeFileSync } from "fs";
@@ -62,4 +62,4 @@ var nodeAdapter = {
62
62
  export {
63
63
  nodeAdapter
64
64
  };
65
- //# sourceMappingURL=chunk-EQV67HZL.js.map
65
+ //# sourceMappingURL=chunk-FOZIR3TG.js.map
@@ -2,7 +2,7 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  servicesConfigSchema
5
- } from "./chunk-CCVC6P6B.js";
5
+ } from "./chunk-45C3WUQ7.js";
6
6
 
7
7
  // src/config/schema.ts
8
8
  import { z as z8 } from "zod";
@@ -397,4 +397,4 @@ export {
397
397
  storageSchema,
398
398
  theoConfigSchema
399
399
  };
400
- //# sourceMappingURL=chunk-BNGBG2SQ.js.map
400
+ //# sourceMappingURL=chunk-YJAUJXZS.js.map
package/dist/cli/index.js CHANGED
@@ -5,12 +5,12 @@ import "tsx/esm";
5
5
  import cac from "cac";
6
6
  var cli = cac("theokit");
7
7
  cli.command("dev", "Start development server").option("--port <port>", "Port number").action(async (options) => {
8
- const { devCommand } = await import("../dev-HFOVZWYL.js");
8
+ const { devCommand } = await import("../dev-GBXOTXUP.js");
9
9
  await devCommand({ port: options.port ? Number(options.port) : void 0 });
10
10
  });
11
11
  cli.command("build", "Build for production").option("--target <target>", "Deploy target (node, vercel, cloudflare)").action(async (options) => {
12
12
  try {
13
- const { buildCommand } = await import("../build-LVN3KIE3.js");
13
+ const { buildCommand } = await import("../build-QFRLSEZ4.js");
14
14
  await buildCommand({ target: options.target });
15
15
  } catch (err) {
16
16
  const msg = err instanceof Error ? err.message : String(err);
@@ -22,7 +22,7 @@ cli.command("build", "Build for production").option("--target <target>", "Deploy
22
22
  });
23
23
  cli.command("start", "Start production server").option("--port <port>", "Port number").action(async (options) => {
24
24
  try {
25
- const { startCommand } = await import("../start-N7K7J5OE.js");
25
+ const { startCommand } = await import("../start-3ZHAXSJE.js");
26
26
  await startCommand({ port: options.port ? Number(options.port) : void 0 });
27
27
  } catch (err) {
28
28
  const msg = err instanceof Error ? err.message : String(err);
@@ -49,7 +49,7 @@ cli.command(
49
49
  });
50
50
  cli.command("routes", "List all routes, actions, and WebSocket endpoints").action(async () => {
51
51
  try {
52
- const { routesCommand } = await import("../routes-GHMCCV7V.js");
52
+ const { routesCommand } = await import("../routes-LRYOIIAI.js");
53
53
  await routesCommand();
54
54
  } catch (err) {
55
55
  const msg = err instanceof Error ? err.message : String(err);
@@ -90,7 +90,7 @@ cli.command("add <package>", "Install a known TheoKit adapter or plugin (whiteli
90
90
  await addCommand(pkg);
91
91
  });
92
92
  cli.command("info", "Print environment info (runtime, config, routes)").action(async () => {
93
- const { infoCommand } = await import("../info-DWUBVHHF.js");
93
+ const { infoCommand } = await import("../info-OUEUZOT7.js");
94
94
  await infoCommand();
95
95
  });
96
96
  cli.command(
@@ -98,7 +98,7 @@ cli.command(
98
98
  "Generate <distDir>/openapi.json from route schemas (opt-in via config.openapi)"
99
99
  ).option("--dry-run", "Print the document to stdout without writing to disk (EC-3)").action(async (options) => {
100
100
  try {
101
- const { openapiCommand } = await import("../openapi-NPFP4WZY.js");
101
+ const { openapiCommand } = await import("../openapi-VR6AFBLJ.js");
102
102
  await openapiCommand({ dryRun: Boolean(options.dryRun) });
103
103
  } catch (err) {
104
104
  const msg = err instanceof Error ? err.message : String(err);
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/cloudflare.ts
12
12
  import { mkdirSync, writeFileSync } from "fs";
@@ -119,4 +119,4 @@ export {
119
119
  renderCloudflareWorkerEntry,
120
120
  renderWranglerToml
121
121
  };
122
- //# sourceMappingURL=cloudflare-KHF7JJZ7.js.map
122
+ //# sourceMappingURL=cloudflare-C6E5SPAE.js.map
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/deno-deploy.ts
12
12
  import { mkdirSync, writeFileSync } from "fs";
@@ -104,4 +104,4 @@ export {
104
104
  denoDeployAdapter,
105
105
  renderDenoEntry
106
106
  };
107
- //# sourceMappingURL=deno-deploy-O4JP56BM.js.map
107
+ //# sourceMappingURL=deno-deploy-RFZN56X4.js.map
@@ -8,18 +8,18 @@ import {
8
8
  } from "./chunk-JQSFBJR5.js";
9
9
  import {
10
10
  theoPluginAsync
11
- } from "./chunk-BYS3OYZV.js";
11
+ } from "./chunk-43D6XNDR.js";
12
12
  import "./chunk-PBEH6NXR.js";
13
13
  import {
14
14
  loadConfig,
15
15
  loadEnv
16
- } from "./chunk-IHMJV2OK.js";
16
+ } from "./chunk-7YZHAQU7.js";
17
17
  import "./chunk-NAZ4E2GT.js";
18
18
  import "./chunk-GFMQJHXX.js";
19
- import "./chunk-BNGBG2SQ.js";
19
+ import "./chunk-YJAUJXZS.js";
20
20
  import {
21
21
  orchestrateDev
22
- } from "./chunk-CCVC6P6B.js";
22
+ } from "./chunk-45C3WUQ7.js";
23
23
  import "./chunk-5ODOE6EF.js";
24
24
  import "./chunk-HGZL5EOI.js";
25
25
  import "./chunk-IEES3CHD.js";
@@ -99,4 +99,4 @@ export {
99
99
  devCommand,
100
100
  startDevServer
101
101
  };
102
- //# sourceMappingURL=dev-HFOVZWYL.js.map
102
+ //# sourceMappingURL=dev-GBXOTXUP.js.map
@@ -2,9 +2,9 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  loadConfig
5
- } from "./chunk-IHMJV2OK.js";
6
- import "./chunk-BNGBG2SQ.js";
7
- import "./chunk-CCVC6P6B.js";
5
+ } from "./chunk-7YZHAQU7.js";
6
+ import "./chunk-YJAUJXZS.js";
7
+ import "./chunk-45C3WUQ7.js";
8
8
  import {
9
9
  scanRoutes
10
10
  } from "./chunk-IEES3CHD.js";
@@ -100,4 +100,4 @@ export {
100
100
  buildInfo,
101
101
  infoCommand
102
102
  };
103
- //# sourceMappingURL=info-DWUBVHHF.js.map
103
+ //# sourceMappingURL=info-OUEUZOT7.js.map
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/netlify.ts
12
12
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -147,4 +147,4 @@ export {
147
147
  netlifyAdapter,
148
148
  renderNetlifyFunction
149
149
  };
150
- //# sourceMappingURL=netlify-E63264H6.js.map
150
+ //# sourceMappingURL=netlify-PMLHVPN4.js.map
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+ import {
4
+ nodeAdapter
5
+ } from "./chunk-FOZIR3TG.js";
6
+ import "./chunk-45C3WUQ7.js";
7
+ export {
8
+ nodeAdapter
9
+ };
10
+ //# sourceMappingURL=node-BPJ3Z4DT.js.map
@@ -2,9 +2,9 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  loadConfig
5
- } from "./chunk-IHMJV2OK.js";
6
- import "./chunk-BNGBG2SQ.js";
7
- import "./chunk-CCVC6P6B.js";
5
+ } from "./chunk-7YZHAQU7.js";
6
+ import "./chunk-YJAUJXZS.js";
7
+ import "./chunk-45C3WUQ7.js";
8
8
  import {
9
9
  emitOpenApi,
10
10
  loadRoutesForOpenApi
@@ -79,4 +79,4 @@ function emitOpenApiInMemory(manifest, config) {
79
79
  export {
80
80
  openapiCommand
81
81
  };
82
- //# sourceMappingURL=openapi-NPFP4WZY.js.map
82
+ //# sourceMappingURL=openapi-VR6AFBLJ.js.map
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+
4
+ // src/adapters/registry.ts
5
+ var adapterRegistry = {
6
+ node: async () => (await import("./node-BPJ3Z4DT.js")).nodeAdapter,
7
+ vercel: async () => (await import("./vercel-J6G7ZHYQ.js")).vercelAdapter,
8
+ cloudflare: async () => (await import("./cloudflare-C6E5SPAE.js")).cloudflareAdapter,
9
+ static: async () => (await import("./static-55G3LX2I.js")).staticAdapter,
10
+ bun: async () => (await import("./bun-KP2KES6S.js")).bunAdapter,
11
+ "deno-deploy": async () => (await import("./deno-deploy-RFZN56X4.js")).denoDeployAdapter,
12
+ netlify: async () => (await import("./netlify-PMLHVPN4.js")).netlifyAdapter,
13
+ "aws-lambda": async () => (await import("./aws-lambda-7GSCNLPY.js")).awsLambdaAdapter,
14
+ "theo-cloud": async () => (await import("./theo-cloud-DQRP6S6M.js")).theoCloudAdapter
15
+ };
16
+ async function resolveAdapter(target) {
17
+ const factory = adapterRegistry[target];
18
+ return factory();
19
+ }
20
+ export {
21
+ adapterRegistry,
22
+ resolveAdapter
23
+ };
24
+ //# sourceMappingURL=registry-Q2TZQLUH.js.map
@@ -5,9 +5,9 @@ import {
5
5
  } from "./chunk-JQSFBJR5.js";
6
6
  import {
7
7
  loadConfig
8
- } from "./chunk-IHMJV2OK.js";
9
- import "./chunk-BNGBG2SQ.js";
10
- import "./chunk-CCVC6P6B.js";
8
+ } from "./chunk-7YZHAQU7.js";
9
+ import "./chunk-YJAUJXZS.js";
10
+ import "./chunk-45C3WUQ7.js";
11
11
  import {
12
12
  scanServerActions,
13
13
  scanServerRoutes,
@@ -60,4 +60,4 @@ async function routesCommand() {
60
60
  export {
61
61
  routesCommand
62
62
  };
63
- //# sourceMappingURL=routes-GHMCCV7V.js.map
63
+ //# sourceMappingURL=routes-LRYOIIAI.js.map
@@ -12,8 +12,8 @@ import {
12
12
  storageSchema,
13
13
  theoConfigSchema,
14
14
  uploadSchema
15
- } from "./chunk-BNGBG2SQ.js";
16
- import "./chunk-CCVC6P6B.js";
15
+ } from "./chunk-YJAUJXZS.js";
16
+ import "./chunk-45C3WUQ7.js";
17
17
  export {
18
18
  cacheSchema,
19
19
  corsSchema,
@@ -27,4 +27,4 @@ export {
27
27
  theoConfigSchema,
28
28
  uploadSchema
29
29
  };
30
- //# sourceMappingURL=schema-7K4SFSA3.js.map
30
+ //# sourceMappingURL=schema-7CAY6IZR.js.map
@@ -2,7 +2,7 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  generateTypedClient
5
- } from "./chunk-CCVC6P6B.js";
5
+ } from "./chunk-45C3WUQ7.js";
6
6
 
7
7
  // src/vite-plugin/services-typed-client.ts
8
8
  import { resolve } from "path";
@@ -44,4 +44,4 @@ function servicesTypedClientPlugin(opts) {
44
44
  export {
45
45
  servicesTypedClientPlugin
46
46
  };
47
- //# sourceMappingURL=services-typed-client-6JPFJJ56.js.map
47
+ //# sourceMappingURL=services-typed-client-32KMTTXR.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  loadConfig,
11
11
  loadEnv
12
- } from "./chunk-IHMJV2OK.js";
12
+ } from "./chunk-7YZHAQU7.js";
13
13
  import {
14
14
  buildSecurityHeaders,
15
15
  createPluginRunnerFromConfig,
@@ -23,8 +23,8 @@ import {
23
23
  sendError,
24
24
  warnOnce
25
25
  } from "./chunk-GFMQJHXX.js";
26
- import "./chunk-BNGBG2SQ.js";
27
- import "./chunk-CCVC6P6B.js";
26
+ import "./chunk-YJAUJXZS.js";
27
+ import "./chunk-45C3WUQ7.js";
28
28
  import "./chunk-HGZL5EOI.js";
29
29
  import {
30
30
  loadManifest
@@ -98,7 +98,7 @@ async function configureStorageManagerFromConfig(storageConfig) {
98
98
  if (storageConfig === void 0 || storageConfig === null) return;
99
99
  try {
100
100
  const { getStorageManager } = await import("./storage-manager-ZSQFLEYT.js");
101
- const { storageSchema } = await import("./schema-7K4SFSA3.js");
101
+ const { storageSchema } = await import("./schema-7CAY6IZR.js");
102
102
  const parsed = storageSchema.parse(storageConfig);
103
103
  getStorageManager().configure(parsed);
104
104
  } catch (err) {
@@ -671,4 +671,4 @@ export {
671
671
  resolveSsrEntry,
672
672
  startCommand
673
673
  };
674
- //# sourceMappingURL=start-N7K7J5OE.js.map
674
+ //# sourceMappingURL=start-3ZHAXSJE.js.map
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
  import {
11
11
  scanRoutes
12
12
  } from "./chunk-IEES3CHD.js";
@@ -225,4 +225,4 @@ export {
225
225
  detectApiRoutes,
226
226
  staticAdapter
227
227
  };
228
- //# sourceMappingURL=static-3JXPPDIH.js.map
228
+ //# sourceMappingURL=static-55G3LX2I.js.map
@@ -3,7 +3,7 @@ import "tsx/esm";
3
3
  import {
4
4
  prepareTheoCloudArtifacts,
5
5
  readManifest
6
- } from "./chunk-CCVC6P6B.js";
6
+ } from "./chunk-45C3WUQ7.js";
7
7
 
8
8
  // src/adapters/theo-cloud.ts
9
9
  var theoCloudAdapter = {
@@ -21,4 +21,4 @@ var theoCloudAdapter = {
21
21
  export {
22
22
  theoCloudAdapter
23
23
  };
24
- //# sourceMappingURL=theo-cloud-I3KQE3JN.js.map
24
+ //# sourceMappingURL=theo-cloud-DQRP6S6M.js.map
@@ -2,11 +2,11 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
5
+ } from "./chunk-FOZIR3TG.js";
6
6
  import {
7
7
  assertServicesUnsupported,
8
8
  readManifest
9
- } from "./chunk-CCVC6P6B.js";
9
+ } from "./chunk-45C3WUQ7.js";
10
10
 
11
11
  // src/adapters/vercel.ts
12
12
  import { existsSync, mkdirSync, writeFileSync, cpSync } from "fs";
@@ -130,4 +130,4 @@ export {
130
130
  renderVercelVcConfigJson,
131
131
  vercelAdapter
132
132
  };
133
- //# sourceMappingURL=vercel-6VWQTIUL.js.map
133
+ //# sourceMappingURL=vercel-J6G7ZHYQ.js.map
@@ -7,13 +7,13 @@ import {
7
7
  defineTheoIntegration,
8
8
  theoPlugin,
9
9
  theoPluginAsync
10
- } from "./chunk-BYS3OYZV.js";
10
+ } from "./chunk-43D6XNDR.js";
11
11
  import "./chunk-PBEH6NXR.js";
12
- import "./chunk-IHMJV2OK.js";
12
+ import "./chunk-7YZHAQU7.js";
13
13
  import "./chunk-NAZ4E2GT.js";
14
14
  import "./chunk-GFMQJHXX.js";
15
- import "./chunk-BNGBG2SQ.js";
16
- import "./chunk-CCVC6P6B.js";
15
+ import "./chunk-YJAUJXZS.js";
16
+ import "./chunk-45C3WUQ7.js";
17
17
  import "./chunk-5ODOE6EF.js";
18
18
  import "./chunk-HGZL5EOI.js";
19
19
  import "./chunk-IEES3CHD.js";
@@ -27,4 +27,4 @@ export {
27
27
  theoPlugin,
28
28
  theoPluginAsync
29
29
  };
30
- //# sourceMappingURL=vite-plugin-V5PVDJZW.js.map
30
+ //# sourceMappingURL=vite-plugin-WO72VLYR.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theokit",
3
- "version": "0.11.3",
3
+ "version": "0.11.4",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "Apache-2.0",
@@ -155,7 +155,7 @@
155
155
  }
156
156
  },
157
157
  "devDependencies": {
158
- "@theokit/sdk": "^2.9.0",
158
+ "@theokit/sdk": "^2.11.2",
159
159
  "@types/busboy": "^1.5.4",
160
160
  "@types/pg": "^8.20.0",
161
161
  "@types/picomatch": "^4.0.3",
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
- import "tsx/esm";
3
- import {
4
- nodeAdapter
5
- } from "./chunk-EQV67HZL.js";
6
- import "./chunk-CCVC6P6B.js";
7
- export {
8
- nodeAdapter
9
- };
10
- //# sourceMappingURL=node-XVZAGVVO.js.map
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env node
2
- import "tsx/esm";
3
-
4
- // src/adapters/registry.ts
5
- var adapterRegistry = {
6
- node: async () => (await import("./node-XVZAGVVO.js")).nodeAdapter,
7
- vercel: async () => (await import("./vercel-6VWQTIUL.js")).vercelAdapter,
8
- cloudflare: async () => (await import("./cloudflare-KHF7JJZ7.js")).cloudflareAdapter,
9
- static: async () => (await import("./static-3JXPPDIH.js")).staticAdapter,
10
- bun: async () => (await import("./bun-FUYLUP62.js")).bunAdapter,
11
- "deno-deploy": async () => (await import("./deno-deploy-O4JP56BM.js")).denoDeployAdapter,
12
- netlify: async () => (await import("./netlify-E63264H6.js")).netlifyAdapter,
13
- "aws-lambda": async () => (await import("./aws-lambda-EC74AYN4.js")).awsLambdaAdapter,
14
- "theo-cloud": async () => (await import("./theo-cloud-I3KQE3JN.js")).theoCloudAdapter
15
- };
16
- async function resolveAdapter(target) {
17
- const factory = adapterRegistry[target];
18
- return factory();
19
- }
20
- export {
21
- adapterRegistry,
22
- resolveAdapter
23
- };
24
- //# sourceMappingURL=registry-WHMRQG5F.js.map