@dragonmastery/tamer 0.36.5 → 0.36.6
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.
|
@@ -32,7 +32,10 @@ function topoSortWorkersByServiceBindings(workers, config, naming, env) {
|
|
|
32
32
|
visiting.add(key);
|
|
33
33
|
const cfg = byKey.get(key);
|
|
34
34
|
if (cfg) {
|
|
35
|
-
const
|
|
35
|
+
const merged = rewriteIntraStackServiceTargets(mergedWorkerConfigForEnv(cfg, env, config.tenant), intraMap);
|
|
36
|
+
const serviceDeps = merged.services?.map((s) => s.service) ?? [];
|
|
37
|
+
const doDeps = merged.durable_objects?.bindings?.map((b) => b.script_name).filter((s) => typeof s === "string" && s.length > 0).map((s) => intraMap.get(s) ?? s) ?? [];
|
|
38
|
+
const deps = [...serviceDeps, ...doDeps];
|
|
36
39
|
for (const dep of deps) {
|
|
37
40
|
const depKey = scriptNameToKey.get(dep);
|
|
38
41
|
if (depKey && depKey !== key) visit(depKey);
|
|
@@ -158,4 +161,4 @@ async function runDeploy(options) {
|
|
|
158
161
|
|
|
159
162
|
//#endregion
|
|
160
163
|
export { runDeploy };
|
|
161
|
-
//# sourceMappingURL=deploy-
|
|
164
|
+
//# sourceMappingURL=deploy-CiGgo_Om.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-CiGgo_Om.mjs","names":["out: WorkerEntry[]","deploySecrets: Awaited<\n ReturnType<typeof createDeploySecretsResources>\n > | null","buildEnv: Record<string, string>"],"sources":["../src/cli/commands/deploy.ts"],"sourcesContent":["import { loadConfig, getWorkers, getConfigBaseDir } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport type { NamingEngine } from \"../../core/naming/NamingEngine.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { spawnWranglerSync, spawnBuildSync } from \"../../core/wrangler/wranglerSpawn.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport {\n buildIntraStackScriptNameMap,\n mergedWorkerConfigForEnv,\n resolveDeployedWorkerName,\n resolveWorkerConfig,\n rewriteIntraStackServiceTargets,\n} from \"../../core/config/resolver.js\";\nimport { requiredSecretsForWorker } from \"../../core/secrets/declared.js\";\nimport { createDeploySecretsResources } from \"./secrets/context.js\";\nimport { pushSecretsForDeploy } from \"./secrets/push.js\";\nimport { workflowsApply } from \"../../features/workflows/workflows.apply.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { runSync } from \"./sync.js\";\nimport { workerRoutesApply } from \"../../features/worker-route/index.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { assertShardRegistryPresentForDeploy } from \"../../core/codegen/shardRegistry/index.js\";\nimport type { CfiConfig, WorkerConfig } from \"../../types.js\";\n\ntype WorkerEntry = [string, WorkerConfig];\n\n/**\n * Topologically sort workers by `services[].service` so that dependencies\n * deploy before dependents. Cloudflare rejects deploys that reference\n * service bindings to workers that don't yet exist on the account.\n * Cross-config dependencies (services not in this monorepo) are ignored.\n */\nexport function topoSortWorkersByServiceBindings(\n workers: WorkerEntry[],\n config: CfiConfig,\n naming: NamingEngine,\n env: string,\n): WorkerEntry[] {\n const intraMap = buildIntraStackScriptNameMap(config, env, naming);\n const scriptNameToKey = new Map<string, string>();\n for (const [key, cfg] of workers) {\n const name = resolveDeployedWorkerName(config, key, cfg, env, naming);\n scriptNameToKey.set(name, key);\n }\n\n const byKey = new Map(workers);\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const out: WorkerEntry[] = [];\n\n function visit(key: string): void {\n if (visited.has(key)) return;\n if (visiting.has(key)) return;\n visiting.add(key);\n const cfg = byKey.get(key);\n if (cfg) {\n const merged = rewriteIntraStackServiceTargets(\n mergedWorkerConfigForEnv(cfg, env, config.tenant),\n intraMap,\n );\n const serviceDeps = merged.services?.map((s) => s.service) ?? [];\n const doDeps =\n merged.durable_objects?.bindings\n ?.map((b) => b.script_name)\n .filter((s): s is string => typeof s === \"string\" && s.length > 0)\n .map((s) => intraMap.get(s) ?? s)\n ?? [];\n const deps = [...serviceDeps, ...doDeps];\n for (const dep of deps) {\n const depKey = scriptNameToKey.get(dep);\n if (depKey && depKey !== key) visit(depKey);\n }\n visiting.delete(key);\n visited.add(key);\n out.push([key, cfg]);\n }\n }\n\n for (const [key] of workers) visit(key);\n return out;\n}\n\nexport async function runDeploy(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n /** Passed to `wrangler deploy --dispatch-namespace` when the worker has no `dispatchNamespace` in config. */\n dispatchNamespace?: string;\n}): Promise<void> {\n const workerFilter = options.worker;\n // `--env` is intentionally required (no silent default to \"prod\") to\n // match every other Tamer command and to avoid the classic \"ran\n // `tamer deploy` from the wrong shell, shipped a half-tested branch\n // to production\" footgun.\n const env = options.env;\n if (!env) {\n throw new Error(\n \"deploy: --env is required (e.g. --env staging). \" +\n \"Tamer no longer defaults to prod — pass the env explicitly.\",\n );\n }\n const configPath = options.configPath;\n\n const config = await loadConfig(configPath, { env });\n const baseDir = getConfigBaseDir();\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 console.log(`Syncing state for env: ${env}...`);\n await runSync({ env, configPath });\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 state.beginOperation(\"deploy\", workerFilter ? `worker:${workerFilter}` : undefined);\n\n try {\n\n const workers = await getWorkers(config, baseDir);\n const toDeploy = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toDeploy.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n const ordered = topoSortWorkersByServiceBindings(\n toDeploy,\n config,\n naming,\n env,\n );\n\n await assertShardRegistryPresentForDeploy({\n config,\n env,\n baseDir,\n accountId,\n naming,\n state,\n imports,\n workers,\n });\n\n let deploySecrets: Awaited<\n ReturnType<typeof createDeploySecretsResources>\n > | null = null;\n\n for (const [workerKey, workerConfig] of ordered) {\n const mergedForSecrets = mergedWorkerConfigForEnv(\n workerConfig,\n env,\n config.tenant,\n );\n const requiredSecrets = requiredSecretsForWorker(mergedForSecrets);\n\n if (requiredSecrets.length > 0 && env !== \"local\") {\n if (!deploySecrets) {\n deploySecrets = await createDeploySecretsResources(api, env);\n }\n const deployedName = resolveDeployedWorkerName(\n config,\n workerKey,\n workerConfig,\n env,\n naming,\n );\n await pushSecretsForDeploy({\n workerKey,\n deployedName,\n required: requiredSecrets,\n vault: deploySecrets.vault,\n state,\n api,\n masterKey: deploySecrets.masterKey,\n });\n }\n\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 buildConfig = mergedForSecrets.build;\n if (buildConfig) {\n console.log(`Building ${workerKey} (${buildConfig.command})...`);\n const buildEnv: Record<string, string> = {};\n if (wranglerConfig.vars) {\n for (const [k, v] of Object.entries(wranglerConfig.vars)) {\n buildEnv[k] = typeof v === \"string\" ? v : String(v);\n }\n }\n const buildResult = spawnBuildSync(buildConfig.command, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n env: buildEnv,\n });\n if (buildResult.status !== 0) {\n throw new Error(\n `build failed for ${workerKey} (exit ${buildResult.status})`,\n );\n }\n console.log(`Built ${workerKey}`);\n }\n\n const typesArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"types\",\n ];\n const typesResult = spawnWranglerSync(typesArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n });\n if (typesResult.status !== 0) {\n throw new Error(`wrangler types failed for ${workerKey}`);\n }\n\n const dispatchNs =\n resolved.dispatchNamespace ?? options.dispatchNamespace;\n const deployArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"deploy\",\n ];\n if (dispatchNs) {\n deployArgs.push(\"--dispatch-namespace\", dispatchNs);\n }\n\n const deployResult = spawnWranglerSync(deployArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n });\n if (deployResult.status !== 0) {\n throw new Error(`wrangler deploy failed for ${workerKey}`);\n }\n console.log(`Deployed ${workerKey}`);\n\n // Register workflows after the script exists (chicken-and-egg: workflows\n // need the deployed script). During `tamer apply`, workflow registration\n // is deferred when the script doesn't exist yet. Here the script is live.\n const workflowResources = resolved.resources?.workflows;\n if (workflowResources && workflowResources.length > 0) {\n await workflowsApply(\n workflowResources,\n config.tenant,\n env,\n api,\n state,\n naming,\n { workerKey, deployedName: resolved.workerName },\n );\n }\n }\n\n if (env !== \"local\") {\n try {\n await workerRoutesApply(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`worker routes apply failed after deploy: ${msg}`);\n }\n }\n\n state.finishOperation();\n await state.persist(api);\n console.log(`Deploy complete for env: ${env}`);\n } catch (err) {\n state.failOperation(err instanceof Error ? err.message : String(err));\n try {\n await state.persist(api);\n } catch {\n /* swallow secondary persist failure */\n }\n throw err;\n }\n}\n"],"mappings":"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"}
|
package/dist/tamer.mjs
CHANGED
|
@@ -8856,7 +8856,7 @@ async function main() {
|
|
|
8856
8856
|
break;
|
|
8857
8857
|
case "deploy": {
|
|
8858
8858
|
const d = parseDeployArgs(rest);
|
|
8859
|
-
await import("./deploy-
|
|
8859
|
+
await import("./deploy-CiGgo_Om.mjs").then((m) => m.runDeploy({
|
|
8860
8860
|
worker: d.worker,
|
|
8861
8861
|
env: d.env,
|
|
8862
8862
|
configPath: d.configPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dragonmastery/tamer",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.6",
|
|
4
4
|
"description": "Tamer: Cloudflare Workers infra CLI (sync, apply, deploy, migrate, destroy) and Wrangler-oriented TypeScript types.",
|
|
5
5
|
"author": "DragonMastery",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-ByatGWlQ.mjs","names":["out: WorkerEntry[]","deploySecrets: Awaited<\n ReturnType<typeof createDeploySecretsResources>\n > | null","buildEnv: Record<string, string>"],"sources":["../src/cli/commands/deploy.ts"],"sourcesContent":["import { loadConfig, getWorkers, getConfigBaseDir } from \"../../core/config/loader.js\";\nimport { cloudflareAccountIdFromEnv } from \"../../core/cloudflareEnv.js\";\nimport { namingFromConfig } from \"../../core/config/namingFromConfig.js\";\nimport type { NamingEngine } from \"../../core/naming/NamingEngine.js\";\nimport { wranglerConfigCliArgs } from \"../../core/wrangler/wranglerOutFile.js\";\nimport { spawnWranglerSync, spawnBuildSync } from \"../../core/wrangler/wranglerSpawn.js\";\nimport { StateManager } from \"../../core/state/StateManager.js\";\nimport { stackNameForConfig } from \"../../core/state/stackName.js\";\nimport { CFApiClient } from \"../../core/api/CFApiClient.js\";\nimport {\n buildIntraStackScriptNameMap,\n mergedWorkerConfigForEnv,\n resolveDeployedWorkerName,\n resolveWorkerConfig,\n rewriteIntraStackServiceTargets,\n} from \"../../core/config/resolver.js\";\nimport { requiredSecretsForWorker } from \"../../core/secrets/declared.js\";\nimport { createDeploySecretsResources } from \"./secrets/context.js\";\nimport { pushSecretsForDeploy } from \"./secrets/push.js\";\nimport { workflowsApply } from \"../../features/workflows/workflows.apply.js\";\nimport {\n generateWranglerConfig,\n writeWranglerJson,\n} from \"../../core/wrangler/generator.js\";\nimport { runSync } from \"./sync.js\";\nimport { workerRoutesApply } from \"../../features/worker-route/index.js\";\nimport { fetchStackImports } from \"../../core/imports/fetchStackImports.js\";\nimport { assertShardRegistryPresentForDeploy } from \"../../core/codegen/shardRegistry/index.js\";\nimport type { CfiConfig, WorkerConfig } from \"../../types.js\";\n\ntype WorkerEntry = [string, WorkerConfig];\n\n/**\n * Topologically sort workers by `services[].service` so that dependencies\n * deploy before dependents. Cloudflare rejects deploys that reference\n * service bindings to workers that don't yet exist on the account.\n * Cross-config dependencies (services not in this monorepo) are ignored.\n */\nexport function topoSortWorkersByServiceBindings(\n workers: WorkerEntry[],\n config: CfiConfig,\n naming: NamingEngine,\n env: string,\n): WorkerEntry[] {\n const intraMap = buildIntraStackScriptNameMap(config, env, naming);\n const scriptNameToKey = new Map<string, string>();\n for (const [key, cfg] of workers) {\n const name = resolveDeployedWorkerName(config, key, cfg, env, naming);\n scriptNameToKey.set(name, key);\n }\n\n const byKey = new Map(workers);\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const out: WorkerEntry[] = [];\n\n function visit(key: string): void {\n if (visited.has(key)) return;\n if (visiting.has(key)) return;\n visiting.add(key);\n const cfg = byKey.get(key);\n if (cfg) {\n const merged = rewriteIntraStackServiceTargets(\n mergedWorkerConfigForEnv(cfg, env, config.tenant),\n intraMap,\n );\n const deps = merged.services?.map((s) => s.service) ?? [];\n for (const dep of deps) {\n const depKey = scriptNameToKey.get(dep);\n if (depKey && depKey !== key) visit(depKey);\n }\n visiting.delete(key);\n visited.add(key);\n out.push([key, cfg]);\n }\n }\n\n for (const [key] of workers) visit(key);\n return out;\n}\n\nexport async function runDeploy(options: {\n worker?: string;\n env?: string;\n configPath?: string;\n /** Passed to `wrangler deploy --dispatch-namespace` when the worker has no `dispatchNamespace` in config. */\n dispatchNamespace?: string;\n}): Promise<void> {\n const workerFilter = options.worker;\n // `--env` is intentionally required (no silent default to \"prod\") to\n // match every other Tamer command and to avoid the classic \"ran\n // `tamer deploy` from the wrong shell, shipped a half-tested branch\n // to production\" footgun.\n const env = options.env;\n if (!env) {\n throw new Error(\n \"deploy: --env is required (e.g. --env staging). \" +\n \"Tamer no longer defaults to prod — pass the env explicitly.\",\n );\n }\n const configPath = options.configPath;\n\n const config = await loadConfig(configPath, { env });\n const baseDir = getConfigBaseDir();\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 console.log(`Syncing state for env: ${env}...`);\n await runSync({ env, configPath });\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 state.beginOperation(\"deploy\", workerFilter ? `worker:${workerFilter}` : undefined);\n\n try {\n\n const workers = await getWorkers(config, baseDir);\n const toDeploy = workerFilter\n ? workers.filter(([k]) => k === workerFilter)\n : workers;\n\n if (toDeploy.length === 0) {\n throw new Error(\n workerFilter\n ? `Worker \"${workerFilter}\" not found`\n : \"No workers configured\",\n );\n }\n\n const ordered = topoSortWorkersByServiceBindings(\n toDeploy,\n config,\n naming,\n env,\n );\n\n await assertShardRegistryPresentForDeploy({\n config,\n env,\n baseDir,\n accountId,\n naming,\n state,\n imports,\n workers,\n });\n\n let deploySecrets: Awaited<\n ReturnType<typeof createDeploySecretsResources>\n > | null = null;\n\n for (const [workerKey, workerConfig] of ordered) {\n const mergedForSecrets = mergedWorkerConfigForEnv(\n workerConfig,\n env,\n config.tenant,\n );\n const requiredSecrets = requiredSecretsForWorker(mergedForSecrets);\n\n if (requiredSecrets.length > 0 && env !== \"local\") {\n if (!deploySecrets) {\n deploySecrets = await createDeploySecretsResources(api, env);\n }\n const deployedName = resolveDeployedWorkerName(\n config,\n workerKey,\n workerConfig,\n env,\n naming,\n );\n await pushSecretsForDeploy({\n workerKey,\n deployedName,\n required: requiredSecrets,\n vault: deploySecrets.vault,\n state,\n api,\n masterKey: deploySecrets.masterKey,\n });\n }\n\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 buildConfig = mergedForSecrets.build;\n if (buildConfig) {\n console.log(`Building ${workerKey} (${buildConfig.command})...`);\n const buildEnv: Record<string, string> = {};\n if (wranglerConfig.vars) {\n for (const [k, v] of Object.entries(wranglerConfig.vars)) {\n buildEnv[k] = typeof v === \"string\" ? v : String(v);\n }\n }\n const buildResult = spawnBuildSync(buildConfig.command, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n env: buildEnv,\n });\n if (buildResult.status !== 0) {\n throw new Error(\n `build failed for ${workerKey} (exit ${buildResult.status})`,\n );\n }\n console.log(`Built ${workerKey}`);\n }\n\n const typesArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"types\",\n ];\n const typesResult = spawnWranglerSync(typesArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n });\n if (typesResult.status !== 0) {\n throw new Error(`wrangler types failed for ${workerKey}`);\n }\n\n const dispatchNs =\n resolved.dispatchNamespace ?? options.dispatchNamespace;\n const deployArgs = [\n \"wrangler\",\n ...wranglerConfigCliArgs(resolved.wranglerOutFile),\n \"deploy\",\n ];\n if (dispatchNs) {\n deployArgs.push(\"--dispatch-namespace\", dispatchNs);\n }\n\n const deployResult = spawnWranglerSync(deployArgs, {\n cwd: resolved.workerDir,\n stdio: \"inherit\",\n });\n if (deployResult.status !== 0) {\n throw new Error(`wrangler deploy failed for ${workerKey}`);\n }\n console.log(`Deployed ${workerKey}`);\n\n // Register workflows after the script exists (chicken-and-egg: workflows\n // need the deployed script). During `tamer apply`, workflow registration\n // is deferred when the script doesn't exist yet. Here the script is live.\n const workflowResources = resolved.resources?.workflows;\n if (workflowResources && workflowResources.length > 0) {\n await workflowsApply(\n workflowResources,\n config.tenant,\n env,\n api,\n state,\n naming,\n { workerKey, deployedName: resolved.workerName },\n );\n }\n }\n\n if (env !== \"local\") {\n try {\n await workerRoutesApply(\n env,\n config,\n baseDir,\n accountId,\n naming,\n state,\n api,\n { imports },\n );\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`worker routes apply failed after deploy: ${msg}`);\n }\n }\n\n state.finishOperation();\n await state.persist(api);\n console.log(`Deploy complete for env: ${env}`);\n } catch (err) {\n state.failOperation(err instanceof Error ? err.message : String(err));\n try {\n await state.persist(api);\n } catch {\n /* swallow secondary persist failure */\n }\n throw err;\n }\n}\n"],"mappings":"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"}
|