@geekmidas/cli 10.0.0-alpha.64 → 10.0.0-alpha.65

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 (175) hide show
  1. package/README.md +1 -1
  2. package/dist/{HostingerProvider-Bx2lHHvu.cjs → HostingerProvider-Dlmbfass.cjs} +3 -3
  3. package/dist/{HostingerProvider-Bx2lHHvu.cjs.map → HostingerProvider-Dlmbfass.cjs.map} +1 -1
  4. package/dist/{HostingerProvider-Cd4aS5Kj.mjs → HostingerProvider-x9gQTAGZ.mjs} +2 -2
  5. package/dist/{HostingerProvider-Cd4aS5Kj.mjs.map → HostingerProvider-x9gQTAGZ.mjs.map} +1 -1
  6. package/dist/{LegacyStateStore-C2abV49N.cjs → LegacyStateStore-BGoo__sO.cjs} +2 -2
  7. package/dist/{LegacyStateStore-C2abV49N.cjs.map → LegacyStateStore-BGoo__sO.cjs.map} +1 -1
  8. package/dist/{LegacyStateStore-DIgkGaUP.mjs → LegacyStateStore-BUu1nQ5u.mjs} +2 -2
  9. package/dist/{LegacyStateStore-DIgkGaUP.mjs.map → LegacyStateStore-BUu1nQ5u.mjs.map} +1 -1
  10. package/dist/{LocalStateStore-DiJqKyPy.cjs → LocalStateStore-93urXyQe.cjs} +2 -2
  11. package/dist/{LocalStateStore-DiJqKyPy.cjs.map → LocalStateStore-93urXyQe.cjs.map} +1 -1
  12. package/dist/{LocalStateStore-Cy1ZBW7U.mjs → LocalStateStore-BRhMQRuy.mjs} +2 -2
  13. package/dist/{LocalStateStore-Cy1ZBW7U.mjs.map → LocalStateStore-BRhMQRuy.mjs.map} +1 -1
  14. package/dist/{S3StateStore-Ds0V1Lgm.cjs → S3StateStore-F4dxw6kS.cjs} +2 -2
  15. package/dist/{S3StateStore-Ds0V1Lgm.cjs.map → S3StateStore-F4dxw6kS.cjs.map} +1 -1
  16. package/dist/{S3StateStore-D3x6ivBL.mjs → S3StateStore-pw1GhWwt.mjs} +2 -2
  17. package/dist/{S3StateStore-D3x6ivBL.mjs.map → S3StateStore-pw1GhWwt.mjs.map} +1 -1
  18. package/dist/{SSMStateStore-CLipvx47.cjs → SSMStateStore-Bt9acuAF.cjs} +2 -2
  19. package/dist/{SSMStateStore-CLipvx47.cjs.map → SSMStateStore-Bt9acuAF.cjs.map} +1 -1
  20. package/dist/{SSMStateStore-DfF174xQ.mjs → SSMStateStore-Dmj7zzFO.mjs} +2 -2
  21. package/dist/{SSMStateStore-DfF174xQ.mjs.map → SSMStateStore-Dmj7zzFO.mjs.map} +1 -1
  22. package/dist/{bundler-C8uJf324.cjs → bundler-D6MlIfBT.cjs} +3 -3
  23. package/dist/{bundler-C8uJf324.cjs.map → bundler-D6MlIfBT.cjs.map} +1 -1
  24. package/dist/{bundler-DYgm9xsd.mjs → bundler-D_14JLZF.mjs} +3 -3
  25. package/dist/{bundler-DYgm9xsd.mjs.map → bundler-D_14JLZF.mjs.map} +1 -1
  26. package/dist/{cli-D3jofJ6j.cjs → cli-BfH1deAT.cjs} +6 -6
  27. package/dist/{cli-D3jofJ6j.cjs.map → cli-BfH1deAT.cjs.map} +1 -1
  28. package/dist/{cli-Bogz-zEj.mjs → cli-P56vvrDQ.mjs} +5 -5
  29. package/dist/{cli-Bogz-zEj.mjs.map → cli-P56vvrDQ.mjs.map} +1 -1
  30. package/dist/compose-391oEKj1.cjs +1982 -0
  31. package/dist/compose-391oEKj1.cjs.map +1 -0
  32. package/dist/compose-DprE3ASm.mjs +1862 -0
  33. package/dist/compose-DprE3ASm.mjs.map +1 -0
  34. package/dist/{config-DqNRiQOp.d.mts → config-BonvTW8p.d.mts} +3 -3
  35. package/dist/{config-Be-4_I6H.d.cts.map → config-BonvTW8p.d.mts.map} +1 -1
  36. package/dist/{config-Be-4_I6H.d.cts → config-V_X_BMpm.d.cts} +3 -3
  37. package/dist/{config-DqNRiQOp.d.mts.map → config-V_X_BMpm.d.cts.map} +1 -1
  38. package/dist/config.cjs +1 -1
  39. package/dist/config.d.cts +3 -3
  40. package/dist/config.d.mts +3 -3
  41. package/dist/config.mjs +1 -1
  42. package/dist/{credentials-B70vmLcm.cjs → credentials-Bzbg23n8.cjs} +176 -3
  43. package/dist/credentials-Bzbg23n8.cjs.map +1 -0
  44. package/dist/{credentials-s0wMeZBU.mjs → credentials-Dq1MnWQf.mjs} +128 -3
  45. package/dist/credentials-Dq1MnWQf.mjs.map +1 -0
  46. package/dist/{define-CYs0PEfZ.mjs → define-DR8xGYfL.mjs} +5 -1
  47. package/dist/define-DR8xGYfL.mjs.map +1 -0
  48. package/dist/{define-zUsP72ym.cjs → define-DzRz8FgH.cjs} +5 -1
  49. package/dist/define-DzRz8FgH.cjs.map +1 -0
  50. package/dist/deploy/public.cjs +18 -18
  51. package/dist/deploy/public.cjs.map +1 -1
  52. package/dist/deploy/public.d.cts +7 -4
  53. package/dist/deploy/public.d.cts.map +1 -1
  54. package/dist/deploy/public.d.mts +7 -4
  55. package/dist/deploy/public.d.mts.map +1 -1
  56. package/dist/deploy/public.mjs +11 -11
  57. package/dist/{deploy-Dc2LBJaK.mjs → deploy-9MBG_QLd.mjs} +8 -7
  58. package/dist/deploy-9MBG_QLd.mjs.map +1 -0
  59. package/dist/{deploy-yUcR2OlW.cjs → deploy-B80idPUZ.cjs} +11 -10
  60. package/dist/deploy-B80idPUZ.cjs.map +1 -0
  61. package/dist/{deploy-ZRXIPp1c.mjs → deploy-CZ5nlpsu.mjs} +13 -119
  62. package/dist/deploy-CZ5nlpsu.mjs.map +1 -0
  63. package/dist/{deploy-55rJkdKz.cjs → deploy-Cy8igpQF.cjs} +39 -145
  64. package/dist/deploy-Cy8igpQF.cjs.map +1 -0
  65. package/dist/{dokploy-CepdXuMl.mjs → dokploy-BdtBePjp.mjs} +3 -3
  66. package/dist/{dokploy-CepdXuMl.mjs.map → dokploy-BdtBePjp.mjs.map} +1 -1
  67. package/dist/{dokploy-D1d37rvM.cjs → dokploy-iFY8MY-L.cjs} +3 -3
  68. package/dist/{dokploy-D1d37rvM.cjs.map → dokploy-iFY8MY-L.cjs.map} +1 -1
  69. package/dist/{encryption-C9X98u2F.cjs → encryption-B1wJwgae.cjs} +5 -5
  70. package/dist/{encryption-C9X98u2F.cjs.map → encryption-B1wJwgae.cjs.map} +1 -1
  71. package/dist/{encryption-CKHjMpCr.mjs → encryption-DF_hgIpl.mjs} +4 -4
  72. package/dist/{encryption-CKHjMpCr.mjs.map → encryption-DF_hgIpl.mjs.map} +1 -1
  73. package/dist/{github-D-byNI7T.mjs → github-B0YYE98x.mjs} +3 -3
  74. package/dist/{github-D-byNI7T.mjs.map → github-B0YYE98x.mjs.map} +1 -1
  75. package/dist/{github-Dd3tMa1u.cjs → github-CYcmTdFs.cjs} +3 -3
  76. package/dist/{github-Dd3tMa1u.cjs.map → github-CYcmTdFs.cjs.map} +1 -1
  77. package/dist/{index-CfE9Y885.d.cts → index-DPUAGJaK.d.cts} +16 -3
  78. package/dist/index-DPUAGJaK.d.cts.map +1 -0
  79. package/dist/{index-CJ2qsSpp.d.mts → index-DwKD_8lt.d.mts} +16 -3
  80. package/dist/index-DwKD_8lt.d.mts.map +1 -0
  81. package/dist/index.cjs +233 -1667
  82. package/dist/index.cjs.map +1 -1
  83. package/dist/index.mjs +196 -1614
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/{local-C7wnrcYK.cjs → local-BdH4XN0E.cjs} +1 -178
  86. package/dist/local-BdH4XN0E.cjs.map +1 -0
  87. package/dist/{local-Cd8ZYQG3.mjs → local-CWR4Y_kW.mjs} +3 -126
  88. package/dist/local-CWR4Y_kW.mjs.map +1 -0
  89. package/dist/{migrate-B4gngTLe.mjs → migrate-B2qL5wj4.mjs} +6 -5
  90. package/dist/{migrate-B4gngTLe.mjs.map → migrate-B2qL5wj4.mjs.map} +1 -1
  91. package/dist/{migrate-tx9-P9uz.cjs → migrate-q4pPAXtO.cjs} +19 -18
  92. package/dist/{migrate-tx9-P9uz.cjs.map → migrate-q4pPAXtO.cjs.map} +1 -1
  93. package/dist/openapi.d.cts +1 -1
  94. package/dist/openapi.d.mts +1 -1
  95. package/dist/provider-C9_-45d5.cjs +56 -0
  96. package/dist/provider-C9_-45d5.cjs.map +1 -0
  97. package/dist/provider-q4lsYzYG.mjs +45 -0
  98. package/dist/provider-q4lsYzYG.mjs.map +1 -0
  99. package/dist/reconcile/public.d.cts +1 -1
  100. package/dist/reconcile/public.d.mts +1 -1
  101. package/dist/resolve-DLkIXTct.mjs +262 -0
  102. package/dist/resolve-DLkIXTct.mjs.map +1 -0
  103. package/dist/resolve-N_i4XNd-.cjs +315 -0
  104. package/dist/resolve-N_i4XNd-.cjs.map +1 -0
  105. package/dist/{runtime-CJEYK4Gz.d.mts → runtime-BnD7Nn96.d.cts} +2 -2
  106. package/dist/{runtime-CJEYK4Gz.d.mts.map → runtime-BnD7Nn96.d.cts.map} +1 -1
  107. package/dist/{runtime-Cjq1jlVX.d.cts → runtime-j-tmFL65.d.mts} +2 -2
  108. package/dist/{runtime-Cjq1jlVX.d.cts.map → runtime-j-tmFL65.d.mts.map} +1 -1
  109. package/dist/sniffer-BSwaL-dX.cjs +2236 -0
  110. package/dist/sniffer-BSwaL-dX.cjs.map +1 -0
  111. package/dist/sniffer-BZ-OJO4Y.mjs +2068 -0
  112. package/dist/sniffer-BZ-OJO4Y.mjs.map +1 -0
  113. package/dist/{sst-Cper040I.mjs → sst-B2HbrDR3.mjs} +4 -4
  114. package/dist/{sst-Cper040I.mjs.map → sst-B2HbrDR3.mjs.map} +1 -1
  115. package/dist/{sst-BdALKEas.cjs → sst-DcfsVH6x.cjs} +4 -4
  116. package/dist/{sst-BdALKEas.cjs.map → sst-DcfsVH6x.cjs.map} +1 -1
  117. package/dist/{sniffer-49KPbDgq.mjs → state-B8YwmUZU.mjs} +878 -2465
  118. package/dist/state-B8YwmUZU.mjs.map +1 -0
  119. package/dist/{sniffer-ByhbEW5A.cjs → state-DF26e_lo.cjs} +811 -2525
  120. package/dist/state-DF26e_lo.cjs.map +1 -0
  121. package/dist/{store-D_2ByRtW.cjs → store-CJF1Tqkq.cjs} +2 -2
  122. package/dist/{store-D_2ByRtW.cjs.map → store-CJF1Tqkq.cjs.map} +1 -1
  123. package/dist/{store-BaaonhkJ.mjs → store-CLiHnqOY.mjs} +2 -2
  124. package/dist/{store-BaaonhkJ.mjs.map → store-CLiHnqOY.mjs.map} +1 -1
  125. package/dist/target/public.cjs +6 -6
  126. package/dist/target/public.d.cts +2 -2
  127. package/dist/target/public.d.mts +2 -2
  128. package/dist/target/public.mjs +3 -3
  129. package/dist/terminal-Bs5E1oxm.cjs +88 -0
  130. package/dist/terminal-Bs5E1oxm.cjs.map +1 -0
  131. package/dist/terminal-CfbiYUbZ.mjs +84 -0
  132. package/dist/terminal-CfbiYUbZ.mjs.map +1 -0
  133. package/dist/{types-B_bEQvb9.d.mts → types-BCzMWBb6.d.mts} +43 -11
  134. package/dist/types-BCzMWBb6.d.mts.map +1 -0
  135. package/dist/{types-DkrDOMxw.d.cts → types-ByMWkXKP.d.cts} +43 -11
  136. package/dist/types-ByMWkXKP.d.cts.map +1 -0
  137. package/dist/workspace/index.cjs +3 -1
  138. package/dist/workspace/index.d.cts +3 -3
  139. package/dist/workspace/index.d.mts +3 -3
  140. package/dist/workspace/index.mjs +2 -2
  141. package/dist/{workspace-BwgWJK7h.cjs → workspace-BewAHZIo.cjs} +38 -3
  142. package/dist/workspace-BewAHZIo.cjs.map +1 -0
  143. package/dist/{workspace-Bwit4q9O.mjs → workspace-C06_pW4g.mjs} +27 -4
  144. package/dist/workspace-C06_pW4g.mjs.map +1 -0
  145. package/package.json +13 -13
  146. package/dist/credentials-B70vmLcm.cjs.map +0 -1
  147. package/dist/credentials-s0wMeZBU.mjs.map +0 -1
  148. package/dist/define-CYs0PEfZ.mjs.map +0 -1
  149. package/dist/define-zUsP72ym.cjs.map +0 -1
  150. package/dist/deploy-55rJkdKz.cjs.map +0 -1
  151. package/dist/deploy-Dc2LBJaK.mjs.map +0 -1
  152. package/dist/deploy-ZRXIPp1c.mjs.map +0 -1
  153. package/dist/deploy-yUcR2OlW.cjs.map +0 -1
  154. package/dist/index-CJ2qsSpp.d.mts.map +0 -1
  155. package/dist/index-CfE9Y885.d.cts.map +0 -1
  156. package/dist/local-C7wnrcYK.cjs.map +0 -1
  157. package/dist/local-Cd8ZYQG3.mjs.map +0 -1
  158. package/dist/resolve-BXsNQjMR.cjs +0 -220
  159. package/dist/resolve-BXsNQjMR.cjs.map +0 -1
  160. package/dist/resolve-DZ2IJ0qY.mjs +0 -173
  161. package/dist/resolve-DZ2IJ0qY.mjs.map +0 -1
  162. package/dist/runtime-BGNDrHzh.cjs +0 -163
  163. package/dist/runtime-BGNDrHzh.cjs.map +0 -1
  164. package/dist/runtime-Cmn-FeYO.mjs +0 -134
  165. package/dist/runtime-Cmn-FeYO.mjs.map +0 -1
  166. package/dist/sniffer-49KPbDgq.mjs.map +0 -1
  167. package/dist/sniffer-ByhbEW5A.cjs.map +0 -1
  168. package/dist/terminal-Bdv--jhY.cjs +0 -481
  169. package/dist/terminal-Bdv--jhY.cjs.map +0 -1
  170. package/dist/terminal-D7Ntz6WE.mjs +0 -440
  171. package/dist/terminal-D7Ntz6WE.mjs.map +0 -1
  172. package/dist/types-B_bEQvb9.d.mts.map +0 -1
  173. package/dist/types-DkrDOMxw.d.cts.map +0 -1
  174. package/dist/workspace-BwgWJK7h.cjs.map +0 -1
  175. package/dist/workspace-Bwit4q9O.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose-391oEKj1.cjs","names":["spawn","run","runOutput","mkdir","dirname","planFor","provisionOrder","DEFAULT_EVENTS","DEFAULT_CACHE","localRolePassword","networkEnv","provideKey","publicEnvFor","appEnvKeys","siteDockerfile","generateSlimDockerfile","appKey","validateImageRef","imageRef","hostFor","resolveHost","isMainFrontendApp","composeFor","portKeys","DEFAULT_IMAGES","readdir","extname","join","pathToFileURL","stat","readFile","join","migrationTargets","MIGRATIONS_ROOT","canonicalId","readdir","DATABASE_FOLDERS","provideKey","require","createRequire","pathToFileURL","request","runOutput","dirname","fileURLToPath","join","existsSync","activeSandbox","LocalSandbox","pgClient","discover","constructGlobs","detectPackageManager","appPackageName","withGeneratedSecrets","initStageSecrets","postgresStatements","applyPostgres","envFor","primaryPortKey","DeployJournal","createEmptyState","readFile","mkdir","chmod","writeFile","generateDockerignore","appendFile","stringify","defineTarget"],"sources":["../src/compose/docker.ts","../src/compose/images.ts","../src/compose/caddyfile.ts","../src/compose/stack.ts","../src/migrate/provider.ts","../src/migrate/databases.ts","../src/target/compose/health.ts","../src/target/compose/phases.ts","../src/target/compose/index.ts"],"sourcesContent":["/**\n * The Docker operations `gkm compose` needs, behind an interface.\n *\n * Small on purpose, like reconcile's: the rules about *when* each runs — the\n * registry is asked before anything is pulled, nothing is started for a tag\n * that is missing — are asserted against a fake, and this file is only the\n * wiring to the real CLI.\n *\n * Every call is an argument array. Image refs, tags and paths come from the\n * workspace, and none of them reaches a shell.\n */\n\nimport { spawn } from 'node:child_process';\nimport { mkdir } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { type RunOptions, run, runOutput } from '../run';\n\n/** Where one stack lives: its compose project and the file that defines it. */\nexport interface StackRef {\n\tproject: string;\n\tfile: string;\n\t/** Where relative paths in the file resolve — the workspace root. */\n\tcwd: string;\n\t/**\n\t * Where docker's own output goes: the terminal (the default), stderr — so\n\t * a `--json` run's stdout carries only events — or nowhere.\n\t */\n\toutput?: 'inherit' | 'stderr' | 'ignore';\n\t/** Stops whatever docker is doing for the stack. */\n\tsignal?: AbortSignal;\n}\n\n/** `output` as `spawn` reads it. */\nconst STDIO: Record<NonNullable<StackRef['output']>, RunOptions['stdio']> = {\n\tinherit: 'inherit',\n\tstderr: ['ignore', 2, 2],\n\tignore: 'ignore',\n};\n\n/** How a stack's docker commands run: where it is, where output goes. */\nfunction runOptions(stack: StackRef, env?: NodeJS.ProcessEnv): RunOptions {\n\treturn {\n\t\tcwd: stack.cwd,\n\t\tstdio: STDIO[stack.output ?? 'inherit'],\n\t\t...(env ? { env } : {}),\n\t\t...(stack.signal ? { signal: stack.signal } : {}),\n\t};\n}\n\n/** What the registry said about one image ref. */\nexport type ImageLookup =\n\t| { ref: string; status: 'found' }\n\t| { ref: string; status: 'missing' }\n\t| { ref: string; status: 'unreachable'; detail: string };\n\nexport interface ComposeDocker {\n\t/** Ask the registry whether `ref` exists, without pulling it. */\n\tlookup(ref: string): Promise<ImageLookup>;\n\t/** Build every service with a `build:` entry. */\n\tbuild(stack: StackRef, services: readonly string[]): Promise<void>;\n\t/** Pull the named services' images. */\n\tpull(stack: StackRef, services: readonly string[]): Promise<void>;\n\t/**\n\t * Start services, detached, and wait for their health checks. With no\n\t * services named, the whole stack — and anything it no longer defines is\n\t * removed.\n\t */\n\tup(stack: StackRef, services?: readonly string[]): Promise<void>;\n\t/** Stop the stack. Its volumes are kept. */\n\tdown(stack: StackRef): Promise<void>;\n\t/** The host port a running service publishes for `inside`. */\n\tport(stack: StackRef, service: string, inside: number): Promise<number>;\n\t/** Copy a file out of a running service. */\n\tcopyOut(\n\t\tstack: StackRef,\n\t\tservice: string,\n\t\tfrom: string,\n\t\tto: string,\n\t): Promise<void>;\n\t/**\n\t * What an image resolved to: the registry digest a pulled image has, or\n\t * the content id of one built here and never pushed.\n\t */\n\tdigest(ref: string): Promise<string | undefined>;\n}\n\n/** How long a stack has to pass its health checks. */\nconst WAIT_TIMEOUT_S = 180;\n\n/** `docker compose port` printed nothing a port can be read from. */\nexport class ServicePortUnknown extends Error {\n\tconstructor(\n\t\treadonly service: string,\n\t\treadonly inside: number,\n\t\treadonly output: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${service}' publishes no host port for ${inside} (docker said: ${output.trim() || 'nothing'}). Is it running? \\`docker compose ps\\` shows the stack.`,\n\t\t);\n\t\tthis.name = 'ServicePortUnknown';\n\t}\n}\n\nfunction compose(stack: StackRef, args: readonly string[]): string[] {\n\treturn ['compose', '-p', stack.project, '-f', stack.file, ...args];\n}\n\n/** Run a program and keep everything it said, whatever it exits with. */\nfunction capture(\n\tcommand: string,\n\targs: readonly string[],\n\ttimeoutMs = 60_000,\n): Promise<{ code: number | null; stdout: string; stderr: string }> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(command, [...args], {\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\tshell: false,\n\t\t});\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\t\tchild.stdout.on('data', (chunk: Buffer) => {\n\t\t\tstdout += chunk.toString();\n\t\t});\n\t\tchild.stderr.on('data', (chunk: Buffer) => {\n\t\t\tstderr += chunk.toString();\n\t\t});\n\t\tconst timer = setTimeout(() => child.kill('SIGKILL'), timeoutMs);\n\t\ttimer.unref?.();\n\t\tchild.on('error', (error) => {\n\t\t\tclearTimeout(timer);\n\t\t\treject(error);\n\t\t});\n\t\tchild.on('close', (code) => {\n\t\t\tclearTimeout(timer);\n\t\t\tresolve({ code, stdout, stderr });\n\t\t});\n\t});\n}\n\n/**\n * Whether a failed `docker manifest inspect` means the tag is not there, as\n * opposed to the registry not answering.\n *\n * Read off the message because that is all the CLI gives. Anything not\n * recognisably \"no such tag\" is treated as the registry being unreachable:\n * a registry that refused credentials must not be reported as a tag that was\n * never pushed, or the fix offered would be the wrong one.\n */\nexport function isMissingManifest(output: string): boolean {\n\treturn /no such manifest|manifest unknown|manifest for .* not found|not found: manifest/i.test(\n\t\toutput,\n\t);\n}\n\nexport const dockerCompose: ComposeDocker = {\n\tasync lookup(ref) {\n\t\tconst { code, stdout, stderr } = await capture('docker', [\n\t\t\t'manifest',\n\t\t\t'inspect',\n\t\t\tref,\n\t\t]);\n\t\tif (code === 0) return { ref, status: 'found' };\n\n\t\tconst output = `${stderr}\\n${stdout}`.trim();\n\t\treturn isMissingManifest(output)\n\t\t\t? { ref, status: 'missing' }\n\t\t\t: { ref, status: 'unreachable', detail: output };\n\t},\n\n\tasync build(stack, services) {\n\t\tawait run(\n\t\t\t'docker',\n\t\t\tcompose(stack, ['build', ...services]),\n\t\t\trunOptions(stack, { ...process.env, DOCKER_BUILDKIT: '1' }),\n\t\t);\n\t},\n\n\tasync pull(stack, services) {\n\t\tawait run(\n\t\t\t'docker',\n\t\t\tcompose(stack, ['pull', ...services]),\n\t\t\trunOptions(stack),\n\t\t);\n\t},\n\n\tasync up(stack, services) {\n\t\tawait run(\n\t\t\t'docker',\n\t\t\tcompose(stack, [\n\t\t\t\t'up',\n\t\t\t\t'-d',\n\t\t\t\t'--wait',\n\t\t\t\t`--wait-timeout=${WAIT_TIMEOUT_S}`,\n\t\t\t\t// Only when the whole stack is asked for: starting the databases\n\t\t\t\t// first must not remove the apps an earlier run left running.\n\t\t\t\t...(services ? [] : ['--remove-orphans']),\n\t\t\t\t...(services ?? []),\n\t\t\t]),\n\t\t\trunOptions(stack),\n\t\t);\n\t},\n\n\tasync down(stack) {\n\t\tawait run('docker', compose(stack, ['down']), runOptions(stack));\n\t},\n\n\tasync port(stack, service, inside) {\n\t\tconst output = await runOutput(\n\t\t\t'docker',\n\t\t\tcompose(stack, ['port', service, String(inside)]),\n\t\t\t{ cwd: stack.cwd, ...(stack.signal ? { signal: stack.signal } : {}) },\n\t\t);\n\t\t// `127.0.0.1:54321` — the part after the last colon is the host port.\n\t\tconst port = Number(output.trim().split(':').pop());\n\t\tif (!Number.isInteger(port) || port <= 0) {\n\t\t\tthrow new ServicePortUnknown(service, inside, output);\n\t\t}\n\t\treturn port;\n\t},\n\n\tasync copyOut(stack, service, from, to) {\n\t\tawait mkdir(dirname(to), { recursive: true });\n\t\tawait run(\n\t\t\t'docker',\n\t\t\tcompose(stack, ['cp', `${service}:${from}`, to]),\n\t\t\trunOptions(stack),\n\t\t);\n\t},\n\n\tasync digest(ref) {\n\t\tconst { code, stdout } = await capture('docker', [\n\t\t\t'image',\n\t\t\t'inspect',\n\t\t\t'--format={{json .RepoDigests}} {{.Id}}',\n\t\t\tref,\n\t\t]);\n\t\tif (code !== 0) return undefined;\n\n\t\tconst [json = '[]', id] = stdout.trim().split(' ');\n\t\tconst repository = ref.split('@')[0]!.replace(/:[\\w][\\w.-]*$/, '');\n\t\ttry {\n\t\t\tconst digests = JSON.parse(json) as unknown;\n\t\t\tconst match = Array.isArray(digests)\n\t\t\t\t? digests.find(\n\t\t\t\t\t\t(entry): entry is string =>\n\t\t\t\t\t\t\ttypeof entry === 'string' && entry.startsWith(`${repository}@`),\n\t\t\t\t\t)\n\t\t\t\t: undefined;\n\t\t\tif (match) return match.slice(repository.length + 1);\n\t\t} catch {\n\t\t\t// Fall through to the content id.\n\t\t}\n\t\treturn id || undefined;\n\t},\n};\n","/**\n * Which image each app runs — and, for a tag, whether every one exists.\n *\n * A tag is a release's identity: `--tag=v1.4.0` means the images CI pushed as\n * v1.4.0, and nothing else. So a stack is never half rolled out: every app's\n * image is asked of the registry before anything is pulled or the running\n * stack is touched, and one missing image stops the whole run naming every\n * one that is missing. Nor is a missing image quietly built instead — a build\n * of whatever is checked out here is not the release the tag names.\n */\n\nimport type { ComposeDocker } from './docker';\n\n/** One app's image, as the stack runs it. */\nexport interface AppImage {\n\tapp: string;\n\tref: string;\n\ttag: string;\n}\n\n/**\n * The tag a site's image carries for a release.\n *\n * A site's public URLs are inlined when it is built, so one bundle serves one\n * stage: `v1.4.0-production` and `v1.4.0-staging` are two images of the same\n * commit. A backend reads its URLs at runtime, so one image serves every stage\n * and its tag is the release's alone.\n */\nexport function siteTag(tag: string, stage: string): string {\n\treturn `${tag}-${stage}`;\n}\n\n/** Images a tag names that the registry does not have. */\nexport class ImageTagNotFound extends Error {\n\tconstructor(\n\t\treadonly tag: string,\n\t\treadonly refs: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`The registry has no image for ${refs.length === 1 ? 'this app' : `${refs.length} apps`} at '${tag}':\\n` +\n\t\t\t\trefs.map((ref) => ` - ${ref}`).join('\\n') +\n\t\t\t\t`\\nNothing was pulled or started. Push '${tag}' for every app from CI, ` +\n\t\t\t\t`pick a tag that exists, or run without --tag to build from this checkout.`,\n\t\t);\n\t\tthis.name = 'ImageTagNotFound';\n\t}\n}\n\n/** The registry did not answer, or did not let this machine in. */\nexport class RegistryUnreachable extends Error {\n\tconstructor(\n\t\treadonly ref: string,\n\t\treadonly detail: string,\n\t) {\n\t\tsuper(\n\t\t\t`Could not ask the registry about ${ref}: ${detail || 'no answer'}\\n` +\n\t\t\t\t`Nothing was pulled or started. Check the registry is reachable and ` +\n\t\t\t\t`that this machine is logged in to it (\\`docker login <registry>\\`).`,\n\t\t);\n\t\tthis.name = 'RegistryUnreachable';\n\t}\n}\n\n/**\n * Assert every image exists, before anything else happens.\n *\n * Asked all at once and reported all at once: a release missing two images is\n * one problem with two names, and finding the second only after fixing the\n * first is a slower way to learn the same thing.\n *\n * @throws {RegistryUnreachable} when the registry cannot say\n * @throws {ImageTagNotFound} listing every missing image\n */\nexport async function assertImagesExist(\n\tdocker: Pick<ComposeDocker, 'lookup'>,\n\ttag: string,\n\timages: readonly AppImage[],\n): Promise<void> {\n\tconst lookups = await Promise.all(\n\t\timages.map((image) => docker.lookup(image.ref)),\n\t);\n\n\tconst unreachable = lookups.find((lookup) => lookup.status === 'unreachable');\n\tif (unreachable?.status === 'unreachable') {\n\t\tthrow new RegistryUnreachable(unreachable.ref, unreachable.detail);\n\t}\n\n\tconst missing = lookups\n\t\t.filter((lookup) => lookup.status === 'missing')\n\t\t.map((lookup) => lookup.ref);\n\tif (missing.length > 0) throw new ImageTagNotFound(tag, missing);\n}\n","/**\n * The edge in front of a compose stack: one Caddy, one host per app.\n *\n * Deployed, each host is the stage's real domain and Caddy gets it a\n * certificate from Let's Encrypt on first request — the same automatic HTTPS\n * it does anywhere, with nothing to configure but the name. Locally the hosts\n * are `*.localhost` and the certificates come from Caddy's own CA, as the\n * `gkm dev` edge does, so a local stack is `https://` like a deployed one.\n *\n * Pure: what the edge serves is data, and rendering it is one string.\n */\n\n/** One host on the edge and the app container behind it. */\nexport interface EdgeSite {\n\t/** e.g. `api.example.com` */\n\thost: string;\n\t/** The app on the compose network, e.g. `api:3000`. */\n\tupstream: string;\n}\n\nexport interface EdgeOptions {\n\t/** Certificates from Caddy's internal CA rather than from ACME. */\n\tlocal: boolean;\n\t/** Where ACME sends expiry notices, when someone wants them. */\n\temail?: string;\n}\n\n/** The Caddyfile for a stack's edge. */\nexport function edgeCaddyfile(\n\tsites: readonly EdgeSite[],\n\toptions: EdgeOptions,\n): string {\n\tconst global = options.local\n\t\t? `{\n\t# No ACME and no public DNS: the CA is Caddy's own and the names resolve\n\t# to this machine.\n\tlocal_certs\n\tauto_https disable_redirects\n}`\n\t\t: options.email\n\t\t\t? `{\n\temail ${options.email}\n}`\n\t\t\t: '';\n\n\tconst blocks = sites.map(\n\t\t({ host, upstream }) => `https://${host} {${\n\t\t\toptions.local\n\t\t\t\t? `\n\ttls internal\n`\n\t\t\t\t: ''\n\t\t}\n\t# Host and X-Forwarded-* are passed through as Caddy does by default, so\n\t# an app builds redirects, cookies and links on the address a caller used.\n\treverse_proxy ${upstream} {\n\t\t# Never buffer: a streamed response — server-sent events, a Next.js\n\t\t# RSC payload — reaches the client as each chunk is written.\n\t\tflush_interval -1\n\t}\n}`,\n\t);\n\n\t// No blank line under the header: `caddy fmt` wants the first block there.\n\treturn `${HEADER}${global ? `${global}\\n\\n` : ''}${blocks.join('\\n\\n')}\\n`;\n}\n\nconst HEADER = `# Generated by gkm compose from the construct manifest — do not edit.\n#\n# One host per API and site, each in front of its own container.\n`;\n","/**\n * The stack a workspace runs as for one stage — pure.\n *\n * Everything `gkm compose` writes is decided here, as data: the compose file,\n * the Caddyfile, one env file per backend, and the image each app runs. The\n * command around it reads the workspace, asks the registry, writes the files\n * and starts Docker; none of those decide anything, so all of it can be\n * asserted without a daemon.\n *\n * The values come from the same derivations every other target uses. The\n * plan is reconcile's `planFor`, the keys an app reads are `appEnvKeys`, and\n * every URL is `envFor`'s — asked twice, once with each app at its public\n * address and once on the compose network, because a browser and a sibling\n * service reach the same API by different names.\n */\n\nimport {\n\ttype ConstructManifest,\n\tprovideKey,\n\tprovisionOrder,\n\tpublicEnvFor,\n} from '@geekmidas/manifest';\nimport { isMainFrontendApp, resolveHost } from '../deploy/domain.js';\nimport { type DeployIdentity, imageRef } from '../deploy/identity.js';\nimport { validateImageRef } from '../docker/imageRef.js';\nimport { siteDockerfile } from '../docker/index.js';\nimport {\n\tgenerateSlimDockerfile,\n\ttype PackageManager,\n} from '../docker/templates.js';\nimport { appEnvKeys, networkEnv } from '../reconcile/apps.js';\nimport { hostFor } from '../reconcile/caddyfile.js';\nimport { type ComposeService, composeFor } from '../reconcile/compose.js';\nimport { DEFAULT_IMAGES, portKeys } from '../reconcile/containers.js';\nimport { localRolePassword } from '../reconcile/env.js';\nimport { type Plan, type PlannedResource, planFor } from '../reconcile/plan.js';\nimport type { StageSecrets } from '../secrets/types.js';\nimport { DEFAULT_CACHE, DEFAULT_EVENTS } from '../types.js';\nimport { appKey } from '../workspace/derive.js';\nimport type {\n\tNormalizedAppConfig,\n\tNormalizedWorkspace,\n} from '../workspace/types.js';\nimport { edgeCaddyfile } from './caddyfile.js';\nimport { type AppImage, siteTag } from './images.js';\n\n/** Where a stack's files are written, relative to the workspace root. */\nexport function stackDir(stage: string): string {\n\treturn `.gkm/compose/${stage}`;\n}\n\n/**\n * The compose project a stage's stack runs as.\n *\n * The deploy identity's scope, so two workspaces with one name in different\n * namespaces never share containers or volumes — and the stage, so a\n * machine can run two stages side by side.\n */\nexport function composeProject(identity: DeployIdentity): string {\n\treturn `${identity.scope}-${identity.stage}`;\n}\n\n/** The ports the edge is published on, and the variables that move them. */\nexport const EDGE_PORT_ENV = {\n\thttps: 'GKM_COMPOSE_HTTPS_PORT',\n\thttp: 'GKM_COMPOSE_HTTP_PORT',\n} as const;\n\n/**\n * Containers this target does not run.\n *\n * Object storage is the stage's own — an externally hosted bucket whose URL\n * the stage's secrets hold — and so is a deployed stage's mail. The AWS\n * emulator never applies: a stack is a server target, whose events are\n * pg-boss.\n */\nconst NOT_RUN: Readonly<Record<string, true>> = {\n\tminio: true,\n\tlocalstack: true,\n\tcaddy: true,\n};\n\n/** Kinds whose `<ID>_URL` a stage must be given, because nothing here runs them. */\nconst EXTERNAL_KINDS: Readonly<Record<string, true>> = {\n\tobjects: true,\n\t'file-server': true,\n};\n\n/** The S3 client's credentials, read beside a bucket's URL when it has them. */\nconst STORAGE_KEYS = [\n\t'AWS_ACCESS_KEY_ID',\n\t'AWS_SECRET_ACCESS_KEY',\n\t'AWS_REGION',\n] as const;\n\n/** Each image's build, where the stack builds rather than pulls. */\nexport interface AppBuild {\n\t/** Relative to the workspace root, which is the build context. */\n\tdockerfile: string;\n\t/** A site's public URLs, inlined by its bundler. */\n\targs?: Record<string, string>;\n}\n\n/** One app in the stack. */\nexport interface StackApp extends AppImage {\n\t/** Its compose service name — the app key, `api`. */\n\tname: string;\n\t/** The construct it serves. */\n\tid: string;\n\tkind: 'rest-api' | 'site';\n\t/** Its directory, relative to the workspace root. */\n\tpath: string;\n\tport: number;\n\t/** The host the edge answers it on. */\n\thost: string;\n\t/** `https://<host>` — with the edge's port where it is not 443. */\n\turl: string;\n\tbuild?: AppBuild;\n\t/** A backend's environment, exactly the keys it reads. Absent for a site. */\n\tenv?: Record<string, string>;\n}\n\n/** A service as the stack's compose file defines it. */\nexport interface StackService {\n\timage: string;\n\tbuild?: {\n\t\tcontext: string;\n\t\tdockerfile: string;\n\t\targs?: Record<string, string>;\n\t};\n\trestart?: string;\n\tcommand?: string;\n\tenv_file?: { path: string; format: 'raw' }[];\n\tenvironment?: Record<string, string>;\n\tports?: string[];\n\tvolumes?: string[];\n\tdepends_on?: Record<string, { condition: 'service_healthy' }>;\n\thealthcheck?: ComposeService['healthcheck'];\n}\n\nexport interface StackFile {\n\tname: string;\n\tservices: Record<string, StackService>;\n\tvolumes: Record<string, Record<string, never>>;\n}\n\nexport interface ComposeStack {\n\tproject: string;\n\tstage: string;\n\t/** The project's local stage, served with Caddy's internal CA. */\n\tlocal: boolean;\n\tapps: StackApp[];\n\t/** The infrastructure containers, by compose service name. */\n\tinfra: string[];\n\tcompose: StackFile;\n\tcaddyfile: string;\n\t/** Generated Dockerfiles, by path relative to the workspace root. */\n\tdockerfiles: Record<string, string>;\n\t/** The plan the stack was derived from — what provisioning creates. */\n\tplan: Plan;\n\t/** The Postgres master's password, and the seed role passwords take. */\n\tcredential: { master: string; seed?: string };\n}\n\nexport interface StackInput {\n\tworkspace: NormalizedWorkspace;\n\tmanifest: ConstructManifest;\n\t/** Each owner's runnables' edges, from discovery. */\n\trunnables?: Readonly<Record<string, readonly string[]>>;\n\tstage: string;\n\tidentity: DeployIdentity;\n\timages: {\n\t\tmode: 'build' | 'pull';\n\t\t/** A release tag, or — building — the commit. */\n\t\ttag: string;\n\t\tregistry?: string;\n\t};\n\t/** The stage's secrets — set by hand, and what a deployed stage generated. */\n\tsecrets?: StageSecrets | null;\n\t/** The edge's published ports. 443 and 80 by default. */\n\tports?: { https?: number; http?: number };\n\t/** For builds: the package manager the site Dockerfiles install with. */\n\tpackageManager?: PackageManager;\n\t/** For builds: each app's package name, which turbo prunes by. */\n\tpackages?: Readonly<Record<string, string>>;\n}\n\n/** A bucket the stack needs and the stage was not given. */\nexport class BucketNotConfigured extends Error {\n\tconstructor(\n\t\treadonly app: string,\n\t\treadonly id: string,\n\t\treadonly key: string,\n\t\treadonly stage: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${app}' uses the bucket '${id}', and gkm compose runs no object ` +\n\t\t\t\t`storage: the stage needs an externally hosted bucket. Set its URL in ` +\n\t\t\t\t`the stage's secrets: gkm secrets:set ${key} 's3://…' --stage ${stage}`,\n\t\t);\n\t\tthis.name = 'BucketNotConfigured';\n\t}\n}\n\n/** A value only the stage's secrets can hold, and they do not. */\nexport class StageSecretMissing extends Error {\n\tconstructor(\n\t\treadonly app: string,\n\t\treadonly key: string,\n\t\treadonly stage: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${app}' reads ${key}, and the stage '${stage}' has none. Nothing in ` +\n\t\t\t\t`the stack can derive it; set it in the stage's secrets: ` +\n\t\t\t\t`gkm secrets:set ${key} '…' --stage ${stage}`,\n\t\t);\n\t\tthis.name = 'StageSecretMissing';\n\t}\n}\n\n/** A deployed stage's secrets with no seed to derive its passwords from. */\nexport class StageSeedMissing extends Error {\n\tconstructor(readonly stage: string) {\n\t\tsuper(\n\t\t\t`The stage '${stage}' has no seed in its secrets, and a deployed stage's ` +\n\t\t\t\t`database passwords are derived from it. Run gkm compose without ` +\n\t\t\t\t`--dry-run once, or gkm deploy, to generate it.`,\n\t\t);\n\t\tthis.name = 'StageSeedMissing';\n\t}\n}\n\n/** A workspace with no API and no site to run. */\nexport class NothingToCompose extends Error {\n\tconstructor(readonly root: string) {\n\t\tsuper(\n\t\t\t`${root} declares no RestApi and no site, so a stack would run nothing. ` +\n\t\t\t\t`Workers and mobile apps are not run by gkm compose yet.`,\n\t\t);\n\t\tthis.name = 'NothingToCompose';\n\t}\n}\n\n/** A value that cannot be written to an env file a line at a time. */\nexport class EnvValueMultiline extends Error {\n\tconstructor(\n\t\treadonly app: string,\n\t\treadonly key: string,\n\t) {\n\t\tsuper(\n\t\t\t`${key} for '${app}' spans more than one line, and an env file holds ` +\n\t\t\t\t`one value per line. Store it on one line — base64, or JSON — and ` +\n\t\t\t\t`decode it where it is read.`,\n\t\t);\n\t\tthis.name = 'EnvValueMultiline';\n\t}\n}\n\n/** The services a stack's apps wait on and the edge waits on in turn. */\nconst HEALTHY = { condition: 'service_healthy' } as const;\n\n/**\n * An app's health check: its own server, asked on 127.0.0.1 — not\n * `localhost`, which resolves to `::1` first in an Alpine container while a\n * server may listen on IPv4 alone.\n */\nfunction probe(port: number, path: string): StackService['healthcheck'] {\n\treturn {\n\t\ttest: [\n\t\t\t'CMD',\n\t\t\t'wget',\n\t\t\t'-q',\n\t\t\t'-O',\n\t\t\t'/dev/null',\n\t\t\t`http://127.0.0.1:${port}${path}`,\n\t\t],\n\t\tinterval: '5s',\n\t\ttimeout: '3s',\n\t\tretries: 20,\n\t\tstart_period: '10s',\n\t};\n}\n\n/** The stack for one stage. */\nexport function composeStack(input: StackInput): ComposeStack {\n\tconst { workspace, manifest, stage, identity } = input;\n\tconst local = stage === workspace.stages.local;\n\tconst project = composeProject(identity);\n\tconst custom = input.secrets?.custom ?? {};\n\tconst https = input.ports?.https ?? 443;\n\tconst http = input.ports?.http ?? 80;\n\n\t// A server target's backends, whatever `deploy.default` says: the stack is\n\t// one machine running containers, so the cache is a table in the declared\n\t// database and events are pg-boss beside it.\n\tconst plan = planFor(manifest, stage, provisionOrder(manifest), {\n\t\tlocalStage: workspace.stages.local,\n\t\tevents: DEFAULT_EVENTS.server,\n\t\tcache: DEFAULT_CACHE.server,\n\t\t// The stack brings its own edge; reconcile's would front the host.\n\t\tedge: false,\n\t});\n\tconst byId = new Map(plan.resources.map((r) => [r.id, r]));\n\n\tconst seed = local ? undefined : input.secrets?.seed;\n\tif (!local && !seed) throw new StageSeedMissing(stage);\n\tconst credential = {\n\t\tmaster: local\n\t\t\t? 'geekmidas'\n\t\t\t: localRolePassword(workspace.name, plan, 'master', seed),\n\t\t...(seed ? { seed } : {}),\n\t};\n\n\tconst infra = plan.containers\n\t\t.filter((c) => !NOT_RUN[c])\n\t\t// A deployed stage sends real mail, through whatever its MAIL_URL names.\n\t\t.filter((c) => local || c !== 'mailpit')\n\t\t.sort();\n\n\tconst apps = stackApps(workspace, manifest, plan, {\n\t\tlocal,\n\t\tstage,\n\t\thttps,\n\t\tidentity,\n\t\timages: input.images,\n\t});\n\tif (apps.length === 0) throw new NothingToCompose(workspace.root);\n\n\t// Every key the stage resolves, twice: with each app at its public address\n\t// — what a browser is handed, and what an app says it is — and with each on\n\t// the compose network, which is how one service reaches another.\n\tconst derivation = {\n\t\tproject: workspace.name,\n\t\tmaster: credential.master,\n\t\t...(credential.seed ? { seed: credential.seed } : {}),\n\t};\n\tconst outside = networkEnv(plan, {\n\t\t...derivation,\n\t\taddresses: Object.fromEntries(apps.map((app) => [app.id, app.url])),\n\t});\n\tconst inside = networkEnv(plan, {\n\t\t...derivation,\n\t\taddresses: Object.fromEntries(\n\t\t\tapps.map((app) => [app.id, `http://${app.name}:${app.port}`]),\n\t\t),\n\t});\n\n\t// Which construct each key belongs to, so a key is resolved by what it is\n\t// rather than by its spelling.\n\tconst owners = new Map<string, PlannedResource>();\n\tfor (const resource of plan.resources) {\n\t\towners.set(resource.envKey, resource);\n\t\tif (resource.kind === 'email') {\n\t\t\towners.set(provideKey(resource.id, 'from'), resource);\n\t\t\towners.set(provideKey(resource.id, 'inboxUrl'), resource);\n\t\t}\n\t\tif (resource.kind === 'external-api') {\n\t\t\towners.set(provideKey(resource.id, 'credentials'), resource);\n\t\t}\n\t}\n\tconst surfaceUrls = new Map(\n\t\tplan.resources\n\t\t\t.filter((r) => r.kind === 'rest-api' || r.kind === 'site')\n\t\t\t.map((r) => [r.envKey, r.id]),\n\t);\n\tconst appById = new Map(apps.map((app) => [app.id, app]));\n\n\t/**\n\t * What a key resolves to for one app, from the stage's secrets where only\n\t * they can hold it, and the derivations otherwise.\n\t */\n\tconst valueFor = (\n\t\tapp: StackApp,\n\t\tkey: string,\n\t\towner: PlannedResource | undefined,\n\t): string | undefined => {\n\t\tif (owner && EXTERNAL_KINDS[owner.kind] && key === owner.envKey) {\n\t\t\tconst value = custom[key];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new BucketNotConfigured(app.name, owner.id, key, stage);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\t// Supplied by somebody: a third party's credentials, and — deployed —\n\t\t// the mail server a stage sends through and the secrets it generated.\n\t\tif (owner && suppliedBy(owner, key, local)) {\n\t\t\tconst value = custom[key];\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new StageSecretMissing(app.name, key, stage);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\t// Set by hand wins over derived: it is the stage saying what it is.\n\t\tif (custom[key] !== undefined) return custom[key];\n\n\t\t// A backend reaches a sibling surface on the compose network; its own\n\t\t// address is the public one, which is what it builds links on. A site\n\t\t// runs in a browser, which has only the public addresses.\n\t\tconst surface = surfaceUrls.get(key);\n\t\tif (app.kind === 'rest-api' && surface && surface !== app.id) {\n\t\t\treturn inside[key];\n\t\t}\n\n\t\treturn outside[key];\n\t};\n\n\tfor (const app of apps) {\n\t\tif (app.kind === 'site') {\n\t\t\tconst site = manifest[app.id];\n\t\t\tif (site?.kind !== 'site') continue;\n\n\t\t\tconst args: Record<string, string> = {};\n\t\t\tfor (const [key, source] of Object.entries(\n\t\t\t\tpublicEnvFor(site, manifest),\n\t\t\t)) {\n\t\t\t\tconst value = valueFor(app, source, owners.get(source));\n\t\t\t\tif (value !== undefined) args[key] = value;\n\t\t\t}\n\t\t\tif (app.build && Object.keys(args).length > 0) app.build.args = args;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst keys = appEnvKeys(manifest, app.name, input.runnables) ?? new Set();\n\t\tconst values: Record<string, string> = {};\n\t\tfor (const key of [...keys].sort()) {\n\t\t\tconst owner = owners.get(key) ?? storageOwner(key, plan);\n\t\t\t// A deployed stage has no inbox: Mailpit runs only locally.\n\t\t\tif (!local && owner?.kind === 'email' && key.endsWith('_INBOX_URL'))\n\t\t\t\tcontinue;\n\t\t\tif ((STORAGE_KEYS as readonly string[]).includes(key)) {\n\t\t\t\t// The bucket is the stage's own, so its credentials are too —\n\t\t\t\t// when it has any: on AWS an instance role may stand in for them.\n\t\t\t\tif (custom[key] !== undefined) values[key] = custom[key];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst value = valueFor(app, key, owner);\n\t\t\tif (value !== undefined) values[key] = value;\n\t\t}\n\n\t\t// The origins Better Auth trusts are the browser's and, now, each\n\t\t// service that calls this surface across the compose network: its CSRF\n\t\t// check applies to every caller, and a sibling's request carries its\n\t\t// own origin, not a browser's.\n\t\tconst trusted = provideKey(app.id, 'trustedOrigins');\n\t\tif (keys.has(trusted)) {\n\t\t\tconst internal = (byId.get(app.id)?.callers ?? [])\n\t\t\t\t.map((caller) => appById.get(caller))\n\t\t\t\t.filter((caller): caller is StackApp => caller?.kind === 'rest-api')\n\t\t\t\t.map((caller) => `http://${caller.name}:${caller.port}`);\n\t\t\tconst origins = [\n\t\t\t\t...(values[trusted] ?? '').split(',').filter(Boolean),\n\t\t\t\t...internal,\n\t\t\t];\n\t\t\tvalues[trusted] = [...new Set(origins)].join(',');\n\t\t}\n\n\t\tapp.env = {\n\t\t\t...values,\n\t\t\tNODE_ENV: 'production',\n\t\t\tPORT: String(app.port),\n\t\t\tSTAGE: stage,\n\t\t};\n\n\t\tfor (const [key, value] of Object.entries(app.env)) {\n\t\t\tif (/[\\r\\n]/.test(value)) throw new EnvValueMultiline(app.name, key);\n\t\t}\n\t}\n\n\tconst compose = stackFile({\n\t\tproject,\n\t\tplan,\n\t\tinfra,\n\t\tapps,\n\t\tmaster: credential.master,\n\t\thttps,\n\t\thttp,\n\t});\n\n\tconst caddyfile = edgeCaddyfile(\n\t\tapps.map((app) => ({\n\t\t\thost: app.host,\n\t\t\tupstream: `${app.name}:${app.port}`,\n\t\t})),\n\t\t{ local },\n\t);\n\n\tconst dockerfiles: Record<string, string> = {};\n\tfor (const app of apps) {\n\t\tif (!app.build) continue;\n\t\tdockerfiles[app.build.dockerfile] =\n\t\t\tapp.kind === 'site'\n\t\t\t\t? siteDockerfile(app.name, workspace.apps[app.name]!, {\n\t\t\t\t\t\tturboPackage: input.packages?.[app.name] ?? app.name,\n\t\t\t\t\t\tpackageManager: input.packageManager ?? 'pnpm',\n\t\t\t\t\t\tmanifest,\n\t\t\t\t\t})\n\t\t\t\t: generateSlimDockerfile({\n\t\t\t\t\t\timageName: app.name,\n\t\t\t\t\t\tbaseImage: 'node:22-alpine',\n\t\t\t\t\t\tport: app.port,\n\t\t\t\t\t\thealthCheckPath: '/health',\n\t\t\t\t\t\tprebuilt: true,\n\t\t\t\t\t\tpackageManager: input.packageManager ?? 'pnpm',\n\t\t\t\t\t\tbundle: `${app.path}/.gkm/server/dist/server.mjs`,\n\t\t\t\t\t});\n\t}\n\n\treturn {\n\t\tproject,\n\t\tstage,\n\t\tlocal,\n\t\tapps,\n\t\tinfra,\n\t\tcompose,\n\t\tcaddyfile,\n\t\tdockerfiles,\n\t\tplan,\n\t\tcredential,\n\t};\n\n\t/** Whether only the stage's secrets can supply `key` to `owner`. */\n\tfunction suppliedBy(\n\t\towner: PlannedResource,\n\t\tkey: string,\n\t\tisLocal: boolean,\n\t): boolean {\n\t\tif (owner.kind === 'credential') return true;\n\t\tif (owner.kind === 'external-api')\n\t\t\treturn key === provideKey(owner.id, 'credentials');\n\t\tif (isLocal) return false;\n\t\t// Deployed, nothing here derives a secret: the stage generated each one\n\t\t// once, and every run reads the same value back.\n\t\tif (owner.kind === 'secret' || owner.kind === 'encryption') return true;\n\t\treturn owner.kind === 'email' && !key.endsWith('_INBOX_URL');\n\t}\n}\n\n/** Which bucket an S3 credential key belongs to — the first one declared. */\nfunction storageOwner(key: string, plan: Plan): PlannedResource | undefined {\n\tif (!(STORAGE_KEYS as readonly string[]).includes(key)) return undefined;\n\treturn plan.resources.find((r) => r.kind === 'objects');\n}\n\n/** The apps a stack runs: every API and every site, at its stage address. */\nfunction stackApps(\n\tworkspace: NormalizedWorkspace,\n\tmanifest: ConstructManifest,\n\tplan: Plan,\n\toptions: {\n\t\tlocal: boolean;\n\t\tstage: string;\n\t\thttps: number;\n\t\tidentity: DeployIdentity;\n\t\timages: StackInput['images'];\n\t},\n): StackApp[] {\n\tconst apps: StackApp[] = [];\n\tconst resources = new Map(plan.resources.map((r) => [r.id, r]));\n\n\tfor (const [id, declaration] of Object.entries(manifest)) {\n\t\tif (declaration.kind !== 'rest-api' && declaration.kind !== 'site')\n\t\t\tcontinue;\n\n\t\tconst name = appKey(id);\n\t\tconst app = workspace.apps[name];\n\t\tconst resource = resources.get(id);\n\t\tif (!app || !resource || !app.port) continue;\n\n\t\tconst host = hostOf(name, app, workspace, resource, options);\n\t\tconst site = declaration.kind === 'site';\n\t\tconst tag = site\n\t\t\t? siteTag(options.images.tag, options.stage)\n\t\t\t: options.images.tag;\n\t\tconst ref = validateImageRef(\n\t\t\timageRef(options.identity, name, options.images.registry, tag),\n\t\t);\n\n\t\tapps.push({\n\t\t\tapp: name,\n\t\t\tname,\n\t\t\tid,\n\t\t\tkind: declaration.kind,\n\t\t\tpath: app.path,\n\t\t\tport: app.port,\n\t\t\thost,\n\t\t\turl: `https://${host}${options.local && options.https !== 443 ? `:${options.https}` : ''}`,\n\t\t\tref,\n\t\t\ttag,\n\t\t\t...(options.images.mode === 'build'\n\t\t\t\t? {\n\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\tdockerfile: `${stackDir(options.stage)}/Dockerfile.${name}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t});\n\t}\n\n\treturn apps.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * The host an app answers on for a stage: the `gkm dev` edge's\n * `*.localhost` names for the local stage, and the stage's domain — by the\n * same rule a deploy follows — for any other.\n */\nfunction hostOf(\n\tname: string,\n\tapp: NormalizedAppConfig,\n\tworkspace: NormalizedWorkspace,\n\tresource: PlannedResource,\n\toptions: { local: boolean; stage: string },\n): string {\n\tif (options.local) return hostFor(resource, workspace.name);\n\n\treturn resolveHost(\n\t\tname,\n\t\tapp,\n\t\toptions.stage,\n\t\tworkspace.deploy?.domains,\n\t\tisMainFrontendApp(name, app, workspace.apps),\n\t);\n}\n\n/** The compose document: the infrastructure, the apps, and the edge. */\nfunction stackFile(options: {\n\tproject: string;\n\tplan: Plan;\n\tinfra: readonly string[];\n\tapps: readonly StackApp[];\n\tmaster: string;\n\thttps: number;\n\thttp: number;\n}): StackFile {\n\tconst { project, plan, infra, apps } = options;\n\n\t// Reconcile's definitions — images, health checks, volumes — with nothing\n\t// published to the host. Ports are allocation's business there; here the\n\t// edge is the only way in.\n\tconst derived = composeFor(\n\t\t{ ...plan, containers: [...infra] },\n\t\t{\n\t\t\tproject,\n\t\t\tports: Object.fromEntries(\n\t\t\t\tportKeys(infra, plan.fakes).map((key) => [key, 0]),\n\t\t\t),\n\t\t},\n\t);\n\n\tconst services: Record<string, StackService> = {};\n\tconst volumes: Record<string, Record<string, never>> = {\n\t\t...derived.volumes,\n\t\t'caddy-data': {},\n\t\t'caddy-config': {},\n\t};\n\n\tfor (const name of infra) {\n\t\tconst {\n\t\t\tports: _ports,\n\t\t\tdepends_on,\n\t\t\tprofiles: _profiles,\n\t\t\t...service\n\t\t} = derived.services[name]!;\n\t\tservices[name] = {\n\t\t\t...service,\n\t\t\t...(depends_on?.length\n\t\t\t\t? {\n\t\t\t\t\t\tdepends_on: Object.fromEntries(\n\t\t\t\t\t\t\tdepends_on.map((dep) => [dep, HEALTHY]),\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\tconst postgres = services.postgres;\n\tif (postgres) {\n\t\tpostgres.environment = {\n\t\t\t...postgres.environment,\n\t\t\tPOSTGRES_PASSWORD: options.master,\n\t\t};\n\t\t// Loopback only, on a port Docker picks: gkm creates the databases and\n\t\t// roles and runs the migrations from this machine, and nothing else\n\t\t// should reach the database from outside the stack.\n\t\tpostgres.ports = ['127.0.0.1::5432'];\n\t}\n\n\tfor (const app of apps) {\n\t\tservices[app.name] = {\n\t\t\timage: app.ref,\n\t\t\t...(app.build\n\t\t\t\t? {\n\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\tcontext: '../../..',\n\t\t\t\t\t\t\tdockerfile: app.build.dockerfile,\n\t\t\t\t\t\t\t...(app.build.args ? { args: app.build.args } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\trestart: 'unless-stopped',\n\t\t\t// A site is a bundle and reads nothing at runtime; a backend reads\n\t\t\t// exactly the keys in its own file.\n\t\t\t...(app.kind === 'rest-api'\n\t\t\t\t? {\n\t\t\t\t\t\tenv_file: [{ path: `./${app.name}.env`, format: 'raw' as const }],\n\t\t\t\t\t\t...(infra.length\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tdepends_on: Object.fromEntries(\n\t\t\t\t\t\t\t\t\t\tinfra.map((name) => [name, HEALTHY]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\thealthcheck: probe(app.port, app.kind === 'site' ? '/' : '/health'),\n\t\t};\n\t}\n\n\tservices.caddy = {\n\t\timage: DEFAULT_IMAGES.caddy!,\n\t\trestart: 'unless-stopped',\n\t\tports: [`${options.https}:443`, `${options.http}:80`],\n\t\tvolumes: [\n\t\t\t'./Caddyfile:/etc/caddy/Caddyfile:ro',\n\t\t\t'caddy-data:/data',\n\t\t\t'caddy-config:/config',\n\t\t],\n\t\tdepends_on: Object.fromEntries(apps.map((app) => [app.name, HEALTHY])),\n\t\thealthcheck: {\n\t\t\ttest: ['CMD', 'caddy', 'version'],\n\t\t\tinterval: '10s',\n\t\t\ttimeout: '5s',\n\t\t\tretries: 5,\n\t\t},\n\t};\n\n\treturn { name: project, services, volumes };\n}\n\n/** Render an app's env file: one `KEY=value` per line, read raw by compose. */\nexport function envFile(env: Readonly<Record<string, string>>): string {\n\treturn `${Object.entries(env)\n\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t.join('\\n')}\\n`;\n}\n","/**\n * One construct's migrations and seeds, read from its folders.\n *\n * Two kinds of file, told apart by extension rather than by configuration: a\n * script exports `up` (and may export `down`) — or `seed(db, { stage })`, in\n * `seeds/` — and a\n * `.sql` file is run whole. The second is what makes a folder independent of\n * the client the app uses — Better Auth's schema is SQL whatever the\n * application queries with.\n */\n\nimport { readdir, readFile, stat } from 'node:fs/promises';\nimport { extname, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { Kysely, sql } from 'kysely';\nimport type { Migration, MigrationProvider } from 'kysely/migration';\n\nconst SCRIPTS = new Set(['.ts', '.mts', '.js', '.mjs']);\n\n/** Two files in one folder that would be one migration. */\nexport class DuplicateMigration extends Error {\n\tconstructor(\n\t\treadonly folder: string,\n\t\treadonly migration: string,\n\t) {\n\t\tsuper(\n\t\t\t`${folder} has two migrations named '${migration}' — a script and a .sql file ` +\n\t\t\t\t`with the same name. A migration is recorded by name, so only one of ` +\n\t\t\t\t`them could ever run; rename or remove the other.`,\n\t\t);\n\t\tthis.name = 'DuplicateMigration';\n\t}\n}\n\n/** A script in a migrations folder that exports no `up`. */\nexport class MigrationHasNoUp extends Error {\n\tconstructor(readonly file: string) {\n\t\tsuper(\n\t\t\t`${file} is in a migrations folder but exports no \\`up\\` function. ` +\n\t\t\t\t`Export \\`async function up(db: Kysely<unknown>)\\`, or move the file ` +\n\t\t\t\t`out of the folder if it is not a migration.`,\n\t\t);\n\t\tthis.name = 'MigrationHasNoUp';\n\t}\n}\n\n/** A script in a seeds folder that exports no `seed`. */\nexport class SeedHasNoSeed extends Error {\n\tconstructor(readonly file: string) {\n\t\tsuper(\n\t\t\t`${file} is in a seeds folder but exports no \\`seed\\` function. ` +\n\t\t\t\t`Export \\`async function seed(db, { stage })\\`, or move the ` +\n\t\t\t\t`file out of the folder if it is not a seed.`,\n\t\t);\n\t\tthis.name = 'SeedHasNoSeed';\n\t}\n}\n\n/**\n * What a seed is handed beside its database.\n *\n * Seeds run on every stage, production included, so a seed that should write\n * something only somewhere — a demo tenant on `development`, never on\n * `production` — decides by the stage it is given.\n */\nexport interface SeedContext {\n\t/** The stage being seeded: the local one, `test`, or a deployed one. */\n\tstage: string;\n}\n\n/** One seed: what it is called, and what it does. */\nexport interface Seed {\n\tname: string;\n\trun: (db: Kysely<unknown>, context: SeedContext) => Promise<void>;\n}\n\n/**\n * The migration files in a folder, by name, without reading them.\n *\n * Also what `gkm dev` compares against a construct's history to report what\n * is pending, which is why it is separate from loading them.\n */\nexport async function migrationFiles(\n\tfolder: string,\n): Promise<Map<string, string>> {\n\tconst entries = await readdir(folder, { withFileTypes: true }).catch(\n\t\t(error: NodeJS.ErrnoException) => {\n\t\t\tif (error.code === 'ENOENT') return [];\n\t\t\tthrow error;\n\t\t},\n\t);\n\n\tconst files = new Map<string, string>();\n\tfor (const entry of entries) {\n\t\tif (!entry.isFile() || !isMigration(entry.name)) continue;\n\n\t\tconst name = entry.name.slice(0, -extname(entry.name).length);\n\t\tif (files.has(name)) throw new DuplicateMigration(folder, name);\n\n\t\tfiles.set(name, join(folder, entry.name));\n\t}\n\n\treturn files;\n}\n\n/** A Kysely provider over one construct's folder. */\nexport function folderProvider(\n\tfolder: string,\n\traw: typeof sql,\n): MigrationProvider {\n\treturn {\n\t\tasync getMigrations() {\n\t\t\tconst migrations: Record<string, Migration> = {};\n\n\t\t\tfor (const [name, file] of await migrationFiles(folder)) {\n\t\t\t\tmigrations[name] =\n\t\t\t\t\textname(file) === '.sql'\n\t\t\t\t\t\t? await sqlMigration(file, raw)\n\t\t\t\t\t\t: await scriptMigration(file);\n\t\t\t}\n\n\t\t\treturn migrations;\n\t\t},\n\t};\n}\n\n/**\n * The seeds in a folder, loaded, in name order.\n *\n * Every one runs on every pass — there is no history to consult — so the order\n * is the only thing between two seeds where one reads what another writes.\n * Name them to sort that way.\n */\nexport async function loadSeeds(\n\tfolder: string,\n\traw: typeof sql,\n): Promise<Seed[]> {\n\tconst files = [...(await migrationFiles(folder))].sort(([a], [b]) =>\n\t\ta < b ? -1 : a > b ? 1 : 0,\n\t);\n\n\tconst seeds: Seed[] = [];\n\tfor (const [name, file] of files) {\n\t\tseeds.push({\n\t\t\tname,\n\t\t\trun:\n\t\t\t\textname(file) === '.sql'\n\t\t\t\t\t? (await sqlMigration(file, raw)).up\n\t\t\t\t\t: await scriptSeed(file),\n\t\t});\n\t}\n\n\treturn seeds;\n}\n\n/**\n * A seed script, imported as it is on disk now.\n *\n * Keyed by its modification time: a seed is run again after it is edited, and\n * a process that has imported it once would otherwise run the old one.\n */\nasync function scriptSeed(file: string): Promise<Seed['run']> {\n\tconst url = pathToFileURL(file);\n\turl.searchParams.set('mtime', String((await stat(file)).mtimeMs));\n\tconst module = (await import(url.href)) as { seed?: unknown };\n\tif (typeof module.seed !== 'function') throw new SeedHasNoSeed(file);\n\n\treturn module.seed as Seed['run'];\n}\n\nfunction isMigration(file: string): boolean {\n\tif (file.endsWith('.d.ts')) return false;\n\tif (/\\.(spec|test)\\.[cm]?[jt]s$/.test(file)) return false;\n\n\tconst extension = extname(file);\n\treturn extension === '.sql' || SCRIPTS.has(extension);\n}\n\nasync function scriptMigration(file: string): Promise<Migration> {\n\tconst module = (await import(pathToFileURL(file).href)) as Partial<Migration>;\n\tif (typeof module.up !== 'function') throw new MigrationHasNoUp(file);\n\n\treturn {\n\t\tup: module.up,\n\t\t...(typeof module.down === 'function' ? { down: module.down } : {}),\n\t};\n}\n\n/**\n * A `.sql` file, run whole.\n *\n * One query rather than split on `;`: with no parameters, Postgres takes\n * several statements in one message, and splitting by hand breaks on the first\n * `;` inside a string or a function body. There is no `down` — a generated\n * schema is rolled back by a migration that says how, not by guessing.\n */\nasync function sqlMigration(file: string, raw: typeof sql): Promise<Migration> {\n\tconst statements = await readFile(file, 'utf-8');\n\n\treturn {\n\t\tup: async (db: Kysely<unknown>) => {\n\t\t\tawait raw.raw(statements).execute(db);\n\t\t},\n\t};\n}\n","/**\n * Bring each construct's schema up to its migrations folder.\n *\n * Which constructs, in what order, from which folder, is `migrationTargets`'\n * answer and nobody else's. What is decided here is only how one target is\n * run: as its owner, in its own schema, with a history of its own.\n */\n\nimport { readdir } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport {\n\ttype ConstructManifest,\n\tcanonicalId,\n\tDATABASE_FOLDERS,\n\tMIGRATIONS_ROOT,\n\ttype MigrationTarget,\n\tmigrationTargets,\n\tprovideKey,\n} from '@geekmidas/manifest';\nimport type { Kysely } from 'kysely';\nimport type { Migrator } from 'kysely/migration';\nimport pg from 'pg';\nimport type { ConstructSource } from '../reconcile/discover';\nimport { folderProvider, loadSeeds, migrationFiles } from './provider';\n\nexport interface DatabasesOptions {\n\t/** The project root — where `db/` lives. */\n\troot: string;\n\tmanifest: ConstructManifest;\n\t/**\n\t * Where each construct was declared. A construct's migrations run with the\n\t * Kysely its own file resolves, which is the one its migrations import.\n\t */\n\tsources?: Readonly<Record<string, ConstructSource>>;\n\t/** The resolved environment: each construct's owner URL is read from it. */\n\tenv: Readonly<Record<string, string | undefined>>;\n\t/** One construct, by name. All of them when absent. */\n\tonly?: string;\n}\n\nexport interface MigrationRun {\n\ttarget: MigrationTarget;\n\t/** The migrations this run applied, in order. */\n\tapplied: string[];\n}\n\nexport interface SeedOptions extends DatabasesOptions {\n\t/** The stage being seeded, handed to every seed. */\n\tstage: string;\n}\n\nexport interface SeedRun {\n\ttarget: MigrationTarget;\n\t/** The seeds this run ran, in order — every one, every time. */\n\tseeded: string[];\n}\n\nexport interface PendingMigrations {\n\ttarget: MigrationTarget;\n\tpending: string[];\n}\n\n/** A folder under `db/` that names no construct. */\nexport class UnknownMigrationFolder extends Error {\n\tconstructor(\n\t\treadonly folder: string,\n\t\treadonly known: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`${folder} names no database construct, so its migrations would never ` +\n\t\t\t\t`run. ${known.length > 0 ? `The folders that do: ${known.join(', ')}.` : 'This project declares no database.'} ` +\n\t\t\t\t`Rename the folder after the construct it belongs to.`,\n\t\t);\n\t\tthis.name = 'UnknownMigrationFolder';\n\t}\n}\n\n/** A construct was asked for by a name that takes no migrations. */\nexport class NoSuchMigrationTarget extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly known: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`'${construct}' is not a database construct. ` +\n\t\t\t\t(known.length > 0\n\t\t\t\t\t? `The ones with migrations: ${known.join(', ')}.`\n\t\t\t\t\t: 'This project declares no database.'),\n\t\t);\n\t\tthis.name = 'NoSuchMigrationTarget';\n\t}\n}\n\n/**\n * A migration left directly in a construct's folder, where nothing reads it.\n *\n * Migrations moved into `migrations/` so seeds could sit beside them. A file\n * still at the old level would otherwise never run, and nothing would say so.\n */\nexport class MigrationsOutsideFolder extends Error {\n\tconstructor(\n\t\treadonly folder: string,\n\t\treadonly files: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`${folder} has ${files.join(', ')} directly inside it, where nothing ` +\n\t\t\t\t`runs them. Migrations live in ${folder}/migrations/ and seeds in ` +\n\t\t\t\t`${folder}/seeds/ — move ${files.length === 1 ? 'it' : 'them'} there.`,\n\t\t);\n\t\tthis.name = 'MigrationsOutsideFolder';\n\t}\n}\n\n/** A folder inside a construct's folder that is neither `migrations` nor `seeds`. */\nexport class UnknownDatabaseFolder extends Error {\n\tconstructor(readonly folder: string) {\n\t\tsuper(\n\t\t\t`${folder} is neither migrations/ nor seeds/, so nothing in it would ` +\n\t\t\t\t`ever run. A construct's folder holds those two; rename or remove it.`,\n\t\t);\n\t\tthis.name = 'UnknownDatabaseFolder';\n\t}\n}\n\n/** A seed failed; its own writes are rolled back, the ones before it stay. */\nexport class SeedFailed extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly seed: string,\n\t\toverride readonly cause: unknown,\n\t) {\n\t\tsuper(\n\t\t\t`${construct}: seed '${seed}' failed — ` +\n\t\t\t\t`${cause instanceof Error ? cause.message : String(cause)}. ` +\n\t\t\t\t`Its writes were rolled back; fix it and run it again.`,\n\t\t);\n\t\tthis.name = 'SeedFailed';\n\t}\n}\n\n/** A construct with roles has no owner URL to migrate with. */\nexport class NoOwnerCredential extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly key: string,\n\t) {\n\t\tsuper(\n\t\t\t`${construct} has no ${key} to migrate with. Migrations run as the owner ` +\n\t\t\t\t`role — the runtime one cannot create a table — and nothing ` +\n\t\t\t\t`resolved its URL. Is the stage reconciled?`,\n\t\t);\n\t\tthis.name = 'NoOwnerCredential';\n\t}\n}\n\n/** A migration failed; the ones before it in the run stay applied. */\nexport class MigrationFailed extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly migration: string | undefined,\n\t\toverride readonly cause: unknown,\n\t) {\n\t\tsuper(\n\t\t\t`${construct}: migration ${migration ? `'${migration}' ` : ''}failed — ` +\n\t\t\t\t`${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t);\n\t\tthis.name = 'MigrationFailed';\n\t}\n}\n\n/** The project's Kysely could not be found from where a database is declared. */\nexport class KyselyNotFound extends Error {\n\tconstructor(readonly from: string) {\n\t\tsuper(\n\t\t\t`Could not resolve 'kysely' from ${from}. Migrations run with the ` +\n\t\t\t\t`project's own Kysely — install it where the database is declared.`,\n\t\t);\n\t\tthis.name = 'KyselyNotFound';\n\t}\n}\n\n/** Apply every pending migration, construct by construct, parents first. */\nexport async function migrateDatabases(\n\toptions: DatabasesOptions,\n): Promise<MigrationRun[]> {\n\tconst runs: MigrationRun[] = [];\n\n\tfor (const target of await targetsFor(options)) {\n\t\t// No folder, or an empty one, is nothing to do — and no reason to\n\t\t// connect, which a construct nobody has written a migration for yet\n\t\t// should not need.\n\t\tconst files = await migrationFiles(join(options.root, target.migrations));\n\t\tif (files.size === 0) {\n\t\t\truns.push({ target, applied: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst applied = await withMigrator(options, target, async (migrator) => {\n\t\t\tconst { error, results = [] } = await migrator.migrateToLatest();\n\t\t\tif (error) {\n\t\t\t\tconst failed = results.find((result) => result.status === 'Error');\n\t\t\t\tthrow new MigrationFailed(target.id, failed?.migrationName, error);\n\t\t\t}\n\n\t\t\treturn results\n\t\t\t\t.filter((result) => result.status === 'Success')\n\t\t\t\t.map((result) => result.migrationName);\n\t\t});\n\n\t\truns.push({ target, applied });\n\t}\n\n\treturn runs;\n}\n\n/**\n * Run every construct's seeds, parents first — each one, every time, on every\n * stage, production included. Each is handed the stage, so a seed decides\n * what belongs where.\n *\n * Seeds are reference data kept up to date by being run again, so there is no\n * history: a seed is an upsert, and a changed one is applied by the next run.\n * Each runs in its own transaction, as the construct's owner, so a failure\n * leaves nothing half-written. Assumes the schema is migrated —\n * {@link migrateAndSeed} is what makes that true.\n */\nexport async function seedDatabases(options: SeedOptions): Promise<SeedRun[]> {\n\tconst runs: SeedRun[] = [];\n\n\tfor (const target of await targetsFor(options)) {\n\t\tconst folder = join(options.root, target.seeds);\n\t\tif ((await migrationFiles(folder)).size === 0) {\n\t\t\truns.push({ target, seeded: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst seeded = await withOwner(options, target, async (db, kysely) => {\n\t\t\tconst names: string[] = [];\n\t\t\tfor (const seed of await loadSeeds(folder, kysely.sql)) {\n\t\t\t\ttry {\n\t\t\t\t\tawait db\n\t\t\t\t\t\t.transaction()\n\t\t\t\t\t\t.execute((trx) => seed.run(trx, { stage: options.stage }));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new SeedFailed(target.id, seed.name, error);\n\t\t\t\t}\n\t\t\t\tnames.push(seed.name);\n\t\t\t}\n\t\t\treturn names;\n\t\t});\n\n\t\truns.push({ target, seeded });\n\t}\n\n\treturn runs;\n}\n\n/**\n * Migrate, then seed: a seed only ever runs against the schema it was written\n * for.\n *\n * With `only`, the constructs it lives in are migrated too — a tenant's seed\n * cannot run before the database that owns its schema exists — and only it is\n * seeded.\n */\nexport async function migrateAndSeed(options: SeedOptions): Promise<{\n\tmigrations: MigrationRun[];\n\tseeds: SeedRun[];\n}> {\n\tconst migrations: MigrationRun[] = [];\n\tfor (const target of await withParents(options)) {\n\t\tmigrations.push(\n\t\t\t...(await migrateDatabases({ ...options, only: target.id })),\n\t\t);\n\t}\n\n\treturn { migrations, seeds: await seedDatabases(options) };\n}\n\n/** The targets `only` names, after the ones it lives in; all without it. */\nasync function withParents(\n\toptions: DatabasesOptions,\n): Promise<MigrationTarget[]> {\n\tconst chosen = await targetsFor(options);\n\tif (!options.only) return chosen;\n\n\tconst all = migrationTargets(options.manifest);\n\tconst ids = new Set<string>();\n\tfor (const target of chosen) {\n\t\tlet current: MigrationTarget | undefined = target;\n\t\twhile (current) {\n\t\t\tids.add(current.id);\n\t\t\tconst parent: string | undefined = current.of;\n\t\t\tcurrent = parent ? all.find((t) => t.id === parent) : undefined;\n\t\t}\n\t}\n\n\treturn all.filter((target) => ids.has(target.id));\n}\n\n/**\n * What each construct's folder has that its history does not — without\n * applying any of it. What `gkm dev` reports.\n */\nexport async function pendingMigrations(\n\toptions: DatabasesOptions,\n): Promise<PendingMigrations[]> {\n\tconst found: PendingMigrations[] = [];\n\n\tfor (const target of await targetsFor(options)) {\n\t\tconst files = await migrationFiles(join(options.root, target.migrations));\n\t\tif (files.size === 0) continue;\n\n\t\tconst pending = await withMigrator(options, target, async (migrator) =>\n\t\t\t(await migrator.getMigrations())\n\t\t\t\t.filter((migration) => migration.executedAt === undefined)\n\t\t\t\t.map((migration) => migration.name),\n\t\t);\n\n\t\tif (pending.length > 0) found.push({ target, pending });\n\t}\n\n\treturn found;\n}\n\n/**\n * The targets this run covers, with every folder under `db/` accounted for.\n *\n * A folder that names no construct is an error rather than something to skip:\n * a typo in its name is otherwise a migration that silently never runs.\n */\nasync function targetsFor(\n\toptions: DatabasesOptions,\n): Promise<MigrationTarget[]> {\n\tconst targets = migrationTargets(options.manifest);\n\tconst folders = targets.map((target) => target.folder);\n\n\tfor (const folder of await foldersIn(join(options.root, MIGRATIONS_ROOT))) {\n\t\tconst relative = `${MIGRATIONS_ROOT}/${folder}`;\n\t\tif (!folders.includes(relative)) {\n\t\t\tthrow new UnknownMigrationFolder(relative, folders);\n\t\t}\n\t\tawait checkLayout(options.root, relative);\n\t}\n\n\tif (!options.only) return targets;\n\n\tconst id = canonicalId(options.only);\n\tconst chosen = targets.filter((target) => target.id === id);\n\tif (chosen.length === 0) {\n\t\tthrow new NoSuchMigrationTarget(\n\t\t\toptions.only,\n\t\t\ttargets.map((target) => target.id),\n\t\t);\n\t}\n\n\treturn chosen;\n}\n\n/**\n * A construct's folder holds `migrations/` and `seeds/`, and nothing else —\n * anything beside them is a file or folder nothing would ever run.\n */\nasync function checkLayout(root: string, folder: string): Promise<void> {\n\tconst entries = await readdir(join(root, folder), { withFileTypes: true });\n\n\tconst loose = entries\n\t\t.filter((entry) => entry.isFile() && !entry.name.startsWith('.'))\n\t\t.map((entry) => entry.name);\n\tif (loose.length > 0) throw new MigrationsOutsideFolder(folder, loose);\n\n\tfor (const entry of entries) {\n\t\tif (\n\t\t\tentry.isDirectory() &&\n\t\t\t!(DATABASE_FOLDERS as readonly string[]).includes(entry.name)\n\t\t) {\n\t\t\tthrow new UnknownDatabaseFolder(`${folder}/${entry.name}`);\n\t\t}\n\t}\n}\n\nasync function foldersIn(dir: string): Promise<string[]> {\n\tconst entries = await readdir(dir, { withFileTypes: true }).catch(\n\t\t(error: NodeJS.ErrnoException) => {\n\t\t\tif (error.code === 'ENOENT') return [];\n\t\t\tthrow error;\n\t\t},\n\t);\n\n\treturn entries\n\t\t.filter((entry) => entry.isDirectory())\n\t\t.map((entry) => entry.name);\n}\n\n/**\n * A migrator for one target, connected as its owner.\n *\n * No `migrationTableSchema`: the owner role's `search_path` is pinned to the\n * construct's schema, so the history lands there — `app.kysely_migration` for\n * the database, `auth_database.kysely_migration` for its tenant — and two\n * constructs in one Postgres never share one.\n *\n * Unordered migrations are allowed. Files are timestamped, so a branch merged\n * after another's migration ran carries an older one; refusing it would make\n * every such merge a manual repair.\n */\nasync function withMigrator<T>(\n\toptions: DatabasesOptions,\n\ttarget: MigrationTarget,\n\trun: (migrator: Migrator) => Promise<T>,\n): Promise<T> {\n\treturn withOwner(options, target, (db, { Migrator, sql }) =>\n\t\trun(\n\t\t\tnew Migrator({\n\t\t\t\tdb,\n\t\t\t\tprovider: folderProvider(join(options.root, target.migrations), sql),\n\t\t\t\tallowUnorderedMigrations: true,\n\t\t\t}),\n\t\t),\n\t);\n}\n\n/**\n * One target's database, connected as its owner and closed afterwards — what\n * migrations and seeds both run as.\n */\nasync function withOwner<T>(\n\toptions: DatabasesOptions,\n\ttarget: MigrationTarget,\n\trun: (\n\t\tdb: Kysely<unknown>,\n\t\tkysely: Awaited<ReturnType<typeof kyselyFrom>>,\n\t) => Promise<T>,\n): Promise<T> {\n\tconst from =\n\t\toptions.sources?.[target.id]?.file ??\n\t\t(target.of ? options.sources?.[target.of]?.file : undefined) ??\n\t\tjoin(options.root, 'package.json');\n\tconst kysely = await kyselyFrom(from);\n\n\tconst db: Kysely<unknown> = new kysely.Kysely<unknown>({\n\t\tdialect: new kysely.PostgresDialect({\n\t\t\tpool: new pg.Pool(poolConfig(ownerUrl(options, target))),\n\t\t}),\n\t});\n\n\ttry {\n\t\treturn await run(db, kysely);\n\t} finally {\n\t\tawait db.destroy();\n\t}\n}\n\n/**\n * The owner's URL, with no fallback to the runtime one.\n *\n * The runtime role can create nothing, so falling back would only move the\n * failure to the first `CREATE TABLE` and make it read like a permissions\n * bug. The one exception is a database declared `roles: false`, where there is\n * no owner — both URLs are the master credential by design.\n */\nfunction ownerUrl(options: DatabasesOptions, target: MigrationTarget): string {\n\tconst key = provideKey(target.id, 'ownerUrl');\n\tconst owner = options.env[key];\n\tif (owner) return owner;\n\n\tconst database = options.manifest[target.of ?? target.id];\n\tif (database?.kind === 'database' && database.roles === false) {\n\t\tconst url = options.env[provideKey(target.id, 'url')];\n\t\tif (url) return url;\n\t}\n\n\tthrow new NoOwnerCredential(target.id, key);\n}\n\n/**\n * Pool settings for a URL, with `?search_path=` as the startup option Postgres\n * reads. Only a `roles: false` URL carries it — a role pins its own.\n */\nfunction poolConfig(url: string): pg.PoolConfig {\n\tconst parsed = new URL(url);\n\tconst searchPath = parsed.searchParams.get('search_path');\n\tif (!searchPath) return { connectionString: url };\n\n\tparsed.searchParams.delete('search_path');\n\treturn {\n\t\tconnectionString: parsed.toString(),\n\t\toptions: `-c search_path=${searchPath}`,\n\t};\n}\n\n/** Kysely as the project resolves it from `from`. */\nasync function kyselyFrom(from: string) {\n\tconst require = createRequire(from);\n\n\ttry {\n\t\tconst [main, migration] = await Promise.all([\n\t\t\timport(pathToFileURL(require.resolve('kysely')).href),\n\t\t\timport(pathToFileURL(require.resolve('kysely/migration')).href),\n\t\t]);\n\n\t\treturn {\n\t\t\tKysely: main.Kysely as typeof import('kysely').Kysely,\n\t\t\tPostgresDialect:\n\t\t\t\tmain.PostgresDialect as typeof import('kysely').PostgresDialect,\n\t\t\tsql: main.sql as typeof import('kysely').sql,\n\t\t\tMigrator:\n\t\t\t\tmigration.Migrator as typeof import('kysely/migration').Migrator,\n\t\t};\n\t} catch {\n\t\tthrow new KyselyNotFound(from);\n\t}\n}\n","/**\n * Asking each app of a stack whether it answers — through Caddy, over HTTPS,\n * the way a browser reaches it.\n *\n * `docker compose up --wait` already knows each container passed its own\n * health check, asked on 127.0.0.1 inside it. What that cannot say is whether\n * the stack is reachable: whether the edge routes the host to the app, and\n * whether the certificate it presents is one a client accepts. So the check\n * goes through the edge, by hostname, and verifies the certificate.\n */\n\nimport { request } from 'node:https';\n\n/** One request to the edge. */\nexport interface HealthRequest {\n\t/** The app's public URL plus its health path. */\n\turl: string;\n\t/**\n\t * The certificate authority to verify against, PEM — Caddy's internal CA\n\t * on the local stage. The system's when absent.\n\t */\n\tca?: string;\n\t/**\n\t * Connect here instead of resolving the URL's host — the local edge, at\n\t * 127.0.0.1. The host is still sent as SNI and `Host`, so nothing depends\n\t * on how this machine resolves `*.localhost`.\n\t */\n\tconnectTo?: string;\n\ttimeoutMs: number;\n\tsignal?: AbortSignal;\n}\n\n/** Asks once, resolving with the HTTP status. Rejects when nothing answers. */\nexport type HealthProbe = (request: HealthRequest) => Promise<number>;\n\n/** A request that got no answer in time. */\nexport class HealthRequestTimedOut extends Error {\n\tconstructor(\n\t\treadonly url: string,\n\t\treadonly timeoutMs: number,\n\t) {\n\t\tsuper(\n\t\t\t`${url} did not answer within ${timeoutMs}ms. Check the stack is up with \\`docker compose ps\\`.`,\n\t\t);\n\t\tthis.name = 'HealthRequestTimedOut';\n\t}\n}\n\n/** The real probe: one HTTPS GET, the certificate verified. */\nexport const httpsProbe: HealthProbe = ({\n\turl,\n\tca,\n\tconnectTo,\n\ttimeoutMs,\n\tsignal,\n}) => {\n\tconst target = new URL(url);\n\treturn new Promise((resolve, reject) => {\n\t\tconst req = request(\n\t\t\t{\n\t\t\t\thost: connectTo ?? target.hostname,\n\t\t\t\tport: target.port || 443,\n\t\t\t\tservername: target.hostname,\n\t\t\t\tpath: `${target.pathname}${target.search}`,\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { host: target.host },\n\t\t\t\t...(ca ? { ca } : {}),\n\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\ttimeout: timeoutMs,\n\t\t\t},\n\t\t\t(res) => {\n\t\t\t\t// The status is the answer; the body is drained so the socket closes.\n\t\t\t\tres.resume();\n\t\t\t\tres.on('end', () => resolve(res.statusCode ?? 0));\n\t\t\t\tres.on('error', reject);\n\t\t\t},\n\t\t);\n\t\treq.on('timeout', () =>\n\t\t\treq.destroy(new HealthRequestTimedOut(url, timeoutMs)),\n\t\t);\n\t\treq.on('error', reject);\n\t\treq.end();\n\t});\n};\n\n/** Whether a status means the app answered as it should. */\nexport function isHealthy(status: number): boolean {\n\treturn status >= 200 && status < 400;\n}\n\n/** Apps that did not answer through the edge. */\nexport class ComposeAppsUnhealthy extends Error {\n\tconstructor(\n\t\treadonly project: string,\n\t\t/** Each app, and the last thing its check got: a status or an error. */\n\t\treadonly apps: readonly { app: string; url: string; last: string }[],\n\t) {\n\t\tsuper(\n\t\t\t`${project} started, but ${apps.length === 1 ? 'this app does' : 'these apps do'} not answer through Caddy:\\n` +\n\t\t\t\tapps.map(({ url, last }) => ` - ${url}: ${last}`).join('\\n') +\n\t\t\t\t`\\nSee why with \\`docker compose -p ${project} logs caddy ${apps.map((a) => a.app).join(' ')}\\`.`,\n\t\t);\n\t\tthis.name = 'ComposeAppsUnhealthy';\n\t}\n}\n","/**\n * The compose target's phases: a stage as one Docker Compose stack behind\n * Caddy, on the machine the deploy runs on.\n *\n * The order is the point of this file, and the rules it keeps are these:\n *\n * - A tag is checked before anything happens (`validate`). Every app's image\n * is asked of the registry first; one missing image stops the run naming\n * them all, and nothing is written, pulled or started.\n * - The databases exist before the apps do (`provision`). Postgres comes up\n * alone, its databases, roles and grants are created and its migrations\n * applied from this machine, and only then do the apps start — so an app\n * never boots against a schema that is not there yet.\n * - What a stage runs is recorded (`release`). Each app's image, the tag it\n * was released under and the digest it resolved to are written to the\n * stage's state, so \"what is this stage running\" has an exact answer.\n * - What was started answers (`verify`): each app is asked through Caddy,\n * over HTTPS, with the certificate verified.\n *\n * Docker, the registry, the bundler, Postgres and the health probe are\n * injected, so the rules are asserted without a daemon; the defaults are the\n * real ones.\n */\n\nimport { existsSync } from 'node:fs';\nimport {\n\tappendFile,\n\tchmod,\n\tmkdir,\n\treadFile,\n\twriteFile,\n} from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ConstructManifest } from '@geekmidas/manifest';\nimport { stringify } from 'yaml';\nimport {\n\ttype ComposeDocker,\n\tdockerCompose,\n\ttype StackRef,\n} from '../../compose/docker';\nimport { assertImagesExist } from '../../compose/images';\nimport {\n\ttype ComposeStack,\n\tcomposeProject,\n\tcomposeStack,\n\tEDGE_PORT_ENV,\n\tenvFile,\n\ttype StackApp,\n\tstackDir,\n} from '../../compose/stack';\nimport type { ResourceChange } from '../../deploy/events';\nimport { withGeneratedSecrets } from '../../deploy/generated.js';\nimport { DeployJournal } from '../../deploy/journal';\nimport {\n\tcreateEmptyState,\n\ttype DeployedImage,\n\tsetDeployedImage,\n} from '../../deploy/state.js';\nimport type { DeployResult } from '../../deploy/types';\nimport { appPackageName } from '../../docker/index.js';\nimport {\n\tdetectPackageManager,\n\tgenerateDockerignore,\n} from '../../docker/templates.js';\nimport { migrateDatabases } from '../../migrate/databases.js';\nimport { pgClient } from '../../reconcile/clients.js';\nimport { primaryPortKey } from '../../reconcile/containers.js';\nimport { type ConstructSource, discover } from '../../reconcile/discover.js';\nimport { envFor } from '../../reconcile/env.js';\nimport {\n\tapplyPostgres,\n\tpostgresStatements,\n} from '../../reconcile/provision.js';\nimport { constructGlobs } from '../../reconcile/workspace.js';\nimport { runOutput } from '../../run';\nimport { LocalSandbox } from '../../sandbox/local';\nimport { activeSandbox } from '../../sandbox/sandbox';\nimport { initStageSecrets } from '../../secrets/storage.js';\nimport type { StageSecrets } from '../../secrets/types.js';\nimport type { NormalizedWorkspace } from '../../workspace/types.js';\nimport type { DeployPhaseContext } from '../types';\nimport {\n\tComposeAppsUnhealthy,\n\ttype HealthProbe,\n\thttpsProbe,\n\tisHealthy,\n} from './health';\n\n/** Every phase's context: the compose target takes no options. */\nexport type ComposeContext = DeployPhaseContext<undefined>;\n\n/** What the target needs from outside the process, so tests can stand in. */\nexport interface ComposeDeps {\n\tdocker: ComposeDocker;\n\t/**\n\t * Bundle one backend for production, in its own directory. By default\n\t * `gkm build --provider server --production`, run in the deploy's sandbox:\n\t * it imports the project's code.\n\t */\n\tbundle: (appRoot: string, ctx: ComposeContext) => Promise<void>;\n\t/** The commit a build is tagged with. */\n\trevision: (root: string) => Promise<string>;\n\t/** The Postgres client provisioning and migrations connect through. */\n\tsql: typeof pgClient;\n\t/** Apply the stage's migrations — `migrateDatabases` by default. */\n\tmigrate: typeof migrateDatabases;\n\t/** Ask one app, through the edge, whether it answers. */\n\tprobe: HealthProbe;\n\t/** How many times each app is asked before it counts as down. */\n\thealthAttempts: number;\n\t/** How long to wait between two asks of one app. */\n\thealthIntervalMs: number;\n\t/** Where the edge's ports are read from (`GKM_COMPOSE_HTTPS_PORT`, …). */\n\tenv: NodeJS.ProcessEnv;\n}\n\n/** One app's image, as the stage runs it. */\nexport interface ComposeImage {\n\tref: string;\n\ttag: string;\n\tdigest?: string;\n}\n\n/** A compose deploy in progress: what `validate` found, and what follows. */\nexport interface ComposeRun {\n\t/** Build the images from this checkout, or pull the ones a tag names. */\n\tmode: 'build' | 'pull';\n\tstack: ComposeStack;\n\t/** The stack's directory, absolute: `.gkm/compose/<stage>`. */\n\tdir: string;\n\tref: StackRef;\n\t/** The stage's secrets, with whatever a deployed stage generates once. */\n\tsecrets: StageSecrets | null;\n\t/** The names of what was generated, written back in `provision`. */\n\tgenerated: string[];\n\t/** Each app's image as the stage's state last recorded it. */\n\tprevious: Record<string, DeployedImage>;\n\t/** Every file written, absolute. */\n\tfiles: string[];\n\t/** Each app's image, once built or pulled. */\n\timages: Record<string, ComposeImage>;\n\t/** Every resource the run touched, or for a dry run would. */\n\tchanges: ResourceChange[];\n}\n\n/** A port variable that does not hold a port. */\nexport class EdgePortInvalid extends Error {\n\tconstructor(\n\t\treadonly variable: string,\n\t\treadonly value: string,\n\t) {\n\t\tsuper(\n\t\t\t`${variable}=${value} is not a port. Set it to a number between 1 and 65535, or unset it for the default.`,\n\t\t);\n\t\tthis.name = 'EdgePortInvalid';\n\t}\n}\n\n/** A build with no commit to tag its images with. */\nexport class NoGitRevision extends Error {\n\tconstructor(readonly root: string) {\n\t\tsuper(\n\t\t\t`Images built here are tagged with the commit they were built from, ` +\n\t\t\t\t`and ${root} is not in a git repository with a commit. Commit, or ` +\n\t\t\t\t`pass --tag to name the images yourself.`,\n\t\t);\n\t\tthis.name = 'NoGitRevision';\n\t}\n}\n\n/** A backend's production bundle did not build. */\nexport class BundleFailed extends Error {\n\tconstructor(\n\t\treadonly app: string,\n\t\treadonly exitCode: number | null,\n\t\treadonly stderr: string,\n\t) {\n\t\tsuper(\n\t\t\t`Bundling '${app}' for production failed (exit code ${exitCode}).` +\n\t\t\t\t`${stderr.trim() ? `\\n${stderr.trim().slice(-4000)}` : ''}\\n` +\n\t\t\t\t`Run \\`gkm build --provider server --production\\` in the app's directory to see it again.`,\n\t\t);\n\t\tthis.name = 'BundleFailed';\n\t}\n}\n\n/** The CLI's own entry, which the bundle step runs, is not where it should be. */\nexport class CliEntryNotFound extends Error {\n\tconstructor(readonly from: string) {\n\t\tsuper(\n\t\t\t`Could not find bin/gkm.mjs above ${from}, which bundling a backend runs. Reinstall @geekmidas/cli.`,\n\t\t);\n\t\tthis.name = 'CliEntryNotFound';\n\t}\n}\n\n/** The commit HEAD is at, short — and `-dirty` when the tree has changes. */\nexport async function gitRevision(root: string): Promise<string> {\n\tlet sha: string;\n\ttry {\n\t\tsha = (\n\t\t\tawait runOutput('git', ['rev-parse', '--short', 'HEAD'], { cwd: root })\n\t\t).trim();\n\t} catch {\n\t\tthrow new NoGitRevision(root);\n\t}\n\tif (!sha) throw new NoGitRevision(root);\n\n\t// An image built from uncommitted changes is not the commit's image, and a\n\t// tag that said it was would be the one thing worse than no tag.\n\tconst status = await runOutput('git', ['status', '--porcelain'], {\n\t\tcwd: root,\n\t}).catch(() => '');\n\treturn status.trim() ? `${sha}-dirty` : sha;\n}\n\n/** The edge's ports, from the environment — 443 and 80 when unset. */\nexport function edgePorts(env: NodeJS.ProcessEnv = process.env): {\n\thttps: number;\n\thttp: number;\n} {\n\tconst read = (variable: string, fallback: number) => {\n\t\tconst value = env[variable];\n\t\tif (value === undefined || value === '') return fallback;\n\t\tconst port = Number(value);\n\t\tif (!Number.isInteger(port) || port < 1 || port > 65_535) {\n\t\t\tthrow new EdgePortInvalid(variable, value);\n\t\t}\n\t\treturn port;\n\t};\n\treturn {\n\t\thttps: read(EDGE_PORT_ENV.https, 443),\n\t\thttp: read(EDGE_PORT_ENV.http, 80),\n\t};\n}\n\n/** `bin/gkm.mjs` of the CLI that is running. */\nfunction cliEntry(): string {\n\tconst from = dirname(fileURLToPath(import.meta.url));\n\tfor (let dir = from; dirname(dir) !== dir; dir = dirname(dir)) {\n\t\tconst entry = join(dir, 'bin', 'gkm.mjs');\n\t\tif (existsSync(entry)) return entry;\n\t}\n\tthrow new CliEntryNotFound(from);\n}\n\n/** A cold production bundle is seconds; a hung one must not hold the lock. */\nconst BUNDLE_TIMEOUT_MS = 10 * 60_000;\n\n/**\n * Bundle a backend with the gkm that is running — the same build a deploy\n * makes, so the image holds one file and no dependencies — in the run's\n * sandbox, because the build imports the project's code.\n */\nasync function bundleInSandbox(\n\tappRoot: string,\n\tctx: ComposeContext,\n): Promise<void> {\n\tconst sandbox = activeSandbox() ?? new LocalSandbox({ root: ctx.cwd });\n\tconst result = await sandbox.exec(\n\t\t'node',\n\t\t[cliEntry(), 'build', '--provider', 'server', '--production'],\n\t\t{\n\t\t\tcwd: appRoot,\n\t\t\tenv: sandbox.env,\n\t\t\ttimeoutMs: BUNDLE_TIMEOUT_MS,\n\t\t\toutput: ctx.childOutput,\n\t\t\tsignal: ctx.signal,\n\t\t},\n\t);\n\tif (result.exitCode !== 0) {\n\t\tthrow new BundleFailed(appRoot, result.exitCode, result.stderr);\n\t}\n}\n\n/**\n * The real ones. Each app is asked for three minutes before it counts as\n * down: a deployed stage's first ACME certificate can take that long.\n */\nexport const defaultDeps: ComposeDeps = {\n\tdocker: dockerCompose,\n\tbundle: bundleInSandbox,\n\trevision: gitRevision,\n\tsql: pgClient,\n\tmigrate: migrateDatabases,\n\tprobe: httpsProbe,\n\thealthAttempts: 90,\n\thealthIntervalMs: 2_000,\n\tenv: process.env,\n};\n\n// ============================================================================\n// validate\n// ============================================================================\n\n/**\n * The stack the stage would run, and — for a tag — the registry's word that\n * every image it names exists. Nothing is written: a missing image stops the\n * run here, before a file, a secret or a container is touched.\n */\nexport async function validateCompose(\n\tctx: ComposeContext,\n\tdeps: ComposeDeps,\n\tforced?: 'build' | 'pull',\n): Promise<ComposeRun> {\n\tconst { workspace, stage, identity, tag } = ctx;\n\tconst root = workspace.root;\n\tconst mode = forced ?? (ctx.tagGiven ? 'pull' : 'build');\n\n\t// The runnables' edges say which surface reaches which; the manifest the\n\t// run discovered has the declarations but not them.\n\tconst runnables: Record<string, string[]> = {};\n\tconst manifest = await discover({\n\t\tpatterns: constructGlobs(workspace),\n\t\tcwd: root,\n\t\trunnables,\n\t});\n\n\tconst { secrets, generated } = await stageSecrets(ctx, manifest);\n\n\tconst stack = composeStack({\n\t\tworkspace,\n\t\tmanifest,\n\t\trunnables,\n\t\tstage,\n\t\tidentity,\n\t\timages: {\n\t\t\tmode,\n\t\t\ttag,\n\t\t\t...(workspace.deploy?.registry\n\t\t\t\t? { registry: workspace.deploy.registry }\n\t\t\t\t: {}),\n\t\t},\n\t\tsecrets,\n\t\tports: edgePorts(deps.env),\n\t\tpackageManager: detectPackageManager(root),\n\t\tpackages: Object.fromEntries(\n\t\t\tObject.entries(workspace.apps).map(([name, app]) => [\n\t\t\t\tname,\n\t\t\t\tappPackageName(root, name, app.path),\n\t\t\t]),\n\t\t),\n\t});\n\n\t// A release is all of its images or none of them. A dry run asks nothing,\n\t// so it can be run without a registry login.\n\tif (mode === 'pull' && !ctx.dryRun) {\n\t\tawait assertImagesExist(deps.docker, tag, stack.apps);\n\t}\n\n\tconst dir = join(root, stackDir(stage));\n\tconst previous = (await ctx.state.read(stage))?.state.images ?? {};\n\n\treturn {\n\t\tmode,\n\t\tstack,\n\t\tdir,\n\t\tref: {\n\t\t\tproject: composeProject(identity),\n\t\t\tfile: join(dir, 'docker-compose.yml'),\n\t\t\tcwd: root,\n\t\t\toutput: ctx.childOutput,\n\t\t\tsignal: ctx.signal,\n\t\t},\n\t\tsecrets,\n\t\tgenerated,\n\t\tprevious,\n\t\tfiles: [],\n\t\timages: {},\n\t\tchanges: [],\n\t};\n}\n\n/**\n * The stage's secrets — and, for a deployed stage, everything it generates\n * once: its seed, and each declared secret and keyring. Kept only once the\n * run goes ahead (`provision`), so a dry run, or a tag that is not there,\n * leaves the stage's secrets as it found them.\n */\nasync function stageSecrets(\n\tctx: ComposeContext,\n\tmanifest: ConstructManifest,\n): Promise<{ secrets: StageSecrets | null; generated: string[] }> {\n\tconst stored = await ctx.secrets.read();\n\tif (ctx.stage === ctx.workspace.stages.local) {\n\t\treturn { secrets: stored, generated: [] };\n\t}\n\n\tconst { secrets, generated } = withGeneratedSecrets(\n\t\tstored ?? initStageSecrets(ctx.stage),\n\t\tmanifest,\n\t);\n\t// Read through the store they are masked; made up here, they are not yet.\n\tif (secrets.seed) ctx.secrets.mask(secrets.seed);\n\tfor (const value of Object.values(secrets.custom ?? {})) {\n\t\tctx.secrets.mask(value);\n\t}\n\treturn { secrets, generated };\n}\n\n// ============================================================================\n// plan (dry run)\n// ============================================================================\n\n/**\n * A dry run: the stack's files, written so they can be read, and what a real\n * run would do — no image is built or pulled, no container touched, nothing\n * recorded and no secret kept.\n */\nexport async function planCompose(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n): Promise<void> {\n\tif (run.generated.length > 0) {\n\t\tctx.logger.info(\n\t\t\t`🔑 \"${ctx.stage}\" has no ${run.generated.join(', ')} yet; this dry run used values it did not keep.`,\n\t\t);\n\t}\n\trun.files = await writeStack(ctx.cwd, run.dir, run.stack);\n\tprintPlan(ctx, run);\n\n\tconst planned = (change: ResourceChange) => {\n\t\trun.changes.push(change);\n\t\tctx.emit({ type: 'resource.planned', ...change });\n\t};\n\tfor (const service of run.stack.infra) {\n\t\tplanned({\n\t\t\tkey: `service:${service}`,\n\t\t\tresourceType: 'service',\n\t\t\taction: 'ensure',\n\t\t});\n\t}\n\tfor (const app of run.stack.apps) {\n\t\tplanned({\n\t\t\tkey: `image:${app.name}`,\n\t\t\tresourceType: 'image',\n\t\t\taction: run.mode === 'build' ? 'build' : 'reuse',\n\t\t\tid: app.ref,\n\t\t});\n\t\tplanned({\n\t\t\tkey: `service:${app.name}`,\n\t\t\tresourceType: 'service',\n\t\t\taction: run.previous[app.name] ? 'reuse' : 'create',\n\t\t});\n\t}\n\tplanned({ key: 'service:caddy', resourceType: 'service', action: 'ensure' });\n}\n\n// ============================================================================\n// provision\n// ============================================================================\n\n/**\n * What the apps run on: the stage's generated secrets kept, the stack's files\n * written, its infrastructure started, and its databases, roles, grants and\n * migrations applied.\n */\nexport async function provisionCompose(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tdeps: ComposeDeps,\n): Promise<void> {\n\tconst { stack, ref } = run;\n\n\tif (run.generated.length > 0 && run.secrets) {\n\t\tawait ctx.secrets.write(run.secrets);\n\t\tctx.logger.info(\n\t\t\t`🔑 Generated for \"${ctx.stage}\" (${ctx.secrets.store}): ${run.generated.join(', ')}`,\n\t\t);\n\t}\n\n\trun.files = await writeStack(ctx.cwd, run.dir, stack);\n\tprintPlan(ctx, run);\n\n\tif (stack.infra.length > 0) {\n\t\tctx.logger.info(`\\n🗄️ Starting ${stack.infra.join(', ')}…`);\n\t\tawait deps.docker.up(ref, stack.infra);\n\t\tfor (const service of stack.infra) {\n\t\t\tapplied(ctx, run, {\n\t\t\t\tkey: `service:${service}`,\n\t\t\t\tresourceType: 'service',\n\t\t\t\taction: 'ensure',\n\t\t\t\tid: `${stack.project}/${service}`,\n\t\t\t\tvia: Object.keys(run.previous).length > 0 ? 'recorded' : 'created',\n\t\t\t});\n\t\t}\n\t}\n\n\tif (stack.infra.includes('postgres')) {\n\t\tawait prepareDatabases(ctx, run, deps);\n\t}\n}\n\n/** Create what the plan names in the stack's Postgres, then migrate it. */\nasync function prepareDatabases(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tdeps: ComposeDeps,\n): Promise<void> {\n\tconst { stack } = run;\n\tconst workspace: NormalizedWorkspace = ctx.workspace;\n\tconst port = await deps.docker.port(run.ref, 'postgres', 5432);\n\n\tconst statements = postgresStatements(\n\t\tstack.plan,\n\t\tworkspace.name,\n\t\tstack.credential.seed,\n\t);\n\tif (statements.length > 0) {\n\t\tctx.logger.info('🗄️ Creating databases, roles and grants…');\n\t\tawait applyPostgres(deps.sql(port, stack.credential.master), statements);\n\t}\n\n\t// Migrations run here, with the project's own Kysely, the way `gkm\n\t// migrate` runs them — so the constructs themselves are needed, which\n\t// only an in-process discovery hands back.\n\tconst sources: Record<string, ConstructSource> = {};\n\tconst manifest = await discover({\n\t\tpatterns: constructGlobs(workspace),\n\t\tcwd: workspace.root,\n\t\tsources,\n\t});\n\n\t// The owner URLs, on the port published to this machine.\n\tconst env = envFor(stack.plan, {\n\t\tports: { [primaryPortKey('postgres')]: port },\n\t\tproject: workspace.name,\n\t\tmaster: stack.credential.master,\n\t\t...(stack.credential.seed ? { seed: stack.credential.seed } : {}),\n\t});\n\tconst runs = await deps.migrate({\n\t\troot: workspace.root,\n\t\tmanifest,\n\t\tsources,\n\t\tenv,\n\t});\n\tfor (const { target, applied } of runs) {\n\t\tif (applied.length > 0) {\n\t\t\tctx.logger.info(`🗄️ ${target.migrations}: applied ${applied.length}`);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// build\n// ============================================================================\n\n/**\n * Each app's image: built from this checkout — every backend bundled first,\n * on the host, with this CLI — or pulled at the tag. Nothing live changes.\n */\nexport async function buildCompose(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tdeps: ComposeDeps,\n): Promise<void> {\n\tconst { stack, ref } = run;\n\tconst apps = stack.apps.map((app) => app.name);\n\n\tif (run.mode === 'build') {\n\t\tfor (const app of stack.apps.filter((a) => a.kind === 'rest-api')) {\n\t\t\tctx.signal.throwIfAborted();\n\t\t\tctx.logger.info(`\\n📦 Bundling ${app.name}…`);\n\t\t\tawait deps.bundle(join(ctx.cwd, app.path), ctx);\n\t\t}\n\t\tctx.logger.info('\\n🐳 Building images…');\n\t\tawait deps.docker.build(ref, apps);\n\t} else {\n\t\tctx.logger.info(`\\n🐳 Pulling ${ctx.tag}…`);\n\t\tawait deps.docker.pull(ref, apps);\n\t}\n\n\t// What each tag resolved to: the registry's digest for a pulled image, or\n\t// — for one built here and never pushed — its content id.\n\tfor (const app of stack.apps) {\n\t\tconst digest = await deps.docker.digest(app.ref);\n\t\trun.images[app.name] = {\n\t\t\tref: app.ref,\n\t\t\ttag: app.tag,\n\t\t\t...(digest ? { digest } : {}),\n\t\t};\n\t\tctx.emit({\n\t\t\ttype: 'artifact.built',\n\t\t\tapp: app.name,\n\t\t\timageRef: app.ref,\n\t\t\t...(digest ? { digest } : {}),\n\t\t});\n\t\trun.changes.push({\n\t\t\tkey: `image:${app.name}`,\n\t\t\tresourceType: 'image',\n\t\t\taction: run.mode === 'build' ? 'build' : 'reuse',\n\t\t\tid: digest ?? app.ref,\n\t\t});\n\t}\n}\n\n// ============================================================================\n// release\n// ============================================================================\n\n/**\n * The whole stack up — anything it no longer defines removed — and each\n * app's image recorded in the stage's state.\n */\nexport async function releaseCompose(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tdeps: ComposeDeps,\n): Promise<void> {\n\tconst { stack, ref } = run;\n\n\tctx.logger.info('\\n🚀 Starting the stack…');\n\tawait deps.docker.up(ref);\n\n\tif (stack.local) {\n\t\t// Caddy's CA is generated on its first start. Copied out so a process —\n\t\t// `verify` among them — can trust it without installing anything.\n\t\tawait deps.docker\n\t\t\t.copyOut(\n\t\t\t\tref,\n\t\t\t\t'caddy',\n\t\t\t\t'/data/caddy/pki/authorities/local/root.crt',\n\t\t\t\tcaFile(run),\n\t\t\t)\n\t\t\t.catch(() => {});\n\t}\n\n\tawait recordImages(ctx, run);\n\n\tfor (const app of stack.apps) {\n\t\tconst image = run.images[app.name];\n\t\tapplied(ctx, run, {\n\t\t\tkey: `service:${app.name}`,\n\t\t\tresourceType: 'service',\n\t\t\taction: 'ensure',\n\t\t\tid: `${stack.project}/${app.name}`,\n\t\t\tvia: run.previous[app.name] ? 'recorded' : 'created',\n\t\t});\n\t\tctx.emit({\n\t\t\ttype: 'app.deployed',\n\t\t\tapp: app.name,\n\t\t\tapplicationId: `${stack.project}/${app.name}`,\n\t\t\timageRef: image?.ref ?? app.ref,\n\t\t\turl: app.url,\n\t\t});\n\t}\n\n\tctx.logger.info(`\\n✅ ${stack.project} is running:`);\n\tfor (const app of stack.apps) {\n\t\tctx.logger.info(` ${app.name.padEnd(12)} ${app.url}`);\n\t}\n\tif (stack.local) {\n\t\tctx.logger.info(\n\t\t\t`\\n🔐 Certificates are from Caddy's local CA: NODE_EXTRA_CA_CERTS=${join(stackDir(ctx.stage), 'caddy-root.crt')}`,\n\t\t);\n\t}\n}\n\n/**\n * Each app's image in the stage's state — the same `images` a Dokploy deploy\n * records: the ref it runs, the tag it was released under, and the digest\n * the tag resolved to.\n */\nasync function recordImages(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n): Promise<void> {\n\tconst journal = await DeployJournal.open(ctx.state, ctx.stage, () =>\n\t\tcreateEmptyState(ctx.stage, '', ''),\n\t);\n\tfor (const app of run.stack.apps) {\n\t\tconst image = run.images[app.name] ?? { ref: app.ref, tag: app.tag };\n\t\tsetDeployedImage(journal.state, app.name, image);\n\t}\n\tjournal.state.identity = ctx.identity.key;\n\tawait journal.save();\n}\n\n// ============================================================================\n// verify\n// ============================================================================\n\n/**\n * Each app asked through Caddy, over HTTPS, the certificate verified: an API\n * at `/health`, a site at `/`. On the local stage the edge is this machine and\n * its certificates are Caddy's internal CA's, so the CA `release` copied out\n * is the one trusted and the request goes to 127.0.0.1.\n */\nexport async function verifyCompose(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tdeps: ComposeDeps,\n): Promise<void> {\n\tconst { stack } = run;\n\tconst ca = stack.local\n\t\t? await readFile(caFile(run), 'utf-8').catch(() => undefined)\n\t\t: undefined;\n\n\tctx.logger.info('\\n🩺 Checking each app through Caddy…');\n\tconst results = await Promise.all(\n\t\tstack.apps.map((app) =>\n\t\t\tcheckApp(ctx, app, deps, { ca, local: stack.local }),\n\t\t),\n\t);\n\n\tconst down = results\n\t\t.filter((result) => !result.healthy)\n\t\t.map(({ app, url, last }) => ({ app, url, last }));\n\tif (down.length > 0) throw new ComposeAppsUnhealthy(stack.project, down);\n}\n\nasync function checkApp(\n\tctx: ComposeContext,\n\tapp: StackApp,\n\tdeps: ComposeDeps,\n\toptions: { ca: string | undefined; local: boolean },\n): Promise<{ app: string; url: string; last: string; healthy: boolean }> {\n\tconst url = `${app.url}${app.kind === 'site' ? '/' : '/health'}`;\n\tlet last = 'not asked';\n\n\tfor (let attempt = 1; attempt <= deps.healthAttempts; attempt++) {\n\t\tctx.signal.throwIfAborted();\n\t\tlet status: number | undefined;\n\t\ttry {\n\t\t\tstatus = await deps.probe({\n\t\t\t\turl,\n\t\t\t\t...(options.ca ? { ca: options.ca } : {}),\n\t\t\t\t...(options.local ? { connectTo: '127.0.0.1' } : {}),\n\t\t\t\ttimeoutMs: 10_000,\n\t\t\t\tsignal: ctx.signal,\n\t\t\t});\n\t\t\tlast = `HTTP ${status}`;\n\t\t} catch (error) {\n\t\t\tlast = error instanceof Error ? error.message : String(error);\n\t\t}\n\n\t\tconst healthy = status !== undefined && isHealthy(status);\n\t\tctx.emit({\n\t\t\ttype: 'health.checked',\n\t\t\tapp: app.name,\n\t\t\turl,\n\t\t\thealthy,\n\t\t\t...(status !== undefined ? { status } : {}),\n\t\t\tattempt,\n\t\t});\n\t\tif (healthy) {\n\t\t\tctx.logger.info(` ✓ ${app.name.padEnd(12)} ${url} (${last})`);\n\t\t\treturn { app: app.name, url, last, healthy };\n\t\t}\n\t\tif (attempt < deps.healthAttempts) {\n\t\t\tawait new Promise((resolve) =>\n\t\t\t\tsetTimeout(resolve, deps.healthIntervalMs),\n\t\t\t);\n\t\t}\n\t}\n\n\tctx.logger.warn(` ✗ ${app.name.padEnd(12)} ${url} (${last})`);\n\treturn { app: app.name, url, last, healthy: false };\n}\n\n// ============================================================================\n// result\n// ============================================================================\n\nexport function composeResult(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n): DeployResult {\n\tconst apps = run.stack.apps.map((app) => {\n\t\tconst image = run.images[app.name];\n\t\treturn {\n\t\t\tappName: app.name,\n\t\t\ttype: app.kind === 'site' ? ('web' as const) : ('backend' as const),\n\t\t\tsuccess: !ctx.dryRun,\n\t\t\tapplicationId: `${run.stack.project}/${app.name}`,\n\t\t\timageRef: image?.ref ?? app.ref,\n\t\t\t...(image?.digest ? { digest: image.digest } : {}),\n\t\t\turl: app.url,\n\t\t};\n\t});\n\treturn {\n\t\tapps,\n\t\tprojectId: run.stack.project,\n\t\tsuccessCount: ctx.dryRun ? 0 : apps.length,\n\t\tfailedCount: 0,\n\t\tstage: ctx.stage,\n\t\tidentity: ctx.identity.key,\n\t\ttag: ctx.tag,\n\t\tdryRun: ctx.dryRun,\n\t\tenvironmentId: '',\n\t\tskipped: [...ctx.skipped],\n\t\turls: Object.fromEntries(run.stack.apps.map((app) => [app.name, app.url])),\n\t\tchanges: run.changes,\n\t};\n}\n\n// ============================================================================\n// Files\n// ============================================================================\n\nfunction caFile(run: ComposeRun): string {\n\treturn join(run.dir, 'caddy-root.crt');\n}\n\nfunction applied(\n\tctx: ComposeContext,\n\trun: ComposeRun,\n\tchange: ResourceChange & {\n\t\tid: string;\n\t\tvia: 'recorded' | 'resumed' | 'found' | 'created';\n\t},\n): void {\n\tconst { via, ...rest } = change;\n\trun.changes.push(rest);\n\tctx.emit({ type: 'resource.applied', ...rest, via });\n}\n\n/** Write the stack's files: owner-only, since the env files hold secrets. */\nasync function writeStack(\n\troot: string,\n\tdir: string,\n\tstack: ComposeStack,\n): Promise<string[]> {\n\tawait mkdir(dir, { recursive: true, mode: 0o700 });\n\tawait chmod(dir, 0o700);\n\n\tconst files: string[] = [];\n\tconst write = async (path: string, content: string, mode = 0o644) => {\n\t\tawait mkdir(dirname(path), { recursive: true });\n\t\tawait writeFile(path, content, { mode });\n\t\tawait chmod(path, mode);\n\t\tfiles.push(path);\n\t};\n\n\tawait write(join(dir, 'docker-compose.yml'), composeYaml(stack));\n\tawait write(join(dir, 'Caddyfile'), stack.caddyfile);\n\tfor (const app of stack.apps) {\n\t\tif (app.env)\n\t\t\tawait write(join(dir, `${app.name}.env`), envFile(app.env), 0o600);\n\t}\n\tfor (const [path, content] of Object.entries(stack.dockerfiles)) {\n\t\tawait write(join(root, path), content);\n\t}\n\n\t// The build context is the workspace, and the env files are in it: the\n\t// ignore file is what keeps a stage's secrets out of every image's context.\n\tawait ignoreStacks(root);\n\n\treturn files;\n}\n\n/** Make sure the build context leaves `.gkm/compose` out. */\nasync function ignoreStacks(root: string): Promise<void> {\n\tconst path = join(root, '.dockerignore');\n\tif (!existsSync(path)) {\n\t\tawait writeFile(path, generateDockerignore());\n\t\treturn;\n\t}\n\tconst current = await readFile(path, 'utf-8');\n\tif (/^\\/?\\.gkm\\/compose\\/?$|^\\/?\\.gkm\\/?$/m.test(current)) return;\n\tawait appendFile(\n\t\tpath,\n\t\t`${current.endsWith('\\n') ? '' : '\\n'}\\n# gkm compose's stacks: each app's env file holds its stage's secrets\\n.gkm/compose\\n`,\n\t);\n}\n\nfunction composeYaml(stack: ComposeStack): string {\n\tconst stage = stack.local ? '' : ` --stage ${stack.stage}`;\n\treturn `# Generated by gkm compose from the construct manifest — do not edit.\n# The ${stack.stage} stage's APIs and sites behind one Caddy. Each backend\n# reads exactly the keys in its own env file beside this one.\n#\n# gkm compose${stage} start or update it\n# gkm compose${stage} --down stop it\n${stringify(stack.compose, { lineWidth: 0, aliasDuplicateObjects: false })}`;\n}\n\nfunction printPlan(ctx: ComposeContext, run: ComposeRun): void {\n\tconst { stack, mode, files } = run;\n\tctx.logger.info(`\\n🧱 ${stack.project} — stage ${stack.stage}`);\n\tfor (const app of stack.apps) {\n\t\tctx.logger.info(\n\t\t\t` ${app.name.padEnd(12)} ${app.url.padEnd(40)} ${mode} ${app.ref}`,\n\t\t);\n\t}\n\tif (stack.infra.length > 0) {\n\t\tctx.logger.info(` infrastructure: ${stack.infra.join(', ')}`);\n\t}\n\tctx.logger.info(\n\t\t`\\n📝 Wrote ${files.length} file(s) under ${stackDir(stack.stage)}/`,\n\t);\n}\n","/**\n * The built-in `compose` target: a stage as one Docker Compose stack behind\n * Caddy, on the machine that runs the deploy.\n *\n * ```bash\n * gkm deploy --target compose --stage production --tag v1.4.0 # what CI pushed\n * gkm deploy --target compose --stage production # built from here\n * gkm deploy --target compose --stage development # the local stage\n * ```\n *\n * - `validate`: the stack (`composeStack`, pure) and, for a tag, every image\n * looked up in the registry — `ImageTagNotFound` before anything changes\n * - `plan`: the stack's files and what a run would create or reuse\n * - `provision`: generated secrets kept, files written, infrastructure up,\n * databases, roles, grants and migrations\n * - `build`: each backend bundled on the host and every image built — or, for\n * a tag, pulled\n * - `release`: `up --wait --remove-orphans`, and each app's image, tag and\n * digest in the stage's state\n * - `verify`: each app asked through Caddy over HTTPS\n *\n * `gkm compose` is this target with a few more switches (`--build`, `--pull`,\n * `--down`), run through the same `deploy()`.\n */\n\nimport { defineTarget } from '../define';\nimport type { DeployTarget } from '../types';\nimport {\n\tbuildCompose,\n\ttype ComposeDeps,\n\ttype ComposeRun,\n\tcomposeResult,\n\tdefaultDeps,\n\tplanCompose,\n\tprovisionCompose,\n\treleaseCompose,\n\tvalidateCompose,\n\tverifyCompose,\n} from './phases';\n\nexport {\n\tComposeAppsUnhealthy,\n\ttype HealthProbe,\n\ttype HealthRequest,\n\tHealthRequestTimedOut,\n} from './health';\nexport {\n\tBundleFailed,\n\tCliEntryNotFound,\n\ttype ComposeDeps,\n\ttype ComposeImage,\n\ttype ComposeRun,\n\tEdgePortInvalid,\n\tedgePorts,\n\tgitRevision,\n\tNoGitRevision,\n} from './phases';\n\nexport interface ComposeTargetOptions extends Partial<ComposeDeps> {\n\t/**\n\t * Build or pull whatever the tag says. By default a given tag is pulled\n\t * and no tag builds from the checkout.\n\t */\n\tmode?: 'build' | 'pull';\n\t/** Handed the finished run — `gkm compose` prints and returns from it. */\n\treport?: (run: ComposeRun) => void;\n}\n\n/** The compose target, with its Docker, bundler and probe as given. */\nexport function composeTarget(\n\toptions: ComposeTargetOptions = {},\n): DeployTarget<undefined, ComposeRun> {\n\tconst { mode, report, ...given } = options;\n\tconst deps: ComposeDeps = { ...defaultDeps, ...given };\n\n\treturn defineTarget<undefined, ComposeRun>({\n\t\tname: 'compose',\n\t\truntime: 'server',\n\t\tcapabilities: {\n\t\t\trollback: false,\n\t\t\tmigrations: 'target',\n\t\t\timages: true,\n\t\t\t// The stack runs where the deploy does, so the local stage is one\n\t\t\t// it can run — the `gkm dev` hostnames, behind Caddy's own CA.\n\t\t\tlocalStage: true,\n\t\t},\n\t\t// Images are pulled with this machine's own `docker login`.\n\t\tcredentials: [],\n\t\t// Built from the checkout, an image is named after its commit.\n\t\ttag: ({ cwd }) => deps.revision(cwd),\n\t\tvalidate: (ctx) => validateCompose(ctx, deps, mode),\n\t\tplan: (ctx, run) => planCompose(ctx, run),\n\t\tprovision: (ctx, run) => provisionCompose(ctx, run, deps),\n\t\tbuild: (ctx, run) => buildCompose(ctx, run, deps),\n\t\trelease: (ctx, run) => releaseCompose(ctx, run, deps),\n\t\tverify: (ctx, run) => verifyCompose(ctx, run, deps),\n\t\tresult: (ctx, run) => {\n\t\t\treport?.(run);\n\t\t\treturn composeResult(ctx, run);\n\t\t},\n\t});\n}\n"],"mappings":"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"}