@dragonmastery/tamer 0.31.1 → 0.31.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{apply-BjrYbyHn.mjs → apply-C_70Hgcf.mjs} +7 -7
  2. package/dist/{apply-BjrYbyHn.mjs.map → apply-C_70Hgcf.mjs.map} +1 -1
  3. package/dist/{bootstrap-D__dHw1w.mjs → bootstrap-CQS5s33A.mjs} +2 -2
  4. package/dist/{bootstrap-D__dHw1w.mjs.map → bootstrap-CQS5s33A.mjs.map} +1 -1
  5. package/dist/{cloudflareSnapshot-C6cF8GG8.mjs → cloudflareSnapshot-CFErW72O.mjs} +3 -3
  6. package/dist/{cloudflareSnapshot-C6cF8GG8.mjs.map → cloudflareSnapshot-CFErW72O.mjs.map} +1 -1
  7. package/dist/{deploy-C6fX9td0.mjs → deploy-D-GXzsWR.mjs} +4 -4
  8. package/dist/{deploy-C6fX9td0.mjs.map → deploy-D-GXzsWR.mjs.map} +1 -1
  9. package/dist/{destroy-vfk2Zbfj.mjs → destroy-DJRw_qLX.mjs} +7 -7
  10. package/dist/{destroy-vfk2Zbfj.mjs.map → destroy-DJRw_qLX.mjs.map} +1 -1
  11. package/dist/{destroy-tenant-T_94ed9x.mjs → destroy-tenant-DFHfNImL.mjs} +2 -2
  12. package/dist/{destroy-tenant-T_94ed9x.mjs.map → destroy-tenant-DFHfNImL.mjs.map} +1 -1
  13. package/dist/{dev-BLthyLml.mjs → dev-caJxohHI.mjs} +4 -4
  14. package/dist/{dev-BLthyLml.mjs.map → dev-caJxohHI.mjs.map} +1 -1
  15. package/dist/{dns-records.sync-DqYROe07.mjs → dns-records.sync-Ck0Q2OK3.mjs} +2 -2
  16. package/dist/{dns-records.sync-DqYROe07.mjs.map → dns-records.sync-Ck0Q2OK3.mjs.map} +1 -1
  17. package/dist/{drift-BCxWdYHG.mjs → drift-5_LwAdZo.mjs} +3 -3
  18. package/dist/{drift-CeemyFqL.mjs → drift-C-qnJ-mH.mjs} +4 -4
  19. package/dist/{drift-CeemyFqL.mjs.map → drift-C-qnJ-mH.mjs.map} +1 -1
  20. package/dist/{events-otk0l3aJ.mjs → events-Bor7XgLC.mjs} +2 -2
  21. package/dist/{events-otk0l3aJ.mjs.map → events-Bor7XgLC.mjs.map} +1 -1
  22. package/dist/{import-OvohE-H2.mjs → import-Vn9lhWic.mjs} +2 -2
  23. package/dist/{import-OvohE-H2.mjs.map → import-Vn9lhWic.mjs.map} +1 -1
  24. package/dist/{migrate-CroDjbJz.mjs → migrate-skvsDG6d.mjs} +2 -2
  25. package/dist/{migrate-CroDjbJz.mjs.map → migrate-skvsDG6d.mjs.map} +1 -1
  26. package/dist/{plan-C2urqJOz.mjs → plan-BLy8FaE2.mjs} +6 -6
  27. package/dist/{plan-C2urqJOz.mjs.map → plan-BLy8FaE2.mjs.map} +1 -1
  28. package/dist/{provision-tenant-BJ1KugON.mjs → provision-tenant-CleOYFwr.mjs} +2 -2
  29. package/dist/{provision-tenant-BJ1KugON.mjs.map → provision-tenant-CleOYFwr.mjs.map} +1 -1
  30. package/dist/{stackOutputs-Cltzl2g0.mjs → stackOutputs-BLvUMsQO.mjs} +2 -2
  31. package/dist/{stackOutputs-Cltzl2g0.mjs.map → stackOutputs-BLvUMsQO.mjs.map} +1 -1
  32. package/dist/{status-DkkS5lc9.mjs → status-BxStsax8.mjs} +3 -3
  33. package/dist/{status-DkkS5lc9.mjs.map → status-BxStsax8.mjs.map} +1 -1
  34. package/dist/{sync-CpfxqlOx.mjs → sync-KTzMVc_o.mjs} +4 -4
  35. package/dist/{sync-CpfxqlOx.mjs.map → sync-KTzMVc_o.mjs.map} +1 -1
  36. package/dist/tamer.mjs +319 -245
  37. package/dist/tamer.mjs.map +1 -1
  38. package/dist/{types-BzzHwIdw.mjs → types-D7qKnGsm.mjs} +2 -2
  39. package/dist/{types-BzzHwIdw.mjs.map → types-D7qKnGsm.mjs.map} +1 -1
  40. package/dist/{verifyPlanFile-BmEadIqm.mjs → verifyPlanFile-CR2bELdE.mjs} +2 -2
  41. package/dist/{verifyPlanFile-BmEadIqm.mjs.map → verifyPlanFile-CR2bELdE.mjs.map} +1 -1
  42. package/dist/{worker-route-x8q3K4-z.mjs → worker-route-tOqVbhv3.mjs} +2 -2
  43. package/dist/{worker-route-x8q3K4-z.mjs.map → worker-route-tOqVbhv3.mjs.map} +1 -1
  44. package/dist/{workers-D3Ekf3mF.mjs → workers-6r2ONF9J.mjs} +2 -2
  45. package/dist/{workers-D3Ekf3mF.mjs.map → workers-6r2ONF9J.mjs.map} +1 -1
  46. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
- import { B as getWorkers, C as stackNameForConfig, L as CFApiClient, O as resolveWorkerConfig, P as namingFromConfig, R as cloudflareAccountIdFromEnv, V as loadConfig, d as fetchStackImports, j as wranglerConfigCliArgs, m as StateManager } from "./tamer.mjs";
1
+ import { B as getWorkers, L as CFApiClient, M as wranglerConfigCliArgs, R as cloudflareAccountIdFromEnv, V as loadConfig, f as fetchStackImports, h as StateManager, k as resolveWorkerConfig, u as namingFromConfig, w as stackNameForConfig } from "./tamer.mjs";
2
2
  import "./registry-EWWdkLf7.mjs";
3
3
  import "./r2S3EmptyBucket-B9_pHfvB.mjs";
4
4
  import { n as writeWranglerJson, t as generateWranglerConfig } from "./generator-gvCy7ouY.mjs";
5
5
  import "./logpush-job-DJPlpnRu.mjs";
6
- import "./worker-route-x8q3K4-z.mjs";
7
- import { runSync } from "./sync-CpfxqlOx.mjs";
6
+ import "./worker-route-tOqVbhv3.mjs";
7
+ import { runSync } from "./sync-KTzMVc_o.mjs";
8
8
  import { spawn } from "child_process";
9
9
 
10
10
  //#region src/cli/commands/dev.ts
@@ -98,4 +98,4 @@ async function runDev(options) {
98
98
 
99
99
  //#endregion
100
100
  export { runDev };
101
- //# sourceMappingURL=dev-BLthyLml.mjs.map
101
+ //# sourceMappingURL=dev-caJxohHI.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev-BLthyLml.mjs","names":["workerKey","workerConfig","resolved","children: ChildProcess[]"],"sources":["../src/cli/commands/dev.ts"],"sourcesContent":["import type { ChildProcess } from \"child_process\";\nimport { spawn } from \"child_process\";\nimport { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { runSync } from \"./sync.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\n\nexport async function runDev(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n /** Run every selected worker as a separate `wrangler dev` on incrementing ports (from TAMER_DEV_BASE_PORT or 8787). */\n all?: boolean;\n}): Promise<void> {\n const workerFilter = options.worker;\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const naming = namingFromConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n\n if (\n env !== \"local\" &&\n Object.keys(state.load().resources).length === 0\n ) {\n console.log(\"Tamer state is empty; running sync...\");\n await runSync({ env, configPath });\n state.reset();\n await state.hydrate(api);\n }\n\n // Pre-fetch sibling stack outputs so worker `vars` / `tamerRoutes`\n // can reference `${tamer:import:<stack>.<output>}` even in dev mode.\n // No-op in local env (returns `{}`); when missing in non-local, the\n // import resolver will throw with a clear \"run apply on <stack>\" hint.\n const imports = await fetchStackImports(api, config, env);\n\n const workers = await getWorkers(config, baseDir);\n const toRun = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toRun.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n for (const [workerKey, workerConfig] of toRun) {\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const wranglerConfig = generateWranglerConfig(resolved, state, naming);\n writeWranglerJson(resolved.workerDir, wranglerConfig, resolved.wranglerOutFile);\n }\n\n if (options.all && toRun.length > 0) {\n const basePort = Number(process.env.TAMER_DEV_BASE_PORT) || 8787;\n const children: ChildProcess[] = [];\n\n for (let i = 0; i < toRun.length; i++) {\n const [workerKey, workerConfig] = toRun[i];\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const port = basePort + i;\n const devArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"dev\",\n \"--port\",\n String(port),\n ];\n console.log(`Starting ${workerKey} on http://127.0.0.1:${port}`);\n const proc = spawn(\"bunx\", devArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n shell: true,\n });\n children.push(proc);\n }\n\n const shutdown = () => {\n for (const c of children) {\n if (!c.killed) c.kill(\"SIGTERM\");\n }\n };\n process.once(\"SIGINT\", () => {\n shutdown();\n process.exit(0);\n });\n process.once(\"SIGTERM\", () => {\n shutdown();\n process.exit(0);\n });\n\n await new Promise<void>((resolve) => {\n let remaining = children.length;\n for (const c of children) {\n c.on(\"exit\", () => {\n remaining -= 1;\n if (remaining <= 0) resolve();\n });\n }\n });\n return;\n }\n\n const [workerKey, workerConfig] = toRun[0];\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n\n console.log(`Starting wrangler dev for ${workerKey}...`);\n const devArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"dev\",\n ];\n const proc = spawn(\"bunx\", devArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n shell: true,\n });\n\n proc.on(\"exit\", (code) => {\n process.exit(code ?? 0);\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dev-caJxohHI.mjs","names":["workerKey","workerConfig","resolved","children: ChildProcess[]"],"sources":["../src/cli/commands/dev.ts"],"sourcesContent":["import type { ChildProcess } from \"child_process\";\nimport { spawn } from \"child_process\";\nimport { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { runSync } from \"./sync.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\n\nexport async function runDev(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n /** Run every selected worker as a separate `wrangler dev` on incrementing ports (from TAMER_DEV_BASE_PORT or 8787). */\n all?: boolean;\n}): Promise<void> {\n const workerFilter = options.worker;\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const naming = namingFromConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n\n if (\n env !== \"local\" &&\n Object.keys(state.load().resources).length === 0\n ) {\n console.log(\"Tamer state is empty; running sync...\");\n await runSync({ env, configPath });\n state.reset();\n await state.hydrate(api);\n }\n\n // Pre-fetch sibling stack outputs so worker `vars` / `tamerRoutes`\n // can reference `${tamer:import:<stack>.<output>}` even in dev mode.\n // No-op in local env (returns `{}`); when missing in non-local, the\n // import resolver will throw with a clear \"run apply on <stack>\" hint.\n const imports = await fetchStackImports(api, config, env);\n\n const workers = await getWorkers(config, baseDir);\n const toRun = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toRun.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n for (const [workerKey, workerConfig] of toRun) {\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const wranglerConfig = generateWranglerConfig(resolved, state, naming);\n writeWranglerJson(resolved.workerDir, wranglerConfig, resolved.wranglerOutFile);\n }\n\n if (options.all && toRun.length > 0) {\n const basePort = Number(process.env.TAMER_DEV_BASE_PORT) || 8787;\n const children: ChildProcess[] = [];\n\n for (let i = 0; i < toRun.length; i++) {\n const [workerKey, workerConfig] = toRun[i];\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const port = basePort + i;\n const devArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"dev\",\n \"--port\",\n String(port),\n ];\n console.log(`Starting ${workerKey} on http://127.0.0.1:${port}`);\n const proc = spawn(\"bunx\", devArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n shell: true,\n });\n children.push(proc);\n }\n\n const shutdown = () => {\n for (const c of children) {\n if (!c.killed) c.kill(\"SIGTERM\");\n }\n };\n process.once(\"SIGINT\", () => {\n shutdown();\n process.exit(0);\n });\n process.once(\"SIGTERM\", () => {\n shutdown();\n process.exit(0);\n });\n\n await new Promise<void>((resolve) => {\n let remaining = children.length;\n for (const c of children) {\n c.on(\"exit\", () => {\n remaining -= 1;\n if (remaining <= 0) resolve();\n });\n }\n });\n return;\n }\n\n const [workerKey, workerConfig] = toRun[0];\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n\n console.log(`Starting wrangler dev for ${workerKey}...`);\n const devArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"dev\",\n ];\n const proc = spawn(\"bunx\", devArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n shell: true,\n });\n\n proc.on(\"exit\", (code) => {\n process.exit(code ?? 0);\n });\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { M as effectiveDispatchNamespaceName } from "./tamer.mjs";
1
+ import { N as effectiveDispatchNamespaceName } from "./tamer.mjs";
2
2
  import { n as dnsRecordCommentMarker, r as dnsRecordStateKey, t as dnsRecordAppliesToEnv } from "./dns-records.resolve-BB2agPAb.mjs";
3
3
 
4
4
  //#region src/features/dispatch-namespace/dispatch-namespace.sync.ts
@@ -72,4 +72,4 @@ async function dnsRecordSync(resources, tenant, env, api, state) {
72
72
 
73
73
  //#endregion
74
74
  export { dispatchNamespaceSync as n, dnsRecordSync as t };
75
- //# sourceMappingURL=dns-records.sync-DqYROe07.mjs.map
75
+ //# sourceMappingURL=dns-records.sync-Ck0Q2OK3.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dns-records.sync-DqYROe07.mjs","names":["entry: DnsRecordStateEntry"],"sources":["../src/features/dispatch-namespace/dispatch-namespace.sync.ts","../src/features/dns-records/dns-records.sync.ts"],"sourcesContent":["import type { TenantMeta, DispatchNamespaceResourceConfig } from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { effectiveDispatchNamespaceName } from \"./dispatch-namespace.resolve.js\";\n\nexport async function dispatchNamespaceSync(\n resources: DispatchNamespaceResourceConfig[],\n tenant: TenantMeta,\n env: string,\n api: CFApiClient,\n state: StateManager,\n): Promise<void> {\n if (resources.length === 0) return;\n if (env === \"local\") return;\n\n const list = await api.dispatchNamespaceListAll();\n const names = new Set(list.map((n) => n.namespace_name));\n\n for (const config of resources) {\n const resolved = effectiveDispatchNamespaceName(config, env, tenant);\n const key = `dispatch_ns:${resolved}`;\n if (!names.has(resolved)) continue;\n\n state.set(key, {\n type: \"dispatch_namespace\",\n logicalName: config.logicalName,\n derivedName: resolved,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n });\n }\n}\n","import type {\n DnsRecordResourceConfig,\n DnsRecordStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport {\n dnsRecordAppliesToEnv,\n dnsRecordCommentMarker,\n dnsRecordStateKey,\n} from \"./dns-records.resolve.js\";\n\n/**\n * Re-adopt every Tamer-attributed DNS record found on the live zones into\n * state. Mirrors the dispatch-namespace sync pattern: Tamer never\n * **destroys** records here, just imports rows that match its\n * attribution comment so a `apply` straight after `sync` is a no-op when\n * Cloudflare and config agree.\n *\n * Records on Cloudflare without Tamer's marker comment are ignored even\n * if they happen to match the declared `(zone, type, name)` — they are\n * presumed to be hand-managed and surface in `tamer drift` as\n * `unrecordedInState` so the operator can decide.\n */\nexport async function dnsRecordSync(\n resources: DnsRecordResourceConfig[],\n tenant: TenantMeta,\n env: string,\n api: CFApiClient,\n state: StateManager,\n): Promise<void> {\n if (resources.length === 0) return;\n const applicable = resources.filter((r) => dnsRecordAppliesToEnv(r, env));\n if (applicable.length === 0) return;\n\n const zoneCache = new Map<\n string,\n Awaited<ReturnType<CFApiClient[\"zoneDnsRecordListAll\"]>>\n >();\n\n for (const config of applicable) {\n let live = zoneCache.get(config.zoneId);\n if (!live) {\n live = await api.zoneDnsRecordListAll(config.zoneId);\n zoneCache.set(config.zoneId, live);\n }\n const marker = dnsRecordCommentMarker(tenant, env, config.logicalName);\n const adopted = live.find(\n (r) =>\n r.type === config.type &&\n typeof r.comment === \"string\" &&\n r.comment.startsWith(marker),\n );\n if (!adopted) continue;\n const stateKey = dnsRecordStateKey(config.zoneId, config.type, config.name);\n const ts = new Date().toISOString();\n const entry: DnsRecordStateEntry = {\n type: \"dns_record\",\n logicalName: config.logicalName,\n zoneId: config.zoneId,\n recordType: config.type,\n name: adopted.name,\n content: adopted.content,\n ttl: adopted.ttl ?? 1,\n proxied: adopted.proxied ?? false,\n priority: adopted.priority,\n comment: adopted.comment ?? marker,\n recordId: adopted.id,\n createdAt: state.get(stateKey)?.type === \"dns_record\"\n ? (state.get(stateKey) as DnsRecordStateEntry).createdAt\n : ts,\n updatedAt: ts,\n };\n state.set(stateKey, entry);\n }\n}\n"],"mappings":";;;;AAKA,eAAsB,sBACpB,WACA,QACA,KACA,KACA,OACe;AACf,KAAI,UAAU,WAAW,EAAG;AAC5B,KAAI,QAAQ,QAAS;CAErB,MAAM,OAAO,MAAM,IAAI,0BAA0B;CACjD,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK,MAAM,EAAE,eAAe,CAAC;AAExD,MAAK,MAAM,UAAU,WAAW;EAC9B,MAAM,WAAW,+BAA+B,QAAQ,KAAK,OAAO;EACpE,MAAM,MAAM,eAAe;AAC3B,MAAI,CAAC,MAAM,IAAI,SAAS,CAAE;AAE1B,QAAM,IAAI,KAAK;GACb,MAAM;GACN,aAAa,OAAO;GACpB,aAAa;GACb,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC,CAAC;;;;;;;;;;;;;;;;;;ACJN,eAAsB,cACpB,WACA,QACA,KACA,KACA,OACe;AACf,KAAI,UAAU,WAAW,EAAG;CAC5B,MAAM,aAAa,UAAU,QAAQ,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACzE,KAAI,WAAW,WAAW,EAAG;CAE7B,MAAM,4BAAY,IAAI,KAGnB;AAEH,MAAK,MAAM,UAAU,YAAY;EAC/B,IAAI,OAAO,UAAU,IAAI,OAAO,OAAO;AACvC,MAAI,CAAC,MAAM;AACT,UAAO,MAAM,IAAI,qBAAqB,OAAO,OAAO;AACpD,aAAU,IAAI,OAAO,QAAQ,KAAK;;EAEpC,MAAM,SAAS,uBAAuB,QAAQ,KAAK,OAAO,YAAY;EACtE,MAAM,UAAU,KAAK,MAClB,MACC,EAAE,SAAS,OAAO,QAClB,OAAO,EAAE,YAAY,YACrB,EAAE,QAAQ,WAAW,OAAO,CAC/B;AACD,MAAI,CAAC,QAAS;EACd,MAAM,WAAW,kBAAkB,OAAO,QAAQ,OAAO,MAAM,OAAO,KAAK;EAC3E,MAAM,sBAAK,IAAI,MAAM,EAAC,aAAa;EACnC,MAAMA,QAA6B;GACjC,MAAM;GACN,aAAa,OAAO;GACpB,QAAQ,OAAO;GACf,YAAY,OAAO;GACnB,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB,KAAK,QAAQ,OAAO;GACpB,SAAS,QAAQ,WAAW;GAC5B,UAAU,QAAQ;GAClB,SAAS,QAAQ,WAAW;GAC5B,UAAU,QAAQ;GAClB,WAAW,MAAM,IAAI,SAAS,EAAE,SAAS,eACpC,MAAM,IAAI,SAAS,CAAyB,YAC7C;GACJ,WAAW;GACZ;AACD,QAAM,IAAI,UAAU,MAAM"}
1
+ {"version":3,"file":"dns-records.sync-Ck0Q2OK3.mjs","names":["entry: DnsRecordStateEntry"],"sources":["../src/features/dispatch-namespace/dispatch-namespace.sync.ts","../src/features/dns-records/dns-records.sync.ts"],"sourcesContent":["import type { TenantMeta, DispatchNamespaceResourceConfig } from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { effectiveDispatchNamespaceName } from \"./dispatch-namespace.resolve.js\";\n\nexport async function dispatchNamespaceSync(\n resources: DispatchNamespaceResourceConfig[],\n tenant: TenantMeta,\n env: string,\n api: CFApiClient,\n state: StateManager,\n): Promise<void> {\n if (resources.length === 0) return;\n if (env === \"local\") return;\n\n const list = await api.dispatchNamespaceListAll();\n const names = new Set(list.map((n) => n.namespace_name));\n\n for (const config of resources) {\n const resolved = effectiveDispatchNamespaceName(config, env, tenant);\n const key = `dispatch_ns:${resolved}`;\n if (!names.has(resolved)) continue;\n\n state.set(key, {\n type: \"dispatch_namespace\",\n logicalName: config.logicalName,\n derivedName: resolved,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n });\n }\n}\n","import type {\n DnsRecordResourceConfig,\n DnsRecordStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport {\n dnsRecordAppliesToEnv,\n dnsRecordCommentMarker,\n dnsRecordStateKey,\n} from \"./dns-records.resolve.js\";\n\n/**\n * Re-adopt every Tamer-attributed DNS record found on the live zones into\n * state. Mirrors the dispatch-namespace sync pattern: Tamer never\n * **destroys** records here, just imports rows that match its\n * attribution comment so a `apply` straight after `sync` is a no-op when\n * Cloudflare and config agree.\n *\n * Records on Cloudflare without Tamer's marker comment are ignored even\n * if they happen to match the declared `(zone, type, name)` — they are\n * presumed to be hand-managed and surface in `tamer drift` as\n * `unrecordedInState` so the operator can decide.\n */\nexport async function dnsRecordSync(\n resources: DnsRecordResourceConfig[],\n tenant: TenantMeta,\n env: string,\n api: CFApiClient,\n state: StateManager,\n): Promise<void> {\n if (resources.length === 0) return;\n const applicable = resources.filter((r) => dnsRecordAppliesToEnv(r, env));\n if (applicable.length === 0) return;\n\n const zoneCache = new Map<\n string,\n Awaited<ReturnType<CFApiClient[\"zoneDnsRecordListAll\"]>>\n >();\n\n for (const config of applicable) {\n let live = zoneCache.get(config.zoneId);\n if (!live) {\n live = await api.zoneDnsRecordListAll(config.zoneId);\n zoneCache.set(config.zoneId, live);\n }\n const marker = dnsRecordCommentMarker(tenant, env, config.logicalName);\n const adopted = live.find(\n (r) =>\n r.type === config.type &&\n typeof r.comment === \"string\" &&\n r.comment.startsWith(marker),\n );\n if (!adopted) continue;\n const stateKey = dnsRecordStateKey(config.zoneId, config.type, config.name);\n const ts = new Date().toISOString();\n const entry: DnsRecordStateEntry = {\n type: \"dns_record\",\n logicalName: config.logicalName,\n zoneId: config.zoneId,\n recordType: config.type,\n name: adopted.name,\n content: adopted.content,\n ttl: adopted.ttl ?? 1,\n proxied: adopted.proxied ?? false,\n priority: adopted.priority,\n comment: adopted.comment ?? marker,\n recordId: adopted.id,\n createdAt: state.get(stateKey)?.type === \"dns_record\"\n ? (state.get(stateKey) as DnsRecordStateEntry).createdAt\n : ts,\n updatedAt: ts,\n };\n state.set(stateKey, entry);\n }\n}\n"],"mappings":";;;;AAKA,eAAsB,sBACpB,WACA,QACA,KACA,KACA,OACe;AACf,KAAI,UAAU,WAAW,EAAG;AAC5B,KAAI,QAAQ,QAAS;CAErB,MAAM,OAAO,MAAM,IAAI,0BAA0B;CACjD,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK,MAAM,EAAE,eAAe,CAAC;AAExD,MAAK,MAAM,UAAU,WAAW;EAC9B,MAAM,WAAW,+BAA+B,QAAQ,KAAK,OAAO;EACpE,MAAM,MAAM,eAAe;AAC3B,MAAI,CAAC,MAAM,IAAI,SAAS,CAAE;AAE1B,QAAM,IAAI,KAAK;GACb,MAAM;GACN,aAAa,OAAO;GACpB,aAAa;GACb,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC,CAAC;;;;;;;;;;;;;;;;;;ACJN,eAAsB,cACpB,WACA,QACA,KACA,KACA,OACe;AACf,KAAI,UAAU,WAAW,EAAG;CAC5B,MAAM,aAAa,UAAU,QAAQ,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACzE,KAAI,WAAW,WAAW,EAAG;CAE7B,MAAM,4BAAY,IAAI,KAGnB;AAEH,MAAK,MAAM,UAAU,YAAY;EAC/B,IAAI,OAAO,UAAU,IAAI,OAAO,OAAO;AACvC,MAAI,CAAC,MAAM;AACT,UAAO,MAAM,IAAI,qBAAqB,OAAO,OAAO;AACpD,aAAU,IAAI,OAAO,QAAQ,KAAK;;EAEpC,MAAM,SAAS,uBAAuB,QAAQ,KAAK,OAAO,YAAY;EACtE,MAAM,UAAU,KAAK,MAClB,MACC,EAAE,SAAS,OAAO,QAClB,OAAO,EAAE,YAAY,YACrB,EAAE,QAAQ,WAAW,OAAO,CAC/B;AACD,MAAI,CAAC,QAAS;EACd,MAAM,WAAW,kBAAkB,OAAO,QAAQ,OAAO,MAAM,OAAO,KAAK;EAC3E,MAAM,sBAAK,IAAI,MAAM,EAAC,aAAa;EACnC,MAAMA,QAA6B;GACjC,MAAM;GACN,aAAa,OAAO;GACpB,QAAQ,OAAO;GACf,YAAY,OAAO;GACnB,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB,KAAK,QAAQ,OAAO;GACpB,SAAS,QAAQ,WAAW;GAC5B,UAAU,QAAQ;GAClB,SAAS,QAAQ,WAAW;GAC5B,UAAU,QAAQ;GAClB,WAAW,MAAM,IAAI,SAAS,EAAE,SAAS,eACpC,MAAM,IAAI,SAAS,CAAyB,YAC7C;GACJ,WAAW;GACZ;AACD,QAAM,IAAI,UAAU,MAAM"}
@@ -1,8 +1,8 @@
1
1
  import "./registry-EWWdkLf7.mjs";
2
2
  import "./r2S3EmptyBucket-B9_pHfvB.mjs";
3
- import { n as runDrift, t as computeDriftReport } from "./drift-CeemyFqL.mjs";
3
+ import { n as runDrift, t as computeDriftReport } from "./drift-C-qnJ-mH.mjs";
4
4
  import "./logpush-job-DJPlpnRu.mjs";
5
- import "./worker-route-x8q3K4-z.mjs";
6
- import "./workers-D3Ekf3mF.mjs";
5
+ import "./worker-route-tOqVbhv3.mjs";
6
+ import "./workers-6r2ONF9J.mjs";
7
7
 
8
8
  export { runDrift };
@@ -1,10 +1,10 @@
1
1
  import { f as getDispatchNamespaces, m as getLogpushJobs, p as getDnsRecords } from "./normalize-DVSTRZhO.mjs";
2
- import { B as getWorkers, C as stackNameForConfig, D as resolveDeployedWorkerName, L as CFApiClient, M as effectiveDispatchNamespaceName, P as namingFromConfig, R as cloudflareAccountIdFromEnv, T as mergeWorkerConfigForResourcePick, V as loadConfig, a as reconcileSecrets, c as vaultReaderFromMap, d as fetchStackImports, m as StateManager, o as secretsDrift, u as requiredSecretsForWorker, v as tenantStateKey } from "./tamer.mjs";
2
+ import { B as getWorkers, E as mergeWorkerConfigForResourcePick, L as CFApiClient, N as effectiveDispatchNamespaceName, O as resolveDeployedWorkerName, R as cloudflareAccountIdFromEnv, V as loadConfig, a as reconcileSecrets, c as vaultReaderFromMap, d as requiredSecretsForWorker, f as fetchStackImports, h as StateManager, o as secretsDrift, u as namingFromConfig, w as stackNameForConfig, y as tenantStateKey } from "./tamer.mjs";
3
3
  import { n as resourceModules } from "./registry-EWWdkLf7.mjs";
4
4
  import { n as dnsRecordCommentMarker, r as dnsRecordStateKey, t as dnsRecordAppliesToEnv } from "./dns-records.resolve-BB2agPAb.mjs";
5
5
  import { r as logpushJobDrift } from "./logpush-job-DJPlpnRu.mjs";
6
- import { t as workerRoutesDrift } from "./worker-route-x8q3K4-z.mjs";
7
- import { t as workersDrift } from "./workers-D3Ekf3mF.mjs";
6
+ import { t as workerRoutesDrift } from "./worker-route-tOqVbhv3.mjs";
7
+ import { t as workersDrift } from "./workers-6r2ONF9J.mjs";
8
8
 
9
9
  //#region src/features/dispatch-namespace/dispatch-namespace.drift.ts
10
10
  function dispatchNamespaceDrift(allDispatch, resources, env, tenant, state) {
@@ -348,4 +348,4 @@ async function buildSecretWorkerInputs(workers, config, env, baseDir, accountId,
348
348
 
349
349
  //#endregion
350
350
  export { runDrift as n, computeDriftReport as t };
351
- //# sourceMappingURL=drift-CeemyFqL.mjs.map
351
+ //# sourceMappingURL=drift-C-qnJ-mH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"drift-CeemyFqL.mjs","names":["drift: ResourceDrift","drift: ResourceDrift","drift: ResourceDrift","byZone: DnsRecordsByZone","out: T[]","REGISTRY_LABELS: Record<string, string>","out: Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }>","workerSecretNames: string[]"],"sources":["../src/features/dispatch-namespace/dispatch-namespace.drift.ts","../src/features/dns-records/dns-records.drift.ts","../src/core/drift/drift.types.ts","../src/core/drift/tenantDrift.ts","../src/cli/commands/drift.ts"],"sourcesContent":["import type {\n DispatchNamespaceResourceConfig,\n DispatchNamespaceStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { ResourceDrift } from \"../../core/drift/drift.types.js\";\nimport { effectiveDispatchNamespaceName } from \"./dispatch-namespace.resolve.js\";\n\ninterface CFDispatchNamespace {\n namespace_name: string;\n}\n\nexport function dispatchNamespaceDrift(\n allDispatch: CFDispatchNamespace[],\n resources: DispatchNamespaceResourceConfig[],\n env: string,\n tenant: TenantMeta,\n state: StateManager,\n): ResourceDrift {\n const drift: ResourceDrift = {\n kind: \"dispatch_namespace\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const cfNames = new Set(allDispatch.map((d) => d.namespace_name));\n const allState = state.getAll();\n const nsState = Object.values(allState).filter(\n (e): e is DispatchNamespaceStateEntry => e.type === \"dispatch_namespace\",\n );\n\n for (const config of resources) {\n const derivedName = effectiveDispatchNamespaceName(config, env, tenant);\n const stateEntry = nsState.find(\n (e) => e.logicalName === config.logicalName && e.derivedName === derivedName,\n );\n const onCf = cfNames.has(derivedName);\n\n if (stateEntry && !onCf) {\n drift.missingFromCloudflare.push({\n logicalName: stateEntry.logicalName,\n derivedName: stateEntry.derivedName,\n });\n } else if (onCf && !stateEntry) {\n drift.unrecordedInState.push({\n logicalName: config.logicalName,\n derivedName,\n });\n } else if (!onCf && !stateEntry) {\n drift.undeployed.push({\n logicalName: config.logicalName,\n derivedName,\n });\n }\n }\n\n return drift;\n}\n","import type {\n DnsRecordResourceConfig,\n DnsRecordStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { ResourceDrift } from \"../../core/drift/drift.types.js\";\nimport {\n dnsRecordAppliesToEnv,\n dnsRecordCommentMarker,\n dnsRecordStateKey,\n} from \"./dns-records.resolve.js\";\n\ninterface CFDnsRecord {\n id: string;\n type: string;\n name: string;\n content: string;\n ttl?: number;\n proxied?: boolean;\n priority?: number;\n comment?: string | null;\n}\n\n/**\n * Map of `zoneId → live records`. The drift caller pre-fetches because\n * other resource modules also iterate zones (worker routes), so we\n * accept the snapshot rather than refetching here.\n */\nexport type DnsRecordsByZone = Map<string, CFDnsRecord[]>;\n\nexport function dnsRecordDrift(\n byZone: DnsRecordsByZone,\n resources: DnsRecordResourceConfig[],\n tenant: TenantMeta,\n env: string,\n state: StateManager,\n): ResourceDrift {\n const drift: ResourceDrift = {\n kind: \"dns_record\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const stateRecords = Object.values(state.getAll()).filter(\n (e): e is DnsRecordStateEntry => e.type === \"dns_record\",\n );\n\n for (const config of resources) {\n if (!dnsRecordAppliesToEnv(config, env)) continue;\n const live = byZone.get(config.zoneId) ?? [];\n const marker = dnsRecordCommentMarker(tenant, env, config.logicalName);\n const stateKey = dnsRecordStateKey(config.zoneId, config.type, config.name);\n const entry = stateRecords.find(\n (e) =>\n e.zoneId === config.zoneId &&\n e.recordType === config.type &&\n e.logicalName === config.logicalName,\n );\n const onCf = entry\n ? live.find((r) => r.id === entry.recordId)\n : live.find(\n (r) =>\n r.type === config.type &&\n typeof r.comment === \"string\" &&\n r.comment.startsWith(marker),\n );\n\n if (entry && !onCf) {\n drift.missingFromCloudflare.push({\n logicalName: entry.logicalName,\n derivedName: `${entry.recordType} ${entry.name}`,\n cfId: entry.recordId,\n });\n } else if (onCf && !entry) {\n drift.unrecordedInState.push({\n logicalName: config.logicalName,\n derivedName: `${config.type} ${onCf.name}`,\n cfId: onCf.id,\n });\n } else if (!onCf && !entry) {\n drift.undeployed.push({\n logicalName: config.logicalName,\n derivedName: `${config.type} ${config.name}`,\n detail: stateKey,\n });\n }\n }\n\n return drift;\n}\n","/**\n * Read-only drift report comparing recorded state vs. Cloudflare reality vs.\n * the current `tamer.config.ts`.\n */\n\nexport type DriftKind =\n | \"d1\"\n | \"r2\"\n | \"kv\"\n | \"queue\"\n | \"hyperdrive\"\n | \"vectorize\"\n | \"ai_gateway\"\n | \"pipeline\"\n | \"workflow\"\n | \"secret_store\"\n | \"secret\"\n | \"dns_record\"\n | \"dispatch_namespace\"\n | \"logpush_job\"\n | \"tenant\"\n | \"worker_route\"\n | \"worker_script\";\n\nexport interface DriftEntry {\n /** Logical resource name from `tamer.config.ts`. */\n logicalName: string;\n /** Cloudflare-side name (or `(unknown)` when no CF or state side knows it). */\n derivedName: string;\n /** Cloudflare resource ID, when known (D1 uuid, KV id). */\n cfId?: string;\n /** Optional human-readable detail (e.g. shard date). */\n detail?: string;\n}\n\nexport interface ResourceDrift {\n kind: DriftKind;\n /** Tracked in state but no longer present on Cloudflare. */\n missingFromCloudflare: DriftEntry[];\n /**\n * Present on Cloudflare and matches a declared resource in this config,\n * but no state entry tracks it (e.g. created out-of-band).\n */\n unrecordedInState: DriftEntry[];\n /**\n * Declared in this stack's config but neither tracked in state nor present\n * on Cloudflare (run `tamer apply`).\n */\n undeployed: DriftEntry[];\n}\n\nexport interface DriftReport {\n tenantId: string;\n env: string;\n generatedAt: string;\n resources: ResourceDrift[];\n /** True iff any of the three categories has at least one entry. */\n hasDrift: boolean;\n}\n\nexport function resourceDriftIsClean(d: ResourceDrift): boolean {\n return (\n d.missingFromCloudflare.length === 0 &&\n d.unrecordedInState.length === 0 &&\n d.undeployed.length === 0\n );\n}\n\nexport function reportHasDrift(resources: ResourceDrift[]): boolean {\n return resources.some((d) => !resourceDriftIsClean(d));\n}\n","import type { CFApiClient } from \"../api/CFApiClient.js\";\nimport type { StateManager } from \"../state/StateManager.js\";\nimport type { ResourceDrift } from \"./drift.types.js\";\nimport { tenantStateKey } from \"../tenant/tenantKeys.js\";\n\ninterface CFD1 {\n uuid: string;\n name: string;\n}\n\n/**\n * Drift for workspace tenants in {@link CfiState.tenants}: dispatch script and\n * recorded D1 shards must still exist on Cloudflare.\n *\n * `unrecordedInState` / `undeployed` are intentionally empty here — tenant\n * discovery from CF alone is heuristic until product/script naming is fully\n * pinned (`docs/scope-remaining.md` D-1).\n */\nexport async function tenantDrift(\n state: StateManager,\n api: CFApiClient,\n allD1: CFD1[],\n): Promise<ResourceDrift> {\n const drift: ResourceDrift = {\n kind: \"tenant\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const d1ById = new Map(allD1.map((d) => [d.uuid, d.name]));\n const tenants = state\n .listTenants()\n .filter((t) => t.provisioningStatus !== \"tombstoned\");\n if (tenants.length === 0) return drift;\n\n const scriptLists = new Map<string, Set<string>>();\n async function scriptsInNs(ns: string): Promise<Set<string>> {\n let set = scriptLists.get(ns);\n if (!set) {\n const list = await api.dispatchNamespaceScriptList(ns);\n set = new Set(list.map((s) => s.id));\n scriptLists.set(ns, set);\n }\n return set;\n }\n\n for (const t of tenants) {\n const logical = tenantStateKey(t.product, t.workspace);\n try {\n const ids = await scriptsInNs(t.dispatchNamespaceName);\n if (!ids.has(t.scriptName)) {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: t.scriptName,\n detail: \"dispatch_script\",\n });\n }\n } catch {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: t.dispatchNamespaceName,\n detail: \"dispatch_namespace_list_failed\",\n });\n }\n\n for (const shard of t.d1Shards ?? []) {\n if (!d1ById.has(shard.cfId)) {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: shard.derivedName,\n cfId: shard.cfId,\n detail: `d1:${shard.role}`,\n });\n }\n }\n }\n\n return drift;\n}\n","import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { dispatchNamespaceDrift } from \"../../features/dispatch-namespace/index.js\";\nimport {\n dnsRecordDrift,\n type DnsRecordsByZone,\n} from \"../../features/dns-records/index.js\";\nimport { getDispatchNamespaces, getDnsRecords, getLogpushJobs } from \"../../types.js\";\nimport { logpushJobDrift } from \"../../features/logpush-job/index.js\";\nimport type {\n DriftReport,\n ResourceDrift,\n} from \"../../core/drift/drift.types.js\";\nimport { reportHasDrift } from \"../../core/drift/drift.types.js\";\nimport { tenantDrift } from \"../../core/drift/tenantDrift.js\";\nimport { workerRoutesDrift } from \"../../features/worker-route/index.js\";\nimport { workersDrift } from \"../../features/workers/index.js\";\nimport { resourceModules } from \"../../core/registry/registry.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { mergeWorkerConfigForResourcePick } from \"../../core/config/resolver.js\";\nimport { resolveDeployedWorkerName } from \"../../core/config/resolver.js\";\nimport { requiredSecretsForWorker } from \"../../core/secrets/declared.js\";\nimport {\n reconcileSecrets,\n secretsDrift,\n vaultReaderFromMap,\n type SecretsVaultReader,\n} from \"../../core/secrets/reconcile.js\";\n\n/**\n * Compute a read-only drift report for the given env.\n *\n * Compares Tamer state (D1 `tamer-state-{env}`) against the Cloudflare API\n * and the resources declared in `tamer.config.ts`. Reports three categories:\n *\n * - `missingFromCloudflare` — tracked in state but the CF resource is gone.\n * - `unrecordedInState` — exists on CF and matches a declared resource, but\n * no state entry tracks it (e.g. created out-of-band; run `tamer sync`).\n * - `undeployed` — declared in this stack's config, present in neither\n * state nor CF (run `tamer apply`).\n *\n * Pure: never writes to state. Returns the report so callers can choose how to\n * render or consume it.\n */\nexport async function computeDriftReport(options: {\n env?: string;\n configPath?: string;\n /** Optional vault reader for secret reconciliation (defaults to empty). */\n secretsVault?: SecretsVaultReader;\n}): Promise<DriftReport> {\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId = config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const api = new CFApiClient(accountId);\n const naming = namingFromConfig(config);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n // Tolerant pre-fetch keeps drift accurate when worker `tamerRoutes`\n // depend on sibling-stack outputs (otherwise the placeholder pattern\n // would never match anything CF returned).\n const imports = await fetchStackImports(api, config, env).catch(() => ({}));\n\n async function safeList<T>(\n label: string,\n fn: () => Promise<T[]>,\n ): Promise<T[]> {\n try {\n return await fn();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[drift] skipping ${label}: ${msg}`);\n return [];\n }\n }\n\n const lists = await Promise.all(\n resourceModules.map((m) =>\n safeList(`${m.label} list`, () => m.fetchAll(api)),\n ),\n );\n\n const allDispatch =\n getDispatchNamespaces(config).length > 0\n ? await safeList(\"dispatch namespaces\", () =>\n api.dispatchNamespaceListAll(),\n )\n : [];\n\n const allLogpushJobs =\n getLogpushJobs(config).length > 0 && env !== \"local\"\n ? await safeList(\"logpush jobs\", () => api.logpushAccountJobsList())\n : [];\n\n const workers = await getWorkers(config, baseDir);\n\n const aggregated = new Map<string, ResourceDrift>();\n function merge(d: ResourceDrift): void {\n const existing = aggregated.get(d.kind);\n if (!existing) {\n aggregated.set(d.kind, d);\n return;\n }\n existing.missingFromCloudflare.push(...d.missingFromCloudflare);\n existing.unrecordedInState.push(...d.unrecordedInState);\n existing.undeployed.push(...d.undeployed);\n }\n\n for (const [workerKey, workerConfig] of workers) {\n const mergedWorker = mergeWorkerConfigForResourcePick(\n config,\n workerKey,\n workerConfig,\n env,\n accountId,\n naming,\n state,\n { referencesMode: \"tolerant\", imports },\n );\n resourceModules.forEach((mod, i) => {\n const resources = mod.pickResources(mergedWorker);\n if (resources.length === 0) return;\n merge(\n mod.drift({\n resources,\n all: lists[i],\n tenant: config.tenant,\n env,\n api,\n state,\n naming,\n config,\n baseDir,\n }),\n );\n });\n }\n\n const dispatchResources = getDispatchNamespaces(config);\n if (dispatchResources.length > 0) {\n merge(\n dispatchNamespaceDrift(\n allDispatch,\n dispatchResources,\n env,\n config.tenant,\n state,\n ),\n );\n }\n\n const dnsResources = getDnsRecords(config);\n if (dnsResources.length > 0 && env !== \"local\") {\n const byZone: DnsRecordsByZone = new Map();\n const zones = Array.from(new Set(dnsResources.map((r) => r.zoneId)));\n for (const zoneId of zones) {\n const live = await safeList(`dns records (zone ${zoneId})`, () =>\n api.zoneDnsRecordListAll(zoneId),\n );\n byZone.set(zoneId, live);\n }\n merge(dnsRecordDrift(byZone, dnsResources, config.tenant, env, state));\n }\n\n const logpushResources = getLogpushJobs(config);\n if (logpushResources.length > 0 && env !== \"local\") {\n merge(\n logpushJobDrift(\n allLogpushJobs,\n logpushResources,\n env,\n config.tenant,\n state,\n ),\n );\n }\n\n if (state.listTenants().length > 0) {\n const allD1Idx = resourceModules.findIndex((m) => m.kind === \"d1\");\n const allD1 =\n allD1Idx >= 0\n ? (lists[allD1Idx] as Array<{ uuid: string; name: string }>)\n : [];\n merge(await tenantDrift(state, api, allD1));\n }\n\n const workerRouteReport = await workerRoutesDrift(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n if (workerRouteReport) merge(workerRouteReport);\n\n const workerScriptReport = await workersDrift(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n if (workerScriptReport) merge(workerScriptReport);\n\n const secretWorkers = await buildSecretWorkerInputs(\n workers,\n config,\n env,\n baseDir,\n accountId,\n naming,\n state,\n api,\n imports,\n );\n if (secretWorkers.length > 0) {\n const secretEntries = await reconcileSecrets({\n workers: secretWorkers,\n vault: options.secretsVault ?? vaultReaderFromMap({}),\n state,\n });\n merge(secretsDrift(secretEntries));\n }\n\n const dedupedResources = Array.from(aggregated.values()).map((d) => ({\n ...d,\n missingFromCloudflare: dedupe(d.missingFromCloudflare),\n unrecordedInState: dedupe(d.unrecordedInState),\n undeployed: dedupe(d.undeployed),\n }));\n\n return {\n tenantId: config.tenant.id,\n env,\n generatedAt: new Date().toISOString(),\n resources: dedupedResources,\n hasDrift: reportHasDrift(dedupedResources),\n };\n}\n\nfunction dedupe<T extends { logicalName: string; derivedName: string }>(\n list: T[],\n): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const item of list) {\n const key = `${item.logicalName}::${item.derivedName}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n\n/**\n * CLI entry point. Prints a human report (or JSON when `--json`) and sets a\n * non-zero process exit code when drift is found.\n */\nexport async function runDrift(options: {\n env?: string;\n configPath?: string;\n json?: boolean;\n}): Promise<number> {\n const report = await computeDriftReport({\n env: options.env,\n configPath: options.configPath,\n });\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n } else {\n printHumanReport(report);\n }\n\n return report.hasDrift ? 1 : 0;\n}\n\nfunction printHumanReport(report: DriftReport): void {\n console.log(\n `\\nDrift report — tenant ${report.tenantId}, env ${report.env}\\n`,\n );\n if (report.resources.length === 0) {\n console.log(\" (no managed resource kinds in this config)\\n\");\n return;\n }\n for (const d of report.resources) {\n const total =\n d.missingFromCloudflare.length +\n d.unrecordedInState.length +\n d.undeployed.length;\n console.log(`${labelFor(d.kind)} (${total} drift):`);\n if (total === 0) {\n console.log(\" ok\");\n continue;\n }\n if (d.missingFromCloudflare.length) {\n console.log(\" missing from Cloudflare (state references gone):\");\n for (const e of d.missingFromCloudflare) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}${suffix(e.cfId)}`);\n }\n }\n if (d.unrecordedInState.length) {\n console.log(\" unrecorded in state (run `tamer sync`):\");\n for (const e of d.unrecordedInState) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}${suffix(e.cfId)}`);\n }\n }\n if (d.undeployed.length) {\n console.log(\" undeployed (run `tamer apply`):\");\n for (const e of d.undeployed) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}`);\n }\n }\n }\n console.log(report.hasDrift ? \"\\nDrift detected.\\n\" : \"\\nNo drift.\\n\");\n}\n\nconst REGISTRY_LABELS: Record<string, string> = Object.fromEntries(\n resourceModules.map((m) => [m.kind, m.label]),\n);\n\nfunction labelFor(kind: ResourceDrift[\"kind\"]): string {\n if (REGISTRY_LABELS[kind]) return REGISTRY_LABELS[kind];\n switch (kind) {\n case \"dispatch_namespace\":\n return \"Dispatch namespaces\";\n case \"logpush_job\":\n return \"Logpush jobs\";\n case \"dns_record\":\n return \"DNS records\";\n case \"tenant\":\n return \"Workspace tenants\";\n case \"worker_route\":\n return \"HTTP routes (Workers Routes API)\";\n case \"worker_script\":\n return \"Worker scripts\";\n case \"secret\":\n return \"Worker secrets\";\n default:\n return kind;\n }\n}\n\nfunction suffix(cfId?: string): string {\n return cfId ? ` [${cfId}]` : \"\";\n}\n\nasync function buildSecretWorkerInputs(\n workers: Awaited<ReturnType<typeof getWorkers>>,\n config: Awaited<ReturnType<typeof loadConfig>>,\n env: string,\n baseDir: string,\n accountId: string,\n naming: ReturnType<typeof namingFromConfig>,\n state: StateManager,\n api: CFApiClient,\n imports: Awaited<ReturnType<typeof fetchStackImports>>,\n): Promise<\n Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }>\n> {\n const out: Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }> = [];\n\n for (const [workerKey, workerConfig] of workers) {\n const merged = mergeWorkerConfigForResourcePick(\n config,\n workerKey,\n workerConfig,\n env,\n accountId,\n naming,\n state,\n { referencesMode: \"tolerant\", imports },\n );\n const required = requiredSecretsForWorker(merged);\n if (required.length === 0) continue;\n\n const deployedName = resolveDeployedWorkerName(\n config,\n workerKey,\n workerConfig,\n env,\n naming,\n );\n let workerSecretNames: string[] = [];\n if (env !== \"local\") {\n try {\n workerSecretNames = await api.workersSecretsList(deployedName);\n } catch {\n workerSecretNames = [];\n }\n }\n\n out.push({ workerKey, required, workerSecretNames });\n }\n\n return out;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"drift-C-qnJ-mH.mjs","names":["drift: ResourceDrift","drift: ResourceDrift","drift: ResourceDrift","byZone: DnsRecordsByZone","out: T[]","REGISTRY_LABELS: Record<string, string>","out: Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }>","workerSecretNames: string[]"],"sources":["../src/features/dispatch-namespace/dispatch-namespace.drift.ts","../src/features/dns-records/dns-records.drift.ts","../src/core/drift/drift.types.ts","../src/core/drift/tenantDrift.ts","../src/cli/commands/drift.ts"],"sourcesContent":["import type {\n DispatchNamespaceResourceConfig,\n DispatchNamespaceStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { ResourceDrift } from \"../../core/drift/drift.types.js\";\nimport { effectiveDispatchNamespaceName } from \"./dispatch-namespace.resolve.js\";\n\ninterface CFDispatchNamespace {\n namespace_name: string;\n}\n\nexport function dispatchNamespaceDrift(\n allDispatch: CFDispatchNamespace[],\n resources: DispatchNamespaceResourceConfig[],\n env: string,\n tenant: TenantMeta,\n state: StateManager,\n): ResourceDrift {\n const drift: ResourceDrift = {\n kind: \"dispatch_namespace\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const cfNames = new Set(allDispatch.map((d) => d.namespace_name));\n const allState = state.getAll();\n const nsState = Object.values(allState).filter(\n (e): e is DispatchNamespaceStateEntry => e.type === \"dispatch_namespace\",\n );\n\n for (const config of resources) {\n const derivedName = effectiveDispatchNamespaceName(config, env, tenant);\n const stateEntry = nsState.find(\n (e) => e.logicalName === config.logicalName && e.derivedName === derivedName,\n );\n const onCf = cfNames.has(derivedName);\n\n if (stateEntry && !onCf) {\n drift.missingFromCloudflare.push({\n logicalName: stateEntry.logicalName,\n derivedName: stateEntry.derivedName,\n });\n } else if (onCf && !stateEntry) {\n drift.unrecordedInState.push({\n logicalName: config.logicalName,\n derivedName,\n });\n } else if (!onCf && !stateEntry) {\n drift.undeployed.push({\n logicalName: config.logicalName,\n derivedName,\n });\n }\n }\n\n return drift;\n}\n","import type {\n DnsRecordResourceConfig,\n DnsRecordStateEntry,\n TenantMeta,\n} from \"../../types.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport type { ResourceDrift } from \"../../core/drift/drift.types.js\";\nimport {\n dnsRecordAppliesToEnv,\n dnsRecordCommentMarker,\n dnsRecordStateKey,\n} from \"./dns-records.resolve.js\";\n\ninterface CFDnsRecord {\n id: string;\n type: string;\n name: string;\n content: string;\n ttl?: number;\n proxied?: boolean;\n priority?: number;\n comment?: string | null;\n}\n\n/**\n * Map of `zoneId → live records`. The drift caller pre-fetches because\n * other resource modules also iterate zones (worker routes), so we\n * accept the snapshot rather than refetching here.\n */\nexport type DnsRecordsByZone = Map<string, CFDnsRecord[]>;\n\nexport function dnsRecordDrift(\n byZone: DnsRecordsByZone,\n resources: DnsRecordResourceConfig[],\n tenant: TenantMeta,\n env: string,\n state: StateManager,\n): ResourceDrift {\n const drift: ResourceDrift = {\n kind: \"dns_record\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const stateRecords = Object.values(state.getAll()).filter(\n (e): e is DnsRecordStateEntry => e.type === \"dns_record\",\n );\n\n for (const config of resources) {\n if (!dnsRecordAppliesToEnv(config, env)) continue;\n const live = byZone.get(config.zoneId) ?? [];\n const marker = dnsRecordCommentMarker(tenant, env, config.logicalName);\n const stateKey = dnsRecordStateKey(config.zoneId, config.type, config.name);\n const entry = stateRecords.find(\n (e) =>\n e.zoneId === config.zoneId &&\n e.recordType === config.type &&\n e.logicalName === config.logicalName,\n );\n const onCf = entry\n ? live.find((r) => r.id === entry.recordId)\n : live.find(\n (r) =>\n r.type === config.type &&\n typeof r.comment === \"string\" &&\n r.comment.startsWith(marker),\n );\n\n if (entry && !onCf) {\n drift.missingFromCloudflare.push({\n logicalName: entry.logicalName,\n derivedName: `${entry.recordType} ${entry.name}`,\n cfId: entry.recordId,\n });\n } else if (onCf && !entry) {\n drift.unrecordedInState.push({\n logicalName: config.logicalName,\n derivedName: `${config.type} ${onCf.name}`,\n cfId: onCf.id,\n });\n } else if (!onCf && !entry) {\n drift.undeployed.push({\n logicalName: config.logicalName,\n derivedName: `${config.type} ${config.name}`,\n detail: stateKey,\n });\n }\n }\n\n return drift;\n}\n","/**\n * Read-only drift report comparing recorded state vs. Cloudflare reality vs.\n * the current `tamer.config.ts`.\n */\n\nexport type DriftKind =\n | \"d1\"\n | \"r2\"\n | \"kv\"\n | \"queue\"\n | \"hyperdrive\"\n | \"vectorize\"\n | \"ai_gateway\"\n | \"pipeline\"\n | \"workflow\"\n | \"secret_store\"\n | \"secret\"\n | \"dns_record\"\n | \"dispatch_namespace\"\n | \"logpush_job\"\n | \"tenant\"\n | \"worker_route\"\n | \"worker_script\";\n\nexport interface DriftEntry {\n /** Logical resource name from `tamer.config.ts`. */\n logicalName: string;\n /** Cloudflare-side name (or `(unknown)` when no CF or state side knows it). */\n derivedName: string;\n /** Cloudflare resource ID, when known (D1 uuid, KV id). */\n cfId?: string;\n /** Optional human-readable detail (e.g. shard date). */\n detail?: string;\n}\n\nexport interface ResourceDrift {\n kind: DriftKind;\n /** Tracked in state but no longer present on Cloudflare. */\n missingFromCloudflare: DriftEntry[];\n /**\n * Present on Cloudflare and matches a declared resource in this config,\n * but no state entry tracks it (e.g. created out-of-band).\n */\n unrecordedInState: DriftEntry[];\n /**\n * Declared in this stack's config but neither tracked in state nor present\n * on Cloudflare (run `tamer apply`).\n */\n undeployed: DriftEntry[];\n}\n\nexport interface DriftReport {\n tenantId: string;\n env: string;\n generatedAt: string;\n resources: ResourceDrift[];\n /** True iff any of the three categories has at least one entry. */\n hasDrift: boolean;\n}\n\nexport function resourceDriftIsClean(d: ResourceDrift): boolean {\n return (\n d.missingFromCloudflare.length === 0 &&\n d.unrecordedInState.length === 0 &&\n d.undeployed.length === 0\n );\n}\n\nexport function reportHasDrift(resources: ResourceDrift[]): boolean {\n return resources.some((d) => !resourceDriftIsClean(d));\n}\n","import type { CFApiClient } from \"../api/CFApiClient.js\";\nimport type { StateManager } from \"../state/StateManager.js\";\nimport type { ResourceDrift } from \"./drift.types.js\";\nimport { tenantStateKey } from \"../tenant/tenantKeys.js\";\n\ninterface CFD1 {\n uuid: string;\n name: string;\n}\n\n/**\n * Drift for workspace tenants in {@link CfiState.tenants}: dispatch script and\n * recorded D1 shards must still exist on Cloudflare.\n *\n * `unrecordedInState` / `undeployed` are intentionally empty here — tenant\n * discovery from CF alone is heuristic until product/script naming is fully\n * pinned (`docs/scope-remaining.md` D-1).\n */\nexport async function tenantDrift(\n state: StateManager,\n api: CFApiClient,\n allD1: CFD1[],\n): Promise<ResourceDrift> {\n const drift: ResourceDrift = {\n kind: \"tenant\",\n missingFromCloudflare: [],\n unrecordedInState: [],\n undeployed: [],\n };\n\n const d1ById = new Map(allD1.map((d) => [d.uuid, d.name]));\n const tenants = state\n .listTenants()\n .filter((t) => t.provisioningStatus !== \"tombstoned\");\n if (tenants.length === 0) return drift;\n\n const scriptLists = new Map<string, Set<string>>();\n async function scriptsInNs(ns: string): Promise<Set<string>> {\n let set = scriptLists.get(ns);\n if (!set) {\n const list = await api.dispatchNamespaceScriptList(ns);\n set = new Set(list.map((s) => s.id));\n scriptLists.set(ns, set);\n }\n return set;\n }\n\n for (const t of tenants) {\n const logical = tenantStateKey(t.product, t.workspace);\n try {\n const ids = await scriptsInNs(t.dispatchNamespaceName);\n if (!ids.has(t.scriptName)) {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: t.scriptName,\n detail: \"dispatch_script\",\n });\n }\n } catch {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: t.dispatchNamespaceName,\n detail: \"dispatch_namespace_list_failed\",\n });\n }\n\n for (const shard of t.d1Shards ?? []) {\n if (!d1ById.has(shard.cfId)) {\n drift.missingFromCloudflare.push({\n logicalName: logical,\n derivedName: shard.derivedName,\n cfId: shard.cfId,\n detail: `d1:${shard.role}`,\n });\n }\n }\n }\n\n return drift;\n}\n","import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { dispatchNamespaceDrift } from \"../../features/dispatch-namespace/index.js\";\nimport {\n dnsRecordDrift,\n type DnsRecordsByZone,\n} from \"../../features/dns-records/index.js\";\nimport { getDispatchNamespaces, getDnsRecords, getLogpushJobs } from \"../../types.js\";\nimport { logpushJobDrift } from \"../../features/logpush-job/index.js\";\nimport type {\n DriftReport,\n ResourceDrift,\n} from \"../../core/drift/drift.types.js\";\nimport { reportHasDrift } from \"../../core/drift/drift.types.js\";\nimport { tenantDrift } from \"../../core/drift/tenantDrift.js\";\nimport { workerRoutesDrift } from \"../../features/worker-route/index.js\";\nimport { workersDrift } from \"../../features/workers/index.js\";\nimport { resourceModules } from \"../../core/registry/registry.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { mergeWorkerConfigForResourcePick } from \"../../core/config/resolver.js\";\nimport { resolveDeployedWorkerName } from \"../../core/config/resolver.js\";\nimport { requiredSecretsForWorker } from \"../../core/secrets/declared.js\";\nimport {\n reconcileSecrets,\n secretsDrift,\n vaultReaderFromMap,\n type SecretsVaultReader,\n} from \"../../core/secrets/reconcile.js\";\n\n/**\n * Compute a read-only drift report for the given env.\n *\n * Compares Tamer state (D1 `tamer-state-{env}`) against the Cloudflare API\n * and the resources declared in `tamer.config.ts`. Reports three categories:\n *\n * - `missingFromCloudflare` — tracked in state but the CF resource is gone.\n * - `unrecordedInState` — exists on CF and matches a declared resource, but\n * no state entry tracks it (e.g. created out-of-band; run `tamer sync`).\n * - `undeployed` — declared in this stack's config, present in neither\n * state nor CF (run `tamer apply`).\n *\n * Pure: never writes to state. Returns the report so callers can choose how to\n * render or consume it.\n */\nexport async function computeDriftReport(options: {\n env?: string;\n configPath?: string;\n /** Optional vault reader for secret reconciliation (defaults to empty). */\n secretsVault?: SecretsVaultReader;\n}): Promise<DriftReport> {\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId = config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const api = new CFApiClient(accountId);\n const naming = namingFromConfig(config);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n // Tolerant pre-fetch keeps drift accurate when worker `tamerRoutes`\n // depend on sibling-stack outputs (otherwise the placeholder pattern\n // would never match anything CF returned).\n const imports = await fetchStackImports(api, config, env).catch(() => ({}));\n\n async function safeList<T>(\n label: string,\n fn: () => Promise<T[]>,\n ): Promise<T[]> {\n try {\n return await fn();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[drift] skipping ${label}: ${msg}`);\n return [];\n }\n }\n\n const lists = await Promise.all(\n resourceModules.map((m) =>\n safeList(`${m.label} list`, () => m.fetchAll(api)),\n ),\n );\n\n const allDispatch =\n getDispatchNamespaces(config).length > 0\n ? await safeList(\"dispatch namespaces\", () =>\n api.dispatchNamespaceListAll(),\n )\n : [];\n\n const allLogpushJobs =\n getLogpushJobs(config).length > 0 && env !== \"local\"\n ? await safeList(\"logpush jobs\", () => api.logpushAccountJobsList())\n : [];\n\n const workers = await getWorkers(config, baseDir);\n\n const aggregated = new Map<string, ResourceDrift>();\n function merge(d: ResourceDrift): void {\n const existing = aggregated.get(d.kind);\n if (!existing) {\n aggregated.set(d.kind, d);\n return;\n }\n existing.missingFromCloudflare.push(...d.missingFromCloudflare);\n existing.unrecordedInState.push(...d.unrecordedInState);\n existing.undeployed.push(...d.undeployed);\n }\n\n for (const [workerKey, workerConfig] of workers) {\n const mergedWorker = mergeWorkerConfigForResourcePick(\n config,\n workerKey,\n workerConfig,\n env,\n accountId,\n naming,\n state,\n { referencesMode: \"tolerant\", imports },\n );\n resourceModules.forEach((mod, i) => {\n const resources = mod.pickResources(mergedWorker);\n if (resources.length === 0) return;\n merge(\n mod.drift({\n resources,\n all: lists[i],\n tenant: config.tenant,\n env,\n api,\n state,\n naming,\n config,\n baseDir,\n }),\n );\n });\n }\n\n const dispatchResources = getDispatchNamespaces(config);\n if (dispatchResources.length > 0) {\n merge(\n dispatchNamespaceDrift(\n allDispatch,\n dispatchResources,\n env,\n config.tenant,\n state,\n ),\n );\n }\n\n const dnsResources = getDnsRecords(config);\n if (dnsResources.length > 0 && env !== \"local\") {\n const byZone: DnsRecordsByZone = new Map();\n const zones = Array.from(new Set(dnsResources.map((r) => r.zoneId)));\n for (const zoneId of zones) {\n const live = await safeList(`dns records (zone ${zoneId})`, () =>\n api.zoneDnsRecordListAll(zoneId),\n );\n byZone.set(zoneId, live);\n }\n merge(dnsRecordDrift(byZone, dnsResources, config.tenant, env, state));\n }\n\n const logpushResources = getLogpushJobs(config);\n if (logpushResources.length > 0 && env !== \"local\") {\n merge(\n logpushJobDrift(\n allLogpushJobs,\n logpushResources,\n env,\n config.tenant,\n state,\n ),\n );\n }\n\n if (state.listTenants().length > 0) {\n const allD1Idx = resourceModules.findIndex((m) => m.kind === \"d1\");\n const allD1 =\n allD1Idx >= 0\n ? (lists[allD1Idx] as Array<{ uuid: string; name: string }>)\n : [];\n merge(await tenantDrift(state, api, allD1));\n }\n\n const workerRouteReport = await workerRoutesDrift(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n if (workerRouteReport) merge(workerRouteReport);\n\n const workerScriptReport = await workersDrift(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n if (workerScriptReport) merge(workerScriptReport);\n\n const secretWorkers = await buildSecretWorkerInputs(\n workers,\n config,\n env,\n baseDir,\n accountId,\n naming,\n state,\n api,\n imports,\n );\n if (secretWorkers.length > 0) {\n const secretEntries = await reconcileSecrets({\n workers: secretWorkers,\n vault: options.secretsVault ?? vaultReaderFromMap({}),\n state,\n });\n merge(secretsDrift(secretEntries));\n }\n\n const dedupedResources = Array.from(aggregated.values()).map((d) => ({\n ...d,\n missingFromCloudflare: dedupe(d.missingFromCloudflare),\n unrecordedInState: dedupe(d.unrecordedInState),\n undeployed: dedupe(d.undeployed),\n }));\n\n return {\n tenantId: config.tenant.id,\n env,\n generatedAt: new Date().toISOString(),\n resources: dedupedResources,\n hasDrift: reportHasDrift(dedupedResources),\n };\n}\n\nfunction dedupe<T extends { logicalName: string; derivedName: string }>(\n list: T[],\n): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const item of list) {\n const key = `${item.logicalName}::${item.derivedName}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n return out;\n}\n\n/**\n * CLI entry point. Prints a human report (or JSON when `--json`) and sets a\n * non-zero process exit code when drift is found.\n */\nexport async function runDrift(options: {\n env?: string;\n configPath?: string;\n json?: boolean;\n}): Promise<number> {\n const report = await computeDriftReport({\n env: options.env,\n configPath: options.configPath,\n });\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n } else {\n printHumanReport(report);\n }\n\n return report.hasDrift ? 1 : 0;\n}\n\nfunction printHumanReport(report: DriftReport): void {\n console.log(\n `\\nDrift report — tenant ${report.tenantId}, env ${report.env}\\n`,\n );\n if (report.resources.length === 0) {\n console.log(\" (no managed resource kinds in this config)\\n\");\n return;\n }\n for (const d of report.resources) {\n const total =\n d.missingFromCloudflare.length +\n d.unrecordedInState.length +\n d.undeployed.length;\n console.log(`${labelFor(d.kind)} (${total} drift):`);\n if (total === 0) {\n console.log(\" ok\");\n continue;\n }\n if (d.missingFromCloudflare.length) {\n console.log(\" missing from Cloudflare (state references gone):\");\n for (const e of d.missingFromCloudflare) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}${suffix(e.cfId)}`);\n }\n }\n if (d.unrecordedInState.length) {\n console.log(\" unrecorded in state (run `tamer sync`):\");\n for (const e of d.unrecordedInState) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}${suffix(e.cfId)}`);\n }\n }\n if (d.undeployed.length) {\n console.log(\" undeployed (run `tamer apply`):\");\n for (const e of d.undeployed) {\n console.log(` - ${e.logicalName} -> ${e.derivedName}`);\n }\n }\n }\n console.log(report.hasDrift ? \"\\nDrift detected.\\n\" : \"\\nNo drift.\\n\");\n}\n\nconst REGISTRY_LABELS: Record<string, string> = Object.fromEntries(\n resourceModules.map((m) => [m.kind, m.label]),\n);\n\nfunction labelFor(kind: ResourceDrift[\"kind\"]): string {\n if (REGISTRY_LABELS[kind]) return REGISTRY_LABELS[kind];\n switch (kind) {\n case \"dispatch_namespace\":\n return \"Dispatch namespaces\";\n case \"logpush_job\":\n return \"Logpush jobs\";\n case \"dns_record\":\n return \"DNS records\";\n case \"tenant\":\n return \"Workspace tenants\";\n case \"worker_route\":\n return \"HTTP routes (Workers Routes API)\";\n case \"worker_script\":\n return \"Worker scripts\";\n case \"secret\":\n return \"Worker secrets\";\n default:\n return kind;\n }\n}\n\nfunction suffix(cfId?: string): string {\n return cfId ? ` [${cfId}]` : \"\";\n}\n\nasync function buildSecretWorkerInputs(\n workers: Awaited<ReturnType<typeof getWorkers>>,\n config: Awaited<ReturnType<typeof loadConfig>>,\n env: string,\n baseDir: string,\n accountId: string,\n naming: ReturnType<typeof namingFromConfig>,\n state: StateManager,\n api: CFApiClient,\n imports: Awaited<ReturnType<typeof fetchStackImports>>,\n): Promise<\n Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }>\n> {\n const out: Array<{\n workerKey: string;\n required: string[];\n workerSecretNames: string[];\n }> = [];\n\n for (const [workerKey, workerConfig] of workers) {\n const merged = mergeWorkerConfigForResourcePick(\n config,\n workerKey,\n workerConfig,\n env,\n accountId,\n naming,\n state,\n { referencesMode: \"tolerant\", imports },\n );\n const required = requiredSecretsForWorker(merged);\n if (required.length === 0) continue;\n\n const deployedName = resolveDeployedWorkerName(\n config,\n workerKey,\n workerConfig,\n env,\n naming,\n );\n let workerSecretNames: string[] = [];\n if (env !== \"local\") {\n try {\n workerSecretNames = await api.workersSecretsList(deployedName);\n } catch {\n workerSecretNames = [];\n }\n }\n\n out.push({ workerKey, required, workerSecretNames });\n }\n\n return out;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { C as stackNameForConfig, L as CFApiClient, R as cloudflareAccountIdFromEnv, V as loadConfig, m as StateManager } from "./tamer.mjs";
1
+ import { L as CFApiClient, R as cloudflareAccountIdFromEnv, V as loadConfig, h as StateManager, w as stackNameForConfig } from "./tamer.mjs";
2
2
 
3
3
  //#region src/cli/commands/events.ts
4
4
  function formatDuration(startedAt, completedAt) {
@@ -63,4 +63,4 @@ async function runEvents(options) {
63
63
 
64
64
  //#endregion
65
65
  export { runEvents };
66
- //# sourceMappingURL=events-otk0l3aJ.mjs.map
66
+ //# sourceMappingURL=events-Bor7XgLC.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"events-otk0l3aJ.mjs","names":[],"sources":["../src/cli/commands/events.ts"],"sourcesContent":["import { loadConfig } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport type { CfiOperationRecord } from \"../../types.js\";\n\nfunction formatDuration(\n startedAt: string,\n completedAt: string | undefined,\n): string | undefined {\n if (!completedAt) return undefined;\n const a = Date.parse(startedAt);\n const b = Date.parse(completedAt);\n if (!Number.isFinite(a) || !Number.isFinite(b) || b < a) return undefined;\n const ms = b - a;\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction printOp(label: string, op: CfiOperationRecord): void {\n const dur = formatDuration(op.startedAt, op.completedAt);\n console.log(` [${label}] ${op.command}`);\n console.log(` started: ${op.startedAt}`);\n if (op.completedAt) {\n console.log(` completed: ${op.completedAt}`);\n }\n if (dur) console.log(` duration: ${dur}`);\n if (op.detail) console.log(` detail: ${op.detail}`);\n if (op.errorMessage) console.log(` error: ${op.errorMessage}`);\n console.log();\n}\n\n/**\n * Read-only: print recent completed stack operations from D1 state\n * (`operationHistory`) plus any in-progress marker (`lastOperation`).\n */\nexport async function runEvents(options: {\n env?: string;\n configPath?: string;\n limit?: number;\n json?: boolean;\n}): Promise<void> {\n const env = options.env ?? \"local\";\n const config = await loadConfig(options.configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n const stackName = stackNameForConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(config.tenant.id, env, stackName);\n await state.hydrate(api);\n\n const last = state.getLastOperation();\n const inProgress =\n last?.status === \"in_progress\" ? last : undefined;\n let history = state.getOperationHistory();\n if (options.limit !== undefined) {\n history = history.slice(0, options.limit);\n }\n\n if (options.json) {\n const out = {\n stackName,\n env,\n tenantId: config.tenant.id,\n inProgress: inProgress ?? null,\n history,\n };\n console.log(JSON.stringify(out, null, 2));\n return;\n }\n\n console.log(\n `\\nStack events — ${config.tenant.name} (${config.tenant.slug}) — stack \"${stackName}\" env ${env}\\n`,\n );\n\n if (inProgress) {\n console.log(\"In progress:\\n\");\n printOp(\"in_progress\", inProgress);\n }\n\n if (history.length === 0) {\n console.log(\n inProgress\n ? \"(no completed operations in history yet)\\n\"\n : \"No completed operations recorded in state yet.\\n\",\n );\n return;\n }\n\n console.log(\"Recent completed operations (newest first):\\n\");\n for (const op of history) {\n printOp(op.status, op);\n }\n}\n"],"mappings":";;;AAOA,SAAS,eACP,WACA,aACoB;AACpB,KAAI,CAAC,YAAa,QAAO;CACzB,MAAM,IAAI,KAAK,MAAM,UAAU;CAC/B,MAAM,IAAI,KAAK,MAAM,YAAY;AACjC,KAAI,CAAC,OAAO,SAAS,EAAE,IAAI,CAAC,OAAO,SAAS,EAAE,IAAI,IAAI,EAAG,QAAO;CAChE,MAAM,KAAK,IAAI;AACf,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG;AAC5B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;AAGnC,SAAS,QAAQ,OAAe,IAA8B;CAC5D,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,YAAY;AACxD,SAAQ,IAAI,MAAM,MAAM,IAAI,GAAG,UAAU;AACzC,SAAQ,IAAI,kBAAkB,GAAG,YAAY;AAC7C,KAAI,GAAG,YACL,SAAQ,IAAI,kBAAkB,GAAG,cAAc;AAEjD,KAAI,IAAK,SAAQ,IAAI,kBAAkB,MAAM;AAC7C,KAAI,GAAG,OAAQ,SAAQ,IAAI,kBAAkB,GAAG,SAAS;AACzD,KAAI,GAAG,aAAc,SAAQ,IAAI,kBAAkB,GAAG,eAAe;AACrE,SAAQ,KAAK;;;;;;AAOf,eAAsB,UAAU,SAKd;CAChB,MAAM,MAAM,QAAQ,OAAO;CAC3B,MAAM,SAAS,MAAM,WAAW,QAAQ,YAAY,EAAE,KAAK,CAAC;CAC5D,MAAM,YACJ,OAAO,cAAc,4BAA4B;AACnD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iEACD;CAEH,MAAM,YAAY,mBAAmB,OAAO;CAC5C,MAAM,MAAM,IAAI,YAAY,UAAU;CACtC,MAAM,QAAQ,IAAI,aAAa,OAAO,OAAO,IAAI,KAAK,UAAU;AAChE,OAAM,MAAM,QAAQ,IAAI;CAExB,MAAM,OAAO,MAAM,kBAAkB;CACrC,MAAM,aACJ,MAAM,WAAW,gBAAgB,OAAO;CAC1C,IAAI,UAAU,MAAM,qBAAqB;AACzC,KAAI,QAAQ,UAAU,OACpB,WAAU,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAG3C,KAAI,QAAQ,MAAM;EAChB,MAAM,MAAM;GACV;GACA;GACA,UAAU,OAAO,OAAO;GACxB,YAAY,cAAc;GAC1B;GACD;AACD,UAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,EAAE,CAAC;AACzC;;AAGF,SAAQ,IACN,oBAAoB,OAAO,OAAO,KAAK,IAAI,OAAO,OAAO,KAAK,aAAa,UAAU,QAAQ,IAAI,IAClG;AAED,KAAI,YAAY;AACd,UAAQ,IAAI,iBAAiB;AAC7B,UAAQ,eAAe,WAAW;;AAGpC,KAAI,QAAQ,WAAW,GAAG;AACxB,UAAQ,IACN,aACI,+CACA,mDACL;AACD;;AAGF,SAAQ,IAAI,gDAAgD;AAC5D,MAAK,MAAM,MAAM,QACf,SAAQ,GAAG,QAAQ,GAAG"}
1
+ {"version":3,"file":"events-Bor7XgLC.mjs","names":[],"sources":["../src/cli/commands/events.ts"],"sourcesContent":["import { loadConfig } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport type { CfiOperationRecord } from \"../../types.js\";\n\nfunction formatDuration(\n startedAt: string,\n completedAt: string | undefined,\n): string | undefined {\n if (!completedAt) return undefined;\n const a = Date.parse(startedAt);\n const b = Date.parse(completedAt);\n if (!Number.isFinite(a) || !Number.isFinite(b) || b < a) return undefined;\n const ms = b - a;\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction printOp(label: string, op: CfiOperationRecord): void {\n const dur = formatDuration(op.startedAt, op.completedAt);\n console.log(` [${label}] ${op.command}`);\n console.log(` started: ${op.startedAt}`);\n if (op.completedAt) {\n console.log(` completed: ${op.completedAt}`);\n }\n if (dur) console.log(` duration: ${dur}`);\n if (op.detail) console.log(` detail: ${op.detail}`);\n if (op.errorMessage) console.log(` error: ${op.errorMessage}`);\n console.log();\n}\n\n/**\n * Read-only: print recent completed stack operations from D1 state\n * (`operationHistory`) plus any in-progress marker (`lastOperation`).\n */\nexport async function runEvents(options: {\n env?: string;\n configPath?: string;\n limit?: number;\n json?: boolean;\n}): Promise<void> {\n const env = options.env ?? \"local\";\n const config = await loadConfig(options.configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n const stackName = stackNameForConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(config.tenant.id, env, stackName);\n await state.hydrate(api);\n\n const last = state.getLastOperation();\n const inProgress =\n last?.status === \"in_progress\" ? last : undefined;\n let history = state.getOperationHistory();\n if (options.limit !== undefined) {\n history = history.slice(0, options.limit);\n }\n\n if (options.json) {\n const out = {\n stackName,\n env,\n tenantId: config.tenant.id,\n inProgress: inProgress ?? null,\n history,\n };\n console.log(JSON.stringify(out, null, 2));\n return;\n }\n\n console.log(\n `\\nStack events — ${config.tenant.name} (${config.tenant.slug}) — stack \"${stackName}\" env ${env}\\n`,\n );\n\n if (inProgress) {\n console.log(\"In progress:\\n\");\n printOp(\"in_progress\", inProgress);\n }\n\n if (history.length === 0) {\n console.log(\n inProgress\n ? \"(no completed operations in history yet)\\n\"\n : \"No completed operations recorded in state yet.\\n\",\n );\n return;\n }\n\n console.log(\"Recent completed operations (newest first):\\n\");\n for (const op of history) {\n printOp(op.status, op);\n }\n}\n"],"mappings":";;;AAOA,SAAS,eACP,WACA,aACoB;AACpB,KAAI,CAAC,YAAa,QAAO;CACzB,MAAM,IAAI,KAAK,MAAM,UAAU;CAC/B,MAAM,IAAI,KAAK,MAAM,YAAY;AACjC,KAAI,CAAC,OAAO,SAAS,EAAE,IAAI,CAAC,OAAO,SAAS,EAAE,IAAI,IAAI,EAAG,QAAO;CAChE,MAAM,KAAK,IAAI;AACf,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG;AAC5B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;AAGnC,SAAS,QAAQ,OAAe,IAA8B;CAC5D,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,YAAY;AACxD,SAAQ,IAAI,MAAM,MAAM,IAAI,GAAG,UAAU;AACzC,SAAQ,IAAI,kBAAkB,GAAG,YAAY;AAC7C,KAAI,GAAG,YACL,SAAQ,IAAI,kBAAkB,GAAG,cAAc;AAEjD,KAAI,IAAK,SAAQ,IAAI,kBAAkB,MAAM;AAC7C,KAAI,GAAG,OAAQ,SAAQ,IAAI,kBAAkB,GAAG,SAAS;AACzD,KAAI,GAAG,aAAc,SAAQ,IAAI,kBAAkB,GAAG,eAAe;AACrE,SAAQ,KAAK;;;;;;AAOf,eAAsB,UAAU,SAKd;CAChB,MAAM,MAAM,QAAQ,OAAO;CAC3B,MAAM,SAAS,MAAM,WAAW,QAAQ,YAAY,EAAE,KAAK,CAAC;CAC5D,MAAM,YACJ,OAAO,cAAc,4BAA4B;AACnD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iEACD;CAEH,MAAM,YAAY,mBAAmB,OAAO;CAC5C,MAAM,MAAM,IAAI,YAAY,UAAU;CACtC,MAAM,QAAQ,IAAI,aAAa,OAAO,OAAO,IAAI,KAAK,UAAU;AAChE,OAAM,MAAM,QAAQ,IAAI;CAExB,MAAM,OAAO,MAAM,kBAAkB;CACrC,MAAM,aACJ,MAAM,WAAW,gBAAgB,OAAO;CAC1C,IAAI,UAAU,MAAM,qBAAqB;AACzC,KAAI,QAAQ,UAAU,OACpB,WAAU,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAG3C,KAAI,QAAQ,MAAM;EAChB,MAAM,MAAM;GACV;GACA;GACA,UAAU,OAAO,OAAO;GACxB,YAAY,cAAc;GAC1B;GACD;AACD,UAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,EAAE,CAAC;AACzC;;AAGF,SAAQ,IACN,oBAAoB,OAAO,OAAO,KAAK,IAAI,OAAO,OAAO,KAAK,aAAa,UAAU,QAAQ,IAAI,IAClG;AAED,KAAI,YAAY;AACd,UAAQ,IAAI,iBAAiB;AAC7B,UAAQ,eAAe,WAAW;;AAGpC,KAAI,QAAQ,WAAW,GAAG;AACxB,UAAQ,IACN,aACI,+CACA,mDACL;AACD;;AAGF,SAAQ,IAAI,gDAAgD;AAC5D,MAAK,MAAM,MAAM,QACf,SAAQ,GAAG,QAAQ,GAAG"}
@@ -1,4 +1,4 @@
1
- import { B as getWorkers, C as stackNameForConfig, L as CFApiClient, O as resolveWorkerConfig, P as namingFromConfig, R as cloudflareAccountIdFromEnv, V as loadConfig, d as fetchStackImports, m as StateManager } from "./tamer.mjs";
1
+ import { B as getWorkers, L as CFApiClient, R as cloudflareAccountIdFromEnv, V as loadConfig, f as fetchStackImports, h as StateManager, k as resolveWorkerConfig, u as namingFromConfig, w as stackNameForConfig } from "./tamer.mjs";
2
2
  import { n as resourceModules, t as getResourceModule } from "./registry-EWWdkLf7.mjs";
3
3
  import "./r2S3EmptyBucket-B9_pHfvB.mjs";
4
4
  import { n as workerRouteStateKey, t as findZoneIdByName } from "./zoneResolver-DNNNmO_w.mjs";
@@ -161,4 +161,4 @@ async function importWorkerRoute(ctx) {
161
161
 
162
162
  //#endregion
163
163
  export { runImport };
164
- //# sourceMappingURL=import-OvohE-H2.mjs.map
164
+ //# sourceMappingURL=import-Vn9lhWic.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-OvohE-H2.mjs","names":[],"sources":["../src/cli/commands/import.ts"],"sourcesContent":["import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { workerRouteStateKey } from \"../../features/worker-route/worker-route.stateKey.js\";\nimport { findZoneIdByName } from \"../../core/routes/zoneResolver.js\";\nimport {\n getResourceModule,\n resourceModules,\n type ResourceKind,\n} from \"../../core/registry/registry.js\";\n\n/** All registered resource kinds plus the non-registry imports. */\nexport type ImportKind =\n | ResourceKind\n | \"dispatch_namespace\"\n | \"dns_record\"\n | \"worker_route\";\n\nexport interface ImportOptions {\n env: string;\n kind: ImportKind;\n /** Logical name from `tamer.config.ts` (or worker key, for `worker_route`). */\n logical: string;\n /** Cloudflare resource id (D1 uuid, KV id, R2 bucket name, or namespace name). */\n cfId?: string;\n /** Required for sharded D1 imports (YYYY-MM-DD). */\n shardDate?: string;\n /** R2 buckets only: creation date (YYYY-MM-DD) used in the binding key. */\n createdDate?: string;\n /** worker_route only: the route id from `/zones/{id}/workers/routes`. */\n routeId?: string;\n /** worker_route only: zone name from `tamerRoutes`. */\n zoneName?: string;\n configPath?: string;\n}\n\nconst REGISTRY_KINDS = new Set<string>(resourceModules.map((m) => m.kind));\n\n/**\n * `tamer import` — register an existing Cloudflare resource into Tamer state\n * by logical name (CloudFormation `import_resources` analogue). For all\n * resource-registry kinds the work is delegated to the module's\n * `importOne` hook; `dispatch_namespace` and `worker_route` remain inline\n * because they aren't registry resources today.\n */\nexport async function runImport(options: ImportOptions): Promise<void> {\n const env = options.env;\n if (env === \"local\") {\n throw new Error(\"import: --env local is not supported (no persisted state)\");\n }\n const baseDir = process.cwd();\n const config = await loadConfig(options.configPath, { env });\n const accountId = config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n const api = new CFApiClient(accountId);\n const naming = namingFromConfig(config);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n state.beginOperation(\"import\", `${options.kind}:${options.logical}`);\n\n const ts = new Date().toISOString();\n\n try {\n if (REGISTRY_KINDS.has(options.kind)) {\n const mod = getResourceModule(options.kind as ResourceKind);\n if (!mod) throw new Error(`unknown import kind \"${options.kind}\"`);\n await mod.importOne({\n options: {\n env,\n kind: options.kind,\n logical: options.logical,\n cfId: options.cfId,\n shardDate: options.shardDate,\n createdDate: options.createdDate,\n routeId: options.routeId,\n zoneName: options.zoneName,\n },\n env,\n api,\n state,\n naming,\n config,\n baseDir,\n ts,\n });\n } else if (options.kind === \"dispatch_namespace\") {\n await importDispatchNamespace({ options, env, api, state, ts });\n } else if (options.kind === \"dns_record\") {\n await importDnsRecord({ options, env, api, state, config, ts });\n } else if (options.kind === \"worker_route\") {\n await importWorkerRoute({\n options,\n env,\n baseDir,\n accountId,\n api,\n naming,\n state,\n config,\n ts,\n });\n } else {\n throw new Error(`unknown import kind \"${options.kind}\"`);\n }\n\n state.finishOperation(\"imported\");\n await state.persist(api);\n console.log(`Imported ${options.kind} \"${options.logical}\" into ${env} state.`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n state.failOperation(msg);\n try {\n await state.persist(api);\n } catch {\n /* swallow secondary persist failure */\n }\n throw err;\n }\n}\n\nasync function importDispatchNamespace(ctx: {\n options: ImportOptions;\n env: string;\n api: CFApiClient;\n state: StateManager;\n ts: string;\n}): Promise<void> {\n const { options, api, state, ts } = ctx;\n const namespaces = await api.dispatchNamespaceListAll();\n const hit = namespaces.find((n) => n.namespace_name === options.cfId);\n if (!hit) {\n throw new Error(\n `import dispatch_namespace: namespace \"${options.cfId}\" not found`,\n );\n }\n const derivedName = hit.namespace_name;\n const key = `dispatch_ns:${derivedName}`;\n const existing = state.get(key);\n state.set(key, {\n type: \"dispatch_namespace\",\n logicalName: options.logical,\n derivedName,\n createdAt:\n existing?.type === \"dispatch_namespace\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n\nasync function importDnsRecord(ctx: {\n options: ImportOptions;\n env: string;\n api: CFApiClient;\n state: StateManager;\n config: Awaited<ReturnType<typeof loadConfig>>;\n ts: string;\n}): Promise<void> {\n const { options, api, state, config, ts } = ctx;\n if (!options.cfId) {\n throw new Error(\n \"import dns_record: --cf-id <recordId> is required (the record id from `tamer drift` or the Cloudflare dashboard URL)\",\n );\n }\n const declared = (config.dnsRecords ?? []).find(\n (r) => r.logicalName === options.logical,\n );\n if (!declared) {\n throw new Error(\n `import dns_record: no dnsRecords entry with logicalName \"${options.logical}\" in the Tamer project config`,\n );\n }\n const list = await api.zoneDnsRecordListAll(declared.zoneId);\n const hit = list.find((r) => r.id === options.cfId);\n if (!hit) {\n throw new Error(\n `import dns_record: record id \"${options.cfId}\" not found in zone \"${declared.zoneId}\"`,\n );\n }\n if (hit.type !== declared.type) {\n throw new Error(\n `import dns_record: cf record type \"${hit.type}\" does not match declared type \"${declared.type}\"`,\n );\n }\n const { dnsRecordStateKey } = await import(\n \"../../features/dns-records/dns-records.resolve.js\"\n );\n const key = dnsRecordStateKey(declared.zoneId, declared.type, declared.name);\n const existing = state.get(key);\n state.set(key, {\n type: \"dns_record\",\n logicalName: options.logical,\n zoneId: declared.zoneId,\n recordType: declared.type,\n name: hit.name,\n content: hit.content,\n ttl: hit.ttl ?? 1,\n proxied: hit.proxied ?? false,\n priority: hit.priority,\n comment: hit.comment ?? \"\",\n recordId: hit.id,\n createdAt: existing?.type === \"dns_record\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n\nasync function importWorkerRoute(ctx: {\n options: ImportOptions;\n env: string;\n baseDir: string;\n accountId: string;\n api: CFApiClient;\n naming: ReturnType<typeof namingFromConfig>;\n state: StateManager;\n config: Awaited<ReturnType<typeof loadConfig>>;\n ts: string;\n}): Promise<void> {\n const { options, env, baseDir, accountId, api, naming, state, config, ts } =\n ctx;\n if (!options.routeId) {\n throw new Error(\"import worker_route: --route-id <id> is required\");\n }\n const workers = await getWorkers(config, baseDir);\n const wc = workers.find(([k]) => k === options.logical)?.[1];\n if (!wc) {\n throw new Error(\n `import worker_route: no worker key \"${options.logical}\" in the Tamer project config`,\n );\n }\n const imports = await fetchStackImports(api, config, env);\n const resolved = await resolveWorkerConfig(\n config,\n options.logical,\n wc,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n if (resolved.apiManagedRoutes.length === 0) {\n throw new Error(\n `import worker_route: worker \"${options.logical}\" declares no api-managed tamerRoutes for env ${env}`,\n );\n }\n\n const route = options.zoneName\n ? resolved.apiManagedRoutes.find((r) => r.zone_name === options.zoneName)\n : resolved.apiManagedRoutes[0];\n if (!route) {\n throw new Error(\n `import worker_route: no route for zone \"${options.zoneName}\" in resolved config`,\n );\n }\n const zoneId = await findZoneIdByName(api, route.zone_name);\n if (!zoneId) {\n throw new Error(`import worker_route: zone \"${route.zone_name}\" not found`);\n }\n const list = await api.zoneWorkerRoutesList(zoneId);\n const hit = list.find((r) => r.id === options.routeId);\n if (!hit) {\n throw new Error(\n `import worker_route: route id \"${options.routeId}\" not found in zone \"${route.zone_name}\"`,\n );\n }\n if (hit.pattern !== route.pattern) {\n throw new Error(\n `import worker_route: cf pattern \"${hit.pattern}\" does not match resolved \"${route.pattern}\"`,\n );\n }\n const key = workerRouteStateKey(zoneId, options.routeId);\n const existing = state.get(key);\n state.set(key, {\n type: \"worker_route\",\n workerKey: options.logical,\n workerName: resolved.workerName,\n zoneId,\n zoneName: route.zone_name,\n routeId: options.routeId,\n pattern: route.pattern,\n createdAt: existing?.type === \"worker_route\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"import-Vn9lhWic.mjs","names":[],"sources":["../src/cli/commands/import.ts"],"sourcesContent":["import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { workerRouteStateKey } from \"../../features/worker-route/worker-route.stateKey.js\";\nimport { findZoneIdByName } from \"../../core/routes/zoneResolver.js\";\nimport {\n getResourceModule,\n resourceModules,\n type ResourceKind,\n} from \"../../core/registry/registry.js\";\n\n/** All registered resource kinds plus the non-registry imports. */\nexport type ImportKind =\n | ResourceKind\n | \"dispatch_namespace\"\n | \"dns_record\"\n | \"worker_route\";\n\nexport interface ImportOptions {\n env: string;\n kind: ImportKind;\n /** Logical name from `tamer.config.ts` (or worker key, for `worker_route`). */\n logical: string;\n /** Cloudflare resource id (D1 uuid, KV id, R2 bucket name, or namespace name). */\n cfId?: string;\n /** Required for sharded D1 imports (YYYY-MM-DD). */\n shardDate?: string;\n /** R2 buckets only: creation date (YYYY-MM-DD) used in the binding key. */\n createdDate?: string;\n /** worker_route only: the route id from `/zones/{id}/workers/routes`. */\n routeId?: string;\n /** worker_route only: zone name from `tamerRoutes`. */\n zoneName?: string;\n configPath?: string;\n}\n\nconst REGISTRY_KINDS = new Set<string>(resourceModules.map((m) => m.kind));\n\n/**\n * `tamer import` — register an existing Cloudflare resource into Tamer state\n * by logical name (CloudFormation `import_resources` analogue). For all\n * resource-registry kinds the work is delegated to the module's\n * `importOne` hook; `dispatch_namespace` and `worker_route` remain inline\n * because they aren't registry resources today.\n */\nexport async function runImport(options: ImportOptions): Promise<void> {\n const env = options.env;\n if (env === \"local\") {\n throw new Error(\"import: --env local is not supported (no persisted state)\");\n }\n const baseDir = process.cwd();\n const config = await loadConfig(options.configPath, { env });\n const accountId = config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n const api = new CFApiClient(accountId);\n const naming = namingFromConfig(config);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n state.beginOperation(\"import\", `${options.kind}:${options.logical}`);\n\n const ts = new Date().toISOString();\n\n try {\n if (REGISTRY_KINDS.has(options.kind)) {\n const mod = getResourceModule(options.kind as ResourceKind);\n if (!mod) throw new Error(`unknown import kind \"${options.kind}\"`);\n await mod.importOne({\n options: {\n env,\n kind: options.kind,\n logical: options.logical,\n cfId: options.cfId,\n shardDate: options.shardDate,\n createdDate: options.createdDate,\n routeId: options.routeId,\n zoneName: options.zoneName,\n },\n env,\n api,\n state,\n naming,\n config,\n baseDir,\n ts,\n });\n } else if (options.kind === \"dispatch_namespace\") {\n await importDispatchNamespace({ options, env, api, state, ts });\n } else if (options.kind === \"dns_record\") {\n await importDnsRecord({ options, env, api, state, config, ts });\n } else if (options.kind === \"worker_route\") {\n await importWorkerRoute({\n options,\n env,\n baseDir,\n accountId,\n api,\n naming,\n state,\n config,\n ts,\n });\n } else {\n throw new Error(`unknown import kind \"${options.kind}\"`);\n }\n\n state.finishOperation(\"imported\");\n await state.persist(api);\n console.log(`Imported ${options.kind} \"${options.logical}\" into ${env} state.`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n state.failOperation(msg);\n try {\n await state.persist(api);\n } catch {\n /* swallow secondary persist failure */\n }\n throw err;\n }\n}\n\nasync function importDispatchNamespace(ctx: {\n options: ImportOptions;\n env: string;\n api: CFApiClient;\n state: StateManager;\n ts: string;\n}): Promise<void> {\n const { options, api, state, ts } = ctx;\n const namespaces = await api.dispatchNamespaceListAll();\n const hit = namespaces.find((n) => n.namespace_name === options.cfId);\n if (!hit) {\n throw new Error(\n `import dispatch_namespace: namespace \"${options.cfId}\" not found`,\n );\n }\n const derivedName = hit.namespace_name;\n const key = `dispatch_ns:${derivedName}`;\n const existing = state.get(key);\n state.set(key, {\n type: \"dispatch_namespace\",\n logicalName: options.logical,\n derivedName,\n createdAt:\n existing?.type === \"dispatch_namespace\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n\nasync function importDnsRecord(ctx: {\n options: ImportOptions;\n env: string;\n api: CFApiClient;\n state: StateManager;\n config: Awaited<ReturnType<typeof loadConfig>>;\n ts: string;\n}): Promise<void> {\n const { options, api, state, config, ts } = ctx;\n if (!options.cfId) {\n throw new Error(\n \"import dns_record: --cf-id <recordId> is required (the record id from `tamer drift` or the Cloudflare dashboard URL)\",\n );\n }\n const declared = (config.dnsRecords ?? []).find(\n (r) => r.logicalName === options.logical,\n );\n if (!declared) {\n throw new Error(\n `import dns_record: no dnsRecords entry with logicalName \"${options.logical}\" in the Tamer project config`,\n );\n }\n const list = await api.zoneDnsRecordListAll(declared.zoneId);\n const hit = list.find((r) => r.id === options.cfId);\n if (!hit) {\n throw new Error(\n `import dns_record: record id \"${options.cfId}\" not found in zone \"${declared.zoneId}\"`,\n );\n }\n if (hit.type !== declared.type) {\n throw new Error(\n `import dns_record: cf record type \"${hit.type}\" does not match declared type \"${declared.type}\"`,\n );\n }\n const { dnsRecordStateKey } = await import(\n \"../../features/dns-records/dns-records.resolve.js\"\n );\n const key = dnsRecordStateKey(declared.zoneId, declared.type, declared.name);\n const existing = state.get(key);\n state.set(key, {\n type: \"dns_record\",\n logicalName: options.logical,\n zoneId: declared.zoneId,\n recordType: declared.type,\n name: hit.name,\n content: hit.content,\n ttl: hit.ttl ?? 1,\n proxied: hit.proxied ?? false,\n priority: hit.priority,\n comment: hit.comment ?? \"\",\n recordId: hit.id,\n createdAt: existing?.type === \"dns_record\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n\nasync function importWorkerRoute(ctx: {\n options: ImportOptions;\n env: string;\n baseDir: string;\n accountId: string;\n api: CFApiClient;\n naming: ReturnType<typeof namingFromConfig>;\n state: StateManager;\n config: Awaited<ReturnType<typeof loadConfig>>;\n ts: string;\n}): Promise<void> {\n const { options, env, baseDir, accountId, api, naming, state, config, ts } =\n ctx;\n if (!options.routeId) {\n throw new Error(\"import worker_route: --route-id <id> is required\");\n }\n const workers = await getWorkers(config, baseDir);\n const wc = workers.find(([k]) => k === options.logical)?.[1];\n if (!wc) {\n throw new Error(\n `import worker_route: no worker key \"${options.logical}\" in the Tamer project config`,\n );\n }\n const imports = await fetchStackImports(api, config, env);\n const resolved = await resolveWorkerConfig(\n config,\n options.logical,\n wc,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n if (resolved.apiManagedRoutes.length === 0) {\n throw new Error(\n `import worker_route: worker \"${options.logical}\" declares no api-managed tamerRoutes for env ${env}`,\n );\n }\n\n const route = options.zoneName\n ? resolved.apiManagedRoutes.find((r) => r.zone_name === options.zoneName)\n : resolved.apiManagedRoutes[0];\n if (!route) {\n throw new Error(\n `import worker_route: no route for zone \"${options.zoneName}\" in resolved config`,\n );\n }\n const zoneId = await findZoneIdByName(api, route.zone_name);\n if (!zoneId) {\n throw new Error(`import worker_route: zone \"${route.zone_name}\" not found`);\n }\n const list = await api.zoneWorkerRoutesList(zoneId);\n const hit = list.find((r) => r.id === options.routeId);\n if (!hit) {\n throw new Error(\n `import worker_route: route id \"${options.routeId}\" not found in zone \"${route.zone_name}\"`,\n );\n }\n if (hit.pattern !== route.pattern) {\n throw new Error(\n `import worker_route: cf pattern \"${hit.pattern}\" does not match resolved \"${route.pattern}\"`,\n );\n }\n const key = workerRouteStateKey(zoneId, options.routeId);\n const existing = state.get(key);\n state.set(key, {\n type: \"worker_route\",\n workerKey: options.logical,\n workerName: resolved.workerName,\n zoneId,\n zoneName: route.zone_name,\n routeId: options.routeId,\n pattern: route.pattern,\n createdAt: existing?.type === \"worker_route\" ? existing.createdAt : ts,\n updatedAt: ts,\n });\n}\n"],"mappings":";;;;;;AAyCA,MAAM,iBAAiB,IAAI,IAAY,gBAAgB,KAAK,MAAM,EAAE,KAAK,CAAC;;;;;;;;AAS1E,eAAsB,UAAU,SAAuC;CACrE,MAAM,MAAM,QAAQ;AACpB,KAAI,QAAQ,QACV,OAAM,IAAI,MAAM,4DAA4D;CAE9E,MAAM,UAAU,QAAQ,KAAK;CAC7B,MAAM,SAAS,MAAM,WAAW,QAAQ,YAAY,EAAE,KAAK,CAAC;CAC5D,MAAM,YAAY,OAAO,cAAc,4BAA4B;AACnE,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iEACD;CAEH,MAAM,MAAM,IAAI,YAAY,UAAU;CACtC,MAAM,SAAS,iBAAiB,OAAO;CACvC,MAAM,QAAQ,IAAI,aAChB,OAAO,OAAO,IACd,KACA,mBAAmB,OAAO,CAC3B;AACD,OAAM,MAAM,QAAQ,IAAI;AACxB,OAAM,eAAe,UAAU,GAAG,QAAQ,KAAK,GAAG,QAAQ,UAAU;CAEpE,MAAM,sBAAK,IAAI,MAAM,EAAC,aAAa;AAEnC,KAAI;AACF,MAAI,eAAe,IAAI,QAAQ,KAAK,EAAE;GACpC,MAAM,MAAM,kBAAkB,QAAQ,KAAqB;AAC3D,OAAI,CAAC,IAAK,OAAM,IAAI,MAAM,wBAAwB,QAAQ,KAAK,GAAG;AAClE,SAAM,IAAI,UAAU;IAClB,SAAS;KACP;KACA,MAAM,QAAQ;KACd,SAAS,QAAQ;KACjB,MAAM,QAAQ;KACd,WAAW,QAAQ;KACnB,aAAa,QAAQ;KACrB,SAAS,QAAQ;KACjB,UAAU,QAAQ;KACnB;IACD;IACA;IACA;IACA;IACA;IACA;IACA;IACD,CAAC;aACO,QAAQ,SAAS,qBAC1B,OAAM,wBAAwB;GAAE;GAAS;GAAK;GAAK;GAAO;GAAI,CAAC;WACtD,QAAQ,SAAS,aAC1B,OAAM,gBAAgB;GAAE;GAAS;GAAK;GAAK;GAAO;GAAQ;GAAI,CAAC;WACtD,QAAQ,SAAS,eAC1B,OAAM,kBAAkB;GACtB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;MAEF,OAAM,IAAI,MAAM,wBAAwB,QAAQ,KAAK,GAAG;AAG1D,QAAM,gBAAgB,WAAW;AACjC,QAAM,MAAM,QAAQ,IAAI;AACxB,UAAQ,IAAI,YAAY,QAAQ,KAAK,IAAI,QAAQ,QAAQ,SAAS,IAAI,SAAS;UACxE,KAAK;EACZ,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,QAAM,cAAc,IAAI;AACxB,MAAI;AACF,SAAM,MAAM,QAAQ,IAAI;UAClB;AAGR,QAAM;;;AAIV,eAAe,wBAAwB,KAMrB;CAChB,MAAM,EAAE,SAAS,KAAK,OAAO,OAAO;CAEpC,MAAM,OADa,MAAM,IAAI,0BAA0B,EAChC,MAAM,MAAM,EAAE,mBAAmB,QAAQ,KAAK;AACrE,KAAI,CAAC,IACH,OAAM,IAAI,MACR,yCAAyC,QAAQ,KAAK,aACvD;CAEH,MAAM,cAAc,IAAI;CACxB,MAAM,MAAM,eAAe;CAC3B,MAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,OAAM,IAAI,KAAK;EACb,MAAM;EACN,aAAa,QAAQ;EACrB;EACA,WACE,UAAU,SAAS,uBAAuB,SAAS,YAAY;EACjE,WAAW;EACZ,CAAC;;AAGJ,eAAe,gBAAgB,KAOb;CAChB,MAAM,EAAE,SAAS,KAAK,OAAO,QAAQ,OAAO;AAC5C,KAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MACR,uHACD;CAEH,MAAM,YAAY,OAAO,cAAc,EAAE,EAAE,MACxC,MAAM,EAAE,gBAAgB,QAAQ,QAClC;AACD,KAAI,CAAC,SACH,OAAM,IAAI,MACR,4DAA4D,QAAQ,QAAQ,+BAC7E;CAGH,MAAM,OADO,MAAM,IAAI,qBAAqB,SAAS,OAAO,EAC3C,MAAM,MAAM,EAAE,OAAO,QAAQ,KAAK;AACnD,KAAI,CAAC,IACH,OAAM,IAAI,MACR,iCAAiC,QAAQ,KAAK,uBAAuB,SAAS,OAAO,GACtF;AAEH,KAAI,IAAI,SAAS,SAAS,KACxB,OAAM,IAAI,MACR,sCAAsC,IAAI,KAAK,kCAAkC,SAAS,KAAK,GAChG;CAEH,MAAM,EAAE,sBAAsB,MAAM,OAClC;CAEF,MAAM,MAAM,kBAAkB,SAAS,QAAQ,SAAS,MAAM,SAAS,KAAK;CAC5E,MAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,OAAM,IAAI,KAAK;EACb,MAAM;EACN,aAAa,QAAQ;EACrB,QAAQ,SAAS;EACjB,YAAY,SAAS;EACrB,MAAM,IAAI;EACV,SAAS,IAAI;EACb,KAAK,IAAI,OAAO;EAChB,SAAS,IAAI,WAAW;EACxB,UAAU,IAAI;EACd,SAAS,IAAI,WAAW;EACxB,UAAU,IAAI;EACd,WAAW,UAAU,SAAS,eAAe,SAAS,YAAY;EAClE,WAAW;EACZ,CAAC;;AAGJ,eAAe,kBAAkB,KAUf;CAChB,MAAM,EAAE,SAAS,KAAK,SAAS,WAAW,KAAK,QAAQ,OAAO,QAAQ,OACpE;AACF,KAAI,CAAC,QAAQ,QACX,OAAM,IAAI,MAAM,mDAAmD;CAGrE,MAAM,MADU,MAAM,WAAW,QAAQ,QAAQ,EAC9B,MAAM,CAAC,OAAO,MAAM,QAAQ,QAAQ,GAAG;AAC1D,KAAI,CAAC,GACH,OAAM,IAAI,MACR,uCAAuC,QAAQ,QAAQ,+BACxD;CAEH,MAAM,UAAU,MAAM,kBAAkB,KAAK,QAAQ,IAAI;CACzD,MAAM,WAAW,MAAM,oBACrB,QACA,QAAQ,SACR,IACA,KACA,SACA,WACA,QACA,OACA,EAAE,SAAS,CACZ;AACD,KAAI,SAAS,iBAAiB,WAAW,EACvC,OAAM,IAAI,MACR,gCAAgC,QAAQ,QAAQ,gDAAgD,MACjG;CAGH,MAAM,QAAQ,QAAQ,WAClB,SAAS,iBAAiB,MAAM,MAAM,EAAE,cAAc,QAAQ,SAAS,GACvE,SAAS,iBAAiB;AAC9B,KAAI,CAAC,MACH,OAAM,IAAI,MACR,2CAA2C,QAAQ,SAAS,sBAC7D;CAEH,MAAM,SAAS,MAAM,iBAAiB,KAAK,MAAM,UAAU;AAC3D,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,8BAA8B,MAAM,UAAU,aAAa;CAG7E,MAAM,OADO,MAAM,IAAI,qBAAqB,OAAO,EAClC,MAAM,MAAM,EAAE,OAAO,QAAQ,QAAQ;AACtD,KAAI,CAAC,IACH,OAAM,IAAI,MACR,kCAAkC,QAAQ,QAAQ,uBAAuB,MAAM,UAAU,GAC1F;AAEH,KAAI,IAAI,YAAY,MAAM,QACxB,OAAM,IAAI,MACR,oCAAoC,IAAI,QAAQ,6BAA6B,MAAM,QAAQ,GAC5F;CAEH,MAAM,MAAM,oBAAoB,QAAQ,QAAQ,QAAQ;CACxD,MAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,OAAM,IAAI,KAAK;EACb,MAAM;EACN,WAAW,QAAQ;EACnB,YAAY,SAAS;EACrB;EACA,UAAU,MAAM;EAChB,SAAS,QAAQ;EACjB,SAAS,MAAM;EACf,WAAW,UAAU,SAAS,iBAAiB,SAAS,YAAY;EACpE,WAAW;EACZ,CAAC"}
@@ -1,4 +1,4 @@
1
- import { B as getWorkers, C as stackNameForConfig, L as CFApiClient, O as resolveWorkerConfig, P as namingFromConfig, R as cloudflareAccountIdFromEnv, V as loadConfig, d as fetchStackImports, j as wranglerConfigCliArgs, m as StateManager } from "./tamer.mjs";
1
+ import { B as getWorkers, L as CFApiClient, M as wranglerConfigCliArgs, R as cloudflareAccountIdFromEnv, V as loadConfig, f as fetchStackImports, h as StateManager, k as resolveWorkerConfig, u as namingFromConfig, w as stackNameForConfig } from "./tamer.mjs";
2
2
  import { a as d1CloudflareDatabaseName, o as d1SkipsProvisionAndMigrate } from "./registry-EWWdkLf7.mjs";
3
3
  import "./r2S3EmptyBucket-B9_pHfvB.mjs";
4
4
  import { n as writeWranglerJson, t as generateWranglerConfig } from "./generator-gvCy7ouY.mjs";
@@ -82,4 +82,4 @@ async function runMigrate(options) {
82
82
 
83
83
  //#endregion
84
84
  export { runMigrate };
85
- //# sourceMappingURL=migrate-CroDjbJz.mjs.map
85
+ //# sourceMappingURL=migrate-skvsDG6d.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-CroDjbJz.mjs","names":["databases: string[]"],"sources":["../src/features/d1/d1.migrate.ts","../src/cli/commands/migrate.ts"],"sourcesContent":["import type { D1ResourceConfig, D1StateEntry } from \"./d1.types.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { spawnWranglerSync } from \"../../core/wrangler/wranglerSpawn.js\";\nimport type { NamingEngine } from \"../../core/naming/NamingEngine.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport {\n d1CloudflareDatabaseName,\n d1SkipsProvisionAndMigrate,\n} from \"./d1.ownership.js\";\n\n/**\n * Apply Cloudflare D1 migrations for every D1 in `resources`.\n *\n * Wrangler requires `d1 migrations apply <DATABASE>` (positional). Tamer\n * resolves the derived database name per env (single) or per shard, and\n * invokes wrangler once per database.\n *\n * Adds `--remote` for non-`local` envs so migrations target the live D1, not\n * the local SQLite cache. Skips D1s owned externally or flagged\n * `preserveOnDestroy` (cross-stack).\n */\nexport async function d1Migrate(\n resources: D1ResourceConfig[],\n workerDir: string,\n env: string,\n wranglerOutFile: string = \"wrangler.json\",\n naming: NamingEngine,\n state: StateManager,\n): Promise<void> {\n const d1Configs = resources.filter(\n (r) => r.migrationsDir && !d1SkipsProvisionAndMigrate(r),\n );\n if (d1Configs.length === 0) return;\n\n const databases: string[] = [];\n for (const config of d1Configs) {\n if (config.type === \"single\") {\n databases.push(d1CloudflareDatabaseName(config, env, naming));\n continue;\n }\n const all = state.getAll();\n const shards = Object.values(all).filter(\n (e): e is D1StateEntry =>\n e.type === \"d1_database\" && e.logicalName === config.logicalName,\n );\n for (const s of shards) databases.push(s.derivedName);\n }\n\n for (const dbName of databases) {\n const args = [\n \"wrangler\",\n ...wranglerConfigCliArgs(wranglerOutFile),\n \"d1\",\n \"migrations\",\n \"apply\",\n dbName,\n ];\n if (env !== \"local\") args.push(\"--remote\");\n\n // Wrangler prompts for confirmation when stdin is a TTY. Tamer is an\n // automation path (CI / scripts): skip prompts like `d1 migrations apply`\n // does when `CI` is set or stdin is not a TTY (see wrangler help text).\n const result = spawnWranglerSync(args, {\n cwd: workerDir,\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n env: { CI: \"1\" },\n });\n\n if (result.status !== 0) {\n throw new Error(\n `wrangler d1 migrations apply failed for ${dbName} (exit ${result.status})`,\n );\n }\n }\n}\n","import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { d1Migrate } from \"../../features/d1/index.js\";\n\nexport async function runMigrate(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n}): Promise<void> {\n const workerFilter = options.worker;\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const naming = namingFromConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n const imports = await fetchStackImports(api, config, env);\n\n const workers = await getWorkers(config, baseDir);\n const toRun = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toRun.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n for (const [workerKey, workerConfig] of toRun) {\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const wranglerConfig = generateWranglerConfig(resolved, state, naming);\n writeWranglerJson(resolved.workerDir, wranglerConfig, resolved.wranglerOutFile);\n\n const resources = resolved.resources ?? {};\n await d1Migrate(\n resources.d1 ?? [],\n resolved.workerDir,\n env,\n resolved.wranglerOutFile,\n naming,\n state,\n );\n console.log(`Migrations applied for ${workerKey}`);\n }\n\n console.log(`Migrate complete for env: ${env}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,eAAsB,UACpB,WACA,WACA,KACA,kBAA0B,iBAC1B,QACA,OACe;CACf,MAAM,YAAY,UAAU,QACzB,MAAM,EAAE,iBAAiB,CAAC,2BAA2B,EAAE,CACzD;AACD,KAAI,UAAU,WAAW,EAAG;CAE5B,MAAMA,YAAsB,EAAE;AAC9B,MAAK,MAAM,UAAU,WAAW;AAC9B,MAAI,OAAO,SAAS,UAAU;AAC5B,aAAU,KAAK,yBAAyB,QAAQ,KAAK,OAAO,CAAC;AAC7D;;EAEF,MAAM,MAAM,MAAM,QAAQ;EAC1B,MAAM,SAAS,OAAO,OAAO,IAAI,CAAC,QAC/B,MACC,EAAE,SAAS,iBAAiB,EAAE,gBAAgB,OAAO,YACxD;AACD,OAAK,MAAM,KAAK,OAAQ,WAAU,KAAK,EAAE,YAAY;;AAGvD,MAAK,MAAM,UAAU,WAAW;EAC9B,MAAM,OAAO;GACX;GACA,GAAG,sBAAsB,gBAAgB;GACzC;GACA;GACA;GACA;GACD;AACD,MAAI,QAAQ,QAAS,MAAK,KAAK,WAAW;EAK1C,MAAM,SAAS,kBAAkB,MAAM;GACrC,KAAK;GACL,OAAO;IAAC;IAAU;IAAW;IAAU;GACvC,KAAK,EAAE,IAAI,KAAK;GACjB,CAAC;AAEF,MAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MACR,2CAA2C,OAAO,SAAS,OAAO,OAAO,GAC1E;;;;;;ACzDP,eAAsB,WAAW,SAIf;CAChB,MAAM,eAAe,QAAQ;CAC7B,MAAM,MAAM,QAAQ,OAAO;CAC3B,MAAM,aAAa,QAAQ;CAC3B,MAAM,UAAU,QAAQ,KAAK;CAE7B,MAAM,SAAS,MAAM,WAAW,YAAY,EAAE,KAAK,CAAC;CACpD,MAAM,YACJ,OAAO,cAAc,4BAA4B;AACnD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iEACD;CAGH,MAAM,SAAS,iBAAiB,OAAO;CACvC,MAAM,MAAM,IAAI,YAAY,UAAU;CACtC,MAAM,QAAQ,IAAI,aAChB,OAAO,OAAO,IACd,KACA,mBAAmB,OAAO,CAC3B;AACD,OAAM,MAAM,QAAQ,IAAI;CACxB,MAAM,UAAU,MAAM,kBAAkB,KAAK,QAAQ,IAAI;CAEzD,MAAM,UAAU,MAAM,WAAW,QAAQ,QAAQ;CACjD,MAAM,QAAQ,eACV,QAAQ,QAAQ,CAAC,OAAO,MAAM,aAAa,GAC3C;AAEJ,KAAI,MAAM,WAAW,EACnB,OAAM,IAAI,MACR,eACI,WAAW,aAAa,eACxB,wBACL;AAGH,MAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO;EAC7C,MAAM,WAAW,MAAM,oBACrB,QACA,WACA,cACA,KACA,SACA,WACA,QACA,OACA,EAAE,SAAS,CACZ;EACD,MAAM,iBAAiB,uBAAuB,UAAU,OAAO,OAAO;AACtE,oBAAkB,SAAS,WAAW,gBAAgB,SAAS,gBAAgB;AAG/E,QAAM,WADY,SAAS,aAAa,EAAE,EAE9B,MAAM,EAAE,EAClB,SAAS,WACT,KACA,SAAS,iBACT,QACA,MACD;AACD,UAAQ,IAAI,0BAA0B,YAAY;;AAGpD,SAAQ,IAAI,6BAA6B,MAAM"}
1
+ {"version":3,"file":"migrate-skvsDG6d.mjs","names":["databases: string[]"],"sources":["../src/features/d1/d1.migrate.ts","../src/cli/commands/migrate.ts"],"sourcesContent":["import type { D1ResourceConfig, D1StateEntry } from \"./d1.types.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { spawnWranglerSync } from \"../../core/wrangler/wranglerSpawn.js\";\nimport type { NamingEngine } from \"../../core/naming/NamingEngine.js\";\nimport type { StateManager } from \"../../core/state/StateManager.js\";\nimport {\n d1CloudflareDatabaseName,\n d1SkipsProvisionAndMigrate,\n} from \"./d1.ownership.js\";\n\n/**\n * Apply Cloudflare D1 migrations for every D1 in `resources`.\n *\n * Wrangler requires `d1 migrations apply <DATABASE>` (positional). Tamer\n * resolves the derived database name per env (single) or per shard, and\n * invokes wrangler once per database.\n *\n * Adds `--remote` for non-`local` envs so migrations target the live D1, not\n * the local SQLite cache. Skips D1s owned externally or flagged\n * `preserveOnDestroy` (cross-stack).\n */\nexport async function d1Migrate(\n resources: D1ResourceConfig[],\n workerDir: string,\n env: string,\n wranglerOutFile: string = \"wrangler.json\",\n naming: NamingEngine,\n state: StateManager,\n): Promise<void> {\n const d1Configs = resources.filter(\n (r) => r.migrationsDir && !d1SkipsProvisionAndMigrate(r),\n );\n if (d1Configs.length === 0) return;\n\n const databases: string[] = [];\n for (const config of d1Configs) {\n if (config.type === \"single\") {\n databases.push(d1CloudflareDatabaseName(config, env, naming));\n continue;\n }\n const all = state.getAll();\n const shards = Object.values(all).filter(\n (e): e is D1StateEntry =>\n e.type === \"d1_database\" && e.logicalName === config.logicalName,\n );\n for (const s of shards) databases.push(s.derivedName);\n }\n\n for (const dbName of databases) {\n const args = [\n \"wrangler\",\n ...wranglerConfigCliArgs(wranglerOutFile),\n \"d1\",\n \"migrations\",\n \"apply\",\n dbName,\n ];\n if (env !== \"local\") args.push(\"--remote\");\n\n // Wrangler prompts for confirmation when stdin is a TTY. Tamer is an\n // automation path (CI / scripts): skip prompts like `d1 migrations apply`\n // does when `CI` is set or stdin is not a TTY (see wrangler help text).\n const result = spawnWranglerSync(args, {\n cwd: workerDir,\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n env: { CI: \"1\" },\n });\n\n if (result.status !== 0) {\n throw new Error(\n `wrangler d1 migrations apply failed for ${dbName} (exit ${result.status})`,\n );\n }\n }\n}\n","import { loadConfig, getWorkers } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport { resolveWorkerConfig } from \"../../core/config/resolver.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { d1Migrate } from \"../../features/d1/index.js\";\n\nexport async function runMigrate(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n}): Promise<void> {\n const workerFilter = options.worker;\n const env = options.env ?? \"local\";\n const configPath = options.configPath;\n const baseDir = process.cwd();\n\n const config = await loadConfig(configPath, { env });\n const accountId =\n config.account_id ?? cloudflareAccountIdFromEnv();\n if (!accountId) {\n throw new Error(\n \"account_id required in config or CLOUDFLARE_ACCOUNT_ID env var\",\n );\n }\n\n const naming = namingFromConfig(config);\n const api = new CFApiClient(accountId);\n const state = new StateManager(\n config.tenant.id,\n env,\n stackNameForConfig(config),\n );\n await state.hydrate(api);\n const imports = await fetchStackImports(api, config, env);\n\n const workers = await getWorkers(config, baseDir);\n const toRun = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toRun.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n for (const [workerKey, workerConfig] of toRun) {\n const resolved = await resolveWorkerConfig(\n config,\n workerKey,\n workerConfig,\n env,\n baseDir,\n accountId,\n naming,\n state,\n { imports },\n );\n const wranglerConfig = generateWranglerConfig(resolved, state, naming);\n writeWranglerJson(resolved.workerDir, wranglerConfig, resolved.wranglerOutFile);\n\n const resources = resolved.resources ?? {};\n await d1Migrate(\n resources.d1 ?? [],\n resolved.workerDir,\n env,\n resolved.wranglerOutFile,\n naming,\n state,\n );\n console.log(`Migrations applied for ${workerKey}`);\n }\n\n console.log(`Migrate complete for env: ${env}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,eAAsB,UACpB,WACA,WACA,KACA,kBAA0B,iBAC1B,QACA,OACe;CACf,MAAM,YAAY,UAAU,QACzB,MAAM,EAAE,iBAAiB,CAAC,2BAA2B,EAAE,CACzD;AACD,KAAI,UAAU,WAAW,EAAG;CAE5B,MAAMA,YAAsB,EAAE;AAC9B,MAAK,MAAM,UAAU,WAAW;AAC9B,MAAI,OAAO,SAAS,UAAU;AAC5B,aAAU,KAAK,yBAAyB,QAAQ,KAAK,OAAO,CAAC;AAC7D;;EAEF,MAAM,MAAM,MAAM,QAAQ;EAC1B,MAAM,SAAS,OAAO,OAAO,IAAI,CAAC,QAC/B,MACC,EAAE,SAAS,iBAAiB,EAAE,gBAAgB,OAAO,YACxD;AACD,OAAK,MAAM,KAAK,OAAQ,WAAU,KAAK,EAAE,YAAY;;AAGvD,MAAK,MAAM,UAAU,WAAW;EAC9B,MAAM,OAAO;GACX;GACA,GAAG,sBAAsB,gBAAgB;GACzC;GACA;GACA;GACA;GACD;AACD,MAAI,QAAQ,QAAS,MAAK,KAAK,WAAW;EAK1C,MAAM,SAAS,kBAAkB,MAAM;GACrC,KAAK;GACL,OAAO;IAAC;IAAU;IAAW;IAAU;GACvC,KAAK,EAAE,IAAI,KAAK;GACjB,CAAC;AAEF,MAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MACR,2CAA2C,OAAO,SAAS,OAAO,OAAO,GAC1E;;;;;;ACzDP,eAAsB,WAAW,SAIf;CAChB,MAAM,eAAe,QAAQ;CAC7B,MAAM,MAAM,QAAQ,OAAO;CAC3B,MAAM,aAAa,QAAQ;CAC3B,MAAM,UAAU,QAAQ,KAAK;CAE7B,MAAM,SAAS,MAAM,WAAW,YAAY,EAAE,KAAK,CAAC;CACpD,MAAM,YACJ,OAAO,cAAc,4BAA4B;AACnD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,iEACD;CAGH,MAAM,SAAS,iBAAiB,OAAO;CACvC,MAAM,MAAM,IAAI,YAAY,UAAU;CACtC,MAAM,QAAQ,IAAI,aAChB,OAAO,OAAO,IACd,KACA,mBAAmB,OAAO,CAC3B;AACD,OAAM,MAAM,QAAQ,IAAI;CACxB,MAAM,UAAU,MAAM,kBAAkB,KAAK,QAAQ,IAAI;CAEzD,MAAM,UAAU,MAAM,WAAW,QAAQ,QAAQ;CACjD,MAAM,QAAQ,eACV,QAAQ,QAAQ,CAAC,OAAO,MAAM,aAAa,GAC3C;AAEJ,KAAI,MAAM,WAAW,EACnB,OAAM,IAAI,MACR,eACI,WAAW,aAAa,eACxB,wBACL;AAGH,MAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO;EAC7C,MAAM,WAAW,MAAM,oBACrB,QACA,WACA,cACA,KACA,SACA,WACA,QACA,OACA,EAAE,SAAS,CACZ;EACD,MAAM,iBAAiB,uBAAuB,UAAU,OAAO,OAAO;AACtE,oBAAkB,SAAS,WAAW,gBAAgB,SAAS,gBAAgB;AAG/E,QAAM,WADY,SAAS,aAAa,EAAE,EAE9B,MAAM,EAAE,EAClB,SAAS,WACT,KACA,SAAS,iBACT,QACA,MACD;AACD,UAAQ,IAAI,0BAA0B,YAAY;;AAGpD,SAAQ,IAAI,6BAA6B,MAAM"}
@@ -1,15 +1,15 @@
1
1
  import { f as getDispatchNamespaces, m as getLogpushJobs, p as getDnsRecords } from "./normalize-DVSTRZhO.mjs";
2
- import { B as getWorkers, C as stackNameForConfig, D as resolveDeployedWorkerName, L as CFApiClient, O as resolveWorkerConfig, P as namingFromConfig, R as cloudflareAccountIdFromEnv, V as loadConfig, a as reconcileSecrets, c as vaultReaderFromMap, d as fetchStackImports, m as StateManager, s as secretsPlanItems, u as requiredSecretsForWorker, y as createEmptyCfiState } from "./tamer.mjs";
2
+ import { B as getWorkers, L as CFApiClient, O as resolveDeployedWorkerName, R as cloudflareAccountIdFromEnv, V as loadConfig, a as reconcileSecrets, b as createEmptyCfiState, c as vaultReaderFromMap, d as requiredSecretsForWorker, f as fetchStackImports, h as StateManager, k as resolveWorkerConfig, s as secretsPlanItems, u as namingFromConfig, w as stackNameForConfig } from "./tamer.mjs";
3
3
  import { i as logicalNamesForResourceKind, n as resourceModules } from "./registry-EWWdkLf7.mjs";
4
4
  import "./r2S3EmptyBucket-B9_pHfvB.mjs";
5
5
  import { a as signFor, t as formatPlanFieldChanges } from "./planFormat-5XMJK879.mjs";
6
- import { t as computeDriftReport } from "./drift-CeemyFqL.mjs";
6
+ import { t as computeDriftReport } from "./drift-C-qnJ-mH.mjs";
7
7
  import { r as dnsRecordStateKey } from "./dns-records.resolve-BB2agPAb.mjs";
8
8
  import { a as dnsRecordDiffPlanItems, n as filterPlanItemsForTarget, r as parseApplyTarget, t as assertApplyTargetDeclared } from "./applyTarget-Ce_mtRQX.mjs";
9
9
  import { o as logpushJobDiffPlanItems, s as logpushJobStateKey } from "./logpush-job-DJPlpnRu.mjs";
10
- import "./worker-route-x8q3K4-z.mjs";
11
- import { n as PLAN_FILE_FORMAT, o as writePlanFile, r as computeAttestation, t as buildCloudflareSnapshot } from "./cloudflareSnapshot-C6cF8GG8.mjs";
12
- import "./workers-D3Ekf3mF.mjs";
10
+ import "./worker-route-tOqVbhv3.mjs";
11
+ import { n as PLAN_FILE_FORMAT, o as writePlanFile, r as computeAttestation, t as buildCloudflareSnapshot } from "./cloudflareSnapshot-CFErW72O.mjs";
12
+ import "./workers-6r2ONF9J.mjs";
13
13
 
14
14
  //#region src/core/plan/computePlan.ts
15
15
  /**
@@ -475,4 +475,4 @@ function labelFor(kind) {
475
475
 
476
476
  //#endregion
477
477
  export { runPlan };
478
- //# sourceMappingURL=plan-C2urqJOz.mjs.map
478
+ //# sourceMappingURL=plan-BLy8FaE2.mjs.map