@dragonmastery/tamer 0.30.0 → 0.31.0
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.
- package/README.md +2 -1
- package/dist/{apply-CWU3HY0P.mjs → apply-BjrYbyHn.mjs} +14 -16
- package/dist/{apply-CWU3HY0P.mjs.map → apply-BjrYbyHn.mjs.map} +1 -1
- package/dist/{applyTarget-D15T_q7G.mjs → applyTarget-Ce_mtRQX.mjs} +3 -3
- package/dist/{applyTarget-D15T_q7G.mjs.map → applyTarget-Ce_mtRQX.mjs.map} +1 -1
- package/dist/{bootstrap-BicPW44a.mjs → bootstrap-D__dHw1w.mjs} +6 -6
- package/dist/bootstrap-D__dHw1w.mjs.map +1 -0
- package/dist/{buildDispatchUploadForm-BoUB93b3.mjs → buildDispatchUploadForm-CVnPmHg4.mjs} +1 -1
- package/dist/{buildDispatchUploadForm-BoUB93b3.mjs.map → buildDispatchUploadForm-CVnPmHg4.mjs.map} +1 -1
- package/dist/{cloudflareSnapshot-GBUHeg2m.mjs → cloudflareSnapshot-C6cF8GG8.mjs} +5 -7
- package/dist/{cloudflareSnapshot-GBUHeg2m.mjs.map → cloudflareSnapshot-C6cF8GG8.mjs.map} +1 -1
- package/dist/{deploy-DAEjDjOm.mjs → deploy-C6fX9td0.mjs} +23 -11
- package/dist/deploy-C6fX9td0.mjs.map +1 -0
- package/dist/{destroy-tenant-B-VLKfc6.mjs → destroy-tenant-T_94ed9x.mjs} +2 -4
- package/dist/{destroy-tenant-B-VLKfc6.mjs.map → destroy-tenant-T_94ed9x.mjs.map} +1 -1
- package/dist/{destroy-DtgPD_bD.mjs → destroy-vfk2Zbfj.mjs} +11 -13
- package/dist/{destroy-DtgPD_bD.mjs.map → destroy-vfk2Zbfj.mjs.map} +1 -1
- package/dist/{dev-BYItpt9U.mjs → dev-BLthyLml.mjs} +8 -10
- package/dist/{dev-BYItpt9U.mjs.map → dev-BLthyLml.mjs.map} +1 -1
- package/dist/{dns-records.resolve-C2T0m4NG.mjs → dns-records.resolve-8a_eHfVI.mjs} +1 -1
- package/dist/{dns-records.resolve-DwBR_1WI.mjs → dns-records.resolve-BB2agPAb.mjs} +1 -1
- package/dist/{dns-records.resolve-DwBR_1WI.mjs.map → dns-records.resolve-BB2agPAb.mjs.map} +1 -1
- package/dist/{dns-records.sync-CfI1mqXv.mjs → dns-records.sync-DqYROe07.mjs} +3 -3
- package/dist/{dns-records.sync-CfI1mqXv.mjs.map → dns-records.sync-DqYROe07.mjs.map} +1 -1
- package/dist/{doctor-C_hs7k2D.mjs → doctor-32YLAXXl.mjs} +2 -2
- package/dist/{doctor-C_hs7k2D.mjs.map → doctor-32YLAXXl.mjs.map} +1 -1
- package/dist/drift-BCxWdYHG.mjs +8 -0
- package/dist/{drift-DncpkI2R.mjs → drift-CeemyFqL.mjs} +37 -9
- package/dist/drift-CeemyFqL.mjs.map +1 -0
- package/dist/{events-B6oCdvSt.mjs → events-otk0l3aJ.mjs} +2 -4
- package/dist/{events-B6oCdvSt.mjs.map → events-otk0l3aJ.mjs.map} +1 -1
- package/dist/{generator-h_VG0Q5f.mjs → generator-gvCy7ouY.mjs} +2 -2
- package/dist/{generator-h_VG0Q5f.mjs.map → generator-gvCy7ouY.mjs.map} +1 -1
- package/dist/{import-D8zaVvwK.mjs → import-OvohE-H2.mjs} +6 -8
- package/dist/{import-D8zaVvwK.mjs.map → import-OvohE-H2.mjs.map} +1 -1
- package/dist/index.d.mts +264 -26
- package/dist/index.d.mts.map +1 -1
- package/dist/{logpush-job-DsRkOORJ.mjs → logpush-job-DJPlpnRu.mjs} +2 -2
- package/dist/{logpush-job-DsRkOORJ.mjs.map → logpush-job-DJPlpnRu.mjs.map} +1 -1
- package/dist/{migrate-Bwl0w6XN.mjs → migrate-CroDjbJz.mjs} +6 -8
- package/dist/{migrate-Bwl0w6XN.mjs.map → migrate-CroDjbJz.mjs.map} +1 -1
- package/dist/normalize-DVSTRZhO.mjs.map +1 -1
- package/dist/{plan-BNIAD--f.mjs → plan-C2urqJOz.mjs} +39 -14
- package/dist/plan-C2urqJOz.mjs.map +1 -0
- package/dist/{planFormat-CJw8Kq2s.mjs → planFormat-5XMJK879.mjs} +1 -1
- package/dist/{planFormat-CJw8Kq2s.mjs.map → planFormat-5XMJK879.mjs.map} +1 -1
- package/dist/{provision-tenant-BcZocyyn.mjs → provision-tenant-BJ1KugON.mjs} +6 -8
- package/dist/{provision-tenant-BcZocyyn.mjs.map → provision-tenant-BJ1KugON.mjs.map} +1 -1
- package/dist/{r2S3EmptyBucket-DD81ZWQ7.mjs → r2S3EmptyBucket-B9_pHfvB.mjs} +1 -1
- package/dist/{r2S3EmptyBucket-DD81ZWQ7.mjs.map → r2S3EmptyBucket-B9_pHfvB.mjs.map} +1 -1
- package/dist/{fetchStackImports-ClUYZy_U.mjs → registry-EWWdkLf7.mjs} +5 -982
- package/dist/registry-EWWdkLf7.mjs.map +1 -0
- package/dist/secrets-CnzjvndT.mjs +3 -0
- package/dist/{stackOutputs-D33EmyfT.mjs → stackOutputs-Cltzl2g0.mjs} +2 -2
- package/dist/{stackOutputs-D33EmyfT.mjs.map → stackOutputs-Cltzl2g0.mjs.map} +1 -1
- package/dist/{status-BAPpi2Zt.mjs → status-DkkS5lc9.mjs} +7 -9
- package/dist/{status-BAPpi2Zt.mjs.map → status-DkkS5lc9.mjs.map} +1 -1
- package/dist/{sync-BdJ43vO7.mjs → sync-CpfxqlOx.mjs} +7 -9
- package/dist/{sync-BdJ43vO7.mjs.map → sync-CpfxqlOx.mjs.map} +1 -1
- package/dist/tamer.mjs +4422 -221
- package/dist/tamer.mjs.map +1 -1
- package/dist/{tamerArtifactsR2-Ccgplu2Q.mjs → tamerArtifactsR2-DnUJmxnO.mjs} +2 -2
- package/dist/{tamerArtifactsR2-Ccgplu2Q.mjs.map → tamerArtifactsR2-DnUJmxnO.mjs.map} +1 -1
- package/dist/{types-CN1BOr0U.mjs → types-BzzHwIdw.mjs} +6 -8
- package/dist/{types-CN1BOr0U.mjs.map → types-BzzHwIdw.mjs.map} +1 -1
- package/dist/{verifyPlanFile-BQ7GCDC2.mjs → verifyPlanFile-BmEadIqm.mjs} +2 -2
- package/dist/{verifyPlanFile-BQ7GCDC2.mjs.map → verifyPlanFile-BmEadIqm.mjs.map} +1 -1
- package/dist/{wfp-delete-BG9WBd7F.mjs → wfp-delete-CDBFqmrM.mjs} +2 -3
- package/dist/{wfp-delete-BG9WBd7F.mjs.map → wfp-delete-CDBFqmrM.mjs.map} +1 -1
- package/dist/{wfp-put-DjErqxFa.mjs → wfp-put-BrwICc9i.mjs} +3 -4
- package/dist/{wfp-put-DjErqxFa.mjs.map → wfp-put-BrwICc9i.mjs.map} +1 -1
- package/dist/{worker-route-DY1onr-h.mjs → worker-route-x8q3K4-z.mjs} +3 -4
- package/dist/{worker-route-DY1onr-h.mjs.map → worker-route-x8q3K4-z.mjs.map} +1 -1
- package/dist/{workers-DNKsZOq4.mjs → workers-D3Ekf3mF.mjs} +3 -4
- package/dist/{workers-DNKsZOq4.mjs.map → workers-D3Ekf3mF.mjs.map} +1 -1
- package/dist/{wranglerSpawn-DmEz0ldT.mjs → wranglerSpawn-CUlo2qOJ.mjs} +1 -1
- package/dist/{wranglerSpawn-DmEz0ldT.mjs.map → wranglerSpawn-CUlo2qOJ.mjs.map} +1 -1
- package/dist/{zoneResolver-VoxLHM4N.mjs → zoneResolver-DNNNmO_w.mjs} +1 -1
- package/dist/{zoneResolver-VoxLHM4N.mjs.map → zoneResolver-DNNNmO_w.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/CFApiClient-DhbyyV71.mjs +0 -868
- package/dist/CFApiClient-DhbyyV71.mjs.map +0 -1
- package/dist/StateManager-JLBtz9V-.mjs +0 -760
- package/dist/StateManager-JLBtz9V-.mjs.map +0 -1
- package/dist/bootstrap-BicPW44a.mjs.map +0 -1
- package/dist/deploy-DAEjDjOm.mjs.map +0 -1
- package/dist/drift-DRnwTyZD.mjs +0 -10
- package/dist/drift-DncpkI2R.mjs.map +0 -1
- package/dist/fetchStackImports-ClUYZy_U.mjs.map +0 -1
- package/dist/loader-DnT9iqz9.mjs +0 -531
- package/dist/loader-DnT9iqz9.mjs.map +0 -1
- package/dist/plan-BNIAD--f.mjs.map +0 -1
|
@@ -1,857 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
4
|
-
import { n as r2S3CredentialsFromEnv, t as emptyR2BucketViaS3 } from "./r2S3EmptyBucket-DD81ZWQ7.mjs";
|
|
5
|
-
import { n as logApplyChange } from "./planFormat-CJw8Kq2s.mjs";
|
|
6
|
-
import { resolve } from "path";
|
|
7
|
-
|
|
8
|
-
//#region src/core/naming/NamingEngine.ts
|
|
9
|
-
function reLiteral(s) {
|
|
10
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11
|
-
}
|
|
12
|
-
var NamingEngine = class {
|
|
13
|
-
constructor(tenant, conventions) {
|
|
14
|
-
this.tenant = tenant;
|
|
15
|
-
this.conventions = conventions;
|
|
16
|
-
}
|
|
17
|
-
/** Tenant id for per-resource {@link CloudflareNameFn} overrides. */
|
|
18
|
-
get tenantId() {
|
|
19
|
-
return this.tenant.id;
|
|
20
|
-
}
|
|
21
|
-
d1SingleName(logicalName, env) {
|
|
22
|
-
if (this.conventions?.d1Single) return this.conventions.d1Single(logicalName, this.tenant.id, env);
|
|
23
|
-
return `db_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
24
|
-
}
|
|
25
|
-
d1ShardName(logicalName, shardDate, env) {
|
|
26
|
-
if (this.conventions?.d1Shard) return this.conventions.d1Shard(logicalName, shardDate, this.tenant.id, env);
|
|
27
|
-
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
28
|
-
if (logicalName === "default" || logicalName === "") return `db_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
29
|
-
return `db_${logicalName}_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
30
|
-
}
|
|
31
|
-
d1SingleBindingKey(logicalName) {
|
|
32
|
-
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
33
|
-
}
|
|
34
|
-
d1ShardBindingKey(logicalName, shardDate) {
|
|
35
|
-
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
36
|
-
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_${dateNoDashes}_T_${this.tenant.id.toUpperCase()}`;
|
|
37
|
-
}
|
|
38
|
-
r2BucketName(logicalName, env) {
|
|
39
|
-
if (this.conventions?.r2Bucket) {
|
|
40
|
-
const dateNoDashes = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
41
|
-
return this.conventions.r2Bucket(logicalName, dateNoDashes, this.tenant.id, env);
|
|
42
|
-
}
|
|
43
|
-
return `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Wrangler `r2_buckets[].binding`: logical + tenant only (same idea as {@link kvBindingKey}).
|
|
47
|
-
* Stable across envs; default {@link r2BucketName} is `r2-{logical}-t-{tenant}-{env}`.
|
|
48
|
-
*/
|
|
49
|
-
r2BindingKey(logicalName) {
|
|
50
|
-
return `R2_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
51
|
-
}
|
|
52
|
-
kvNamespaceName(logicalName, env) {
|
|
53
|
-
return `kv_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
54
|
-
}
|
|
55
|
-
kvBindingKey(logicalName) {
|
|
56
|
-
return `KV_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
57
|
-
}
|
|
58
|
-
queueName(logicalName, env) {
|
|
59
|
-
return `q-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
60
|
-
}
|
|
61
|
-
queueBindingKey(logicalName) {
|
|
62
|
-
return `Q_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
63
|
-
}
|
|
64
|
-
hyperdriveName(logicalName, env) {
|
|
65
|
-
return `hd-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
66
|
-
}
|
|
67
|
-
hyperdriveBindingKey(logicalName) {
|
|
68
|
-
return `HD_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
69
|
-
}
|
|
70
|
-
vectorizeName(logicalName, env) {
|
|
71
|
-
return `vec-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
72
|
-
}
|
|
73
|
-
vectorizeBindingKey(logicalName) {
|
|
74
|
-
return `VEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* AI Gateway slug (== Cloudflare gateway id). Per the Cloudflare API,
|
|
78
|
-
* gateway ids are case-sensitive lowercase ascii with `-`/`_`. Format:
|
|
79
|
-
* `aigw-{logical}-t-{tenantId}-{env}`.
|
|
80
|
-
*/
|
|
81
|
-
aiGatewayId(logicalName, env) {
|
|
82
|
-
return `aigw-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Stable cross-reference binding key for AI Gateway. AI Gateway has no
|
|
86
|
-
* Wrangler binding kind today, so this is only consumed by
|
|
87
|
-
* `${tamer:ai_gateway:<logical>.binding}` interpolations.
|
|
88
|
-
*/
|
|
89
|
-
aiGatewayBindingKey(logicalName) {
|
|
90
|
-
return `AI_GW_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Cloudflare-side pipeline name. Pipelines V1 names must be lowercase
|
|
94
|
-
* alphanumerics + hyphens (no underscores), so we mirror the R2 scheme.
|
|
95
|
-
* Pattern: `pipe-{logical}-t-{tenantId}-{env}`.
|
|
96
|
-
*/
|
|
97
|
-
pipelineName(logicalName, env) {
|
|
98
|
-
return `pipe-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Wrangler binding key emitted in `pipelines[]`. Uppercased logical with
|
|
102
|
-
* the tenant id appended so two tenants can share a worker namespace
|
|
103
|
-
* without colliding bindings.
|
|
104
|
-
*/
|
|
105
|
-
pipelineBindingKey(logicalName) {
|
|
106
|
-
return `PIPE_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
107
|
-
}
|
|
108
|
-
pipelineMatchPattern(logicalName, env) {
|
|
109
|
-
const exact = this.pipelineName(logicalName, env);
|
|
110
|
-
return (name) => name === exact;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Cloudflare-side workflow name. Workflow names accept lowercase
|
|
114
|
-
* alphanumerics + hyphens; we mirror the pipelines/AI-Gateway hyphen
|
|
115
|
-
* scheme. Pattern: `wf-{logical}-t-{tenantId}-{env}`.
|
|
116
|
-
*/
|
|
117
|
-
workflowName(logicalName, env) {
|
|
118
|
-
if (this.conventions?.workflow) return this.conventions.workflow(logicalName, this.tenant.id, env);
|
|
119
|
-
return `wf-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Wrangler binding key emitted in `workflows[]`. Uppercased logical with
|
|
123
|
-
* the tenant id appended so two tenants sharing a script can't collide.
|
|
124
|
-
*/
|
|
125
|
-
workflowBindingKey(logicalName) {
|
|
126
|
-
return `WF_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
127
|
-
}
|
|
128
|
-
workflowMatchPattern(logicalName, env) {
|
|
129
|
-
const exact = this.workflowName(logicalName, env);
|
|
130
|
-
return (name) => name === exact;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Cloudflare Secrets Store name. Account-scoped — the API allows free-form
|
|
134
|
-
* names (the dashboard examples use both `service_x_keys` and dashed
|
|
135
|
-
* variants), so we mirror our hyphen convention for consistency with
|
|
136
|
-
* pipelines / workflows / AI Gateway. Pattern:
|
|
137
|
-
* `sec-{logical}-t-{tenantId}-{env}`.
|
|
138
|
-
*/
|
|
139
|
-
secretsStoreName(logicalName, env) {
|
|
140
|
-
return `sec-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Stable cross-reference key for the store. Secrets Store has no Wrangler
|
|
144
|
-
* binding kind directly — `secrets_store_secrets[]` references the
|
|
145
|
-
* resolved `store_id`, not the store name — so this only powers
|
|
146
|
-
* `${tamer:secret_store:<n>.binding}` interpolations.
|
|
147
|
-
*/
|
|
148
|
-
secretsStoreBindingKey(logicalName) {
|
|
149
|
-
return `SEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
150
|
-
}
|
|
151
|
-
secretsStoreMatchPattern(logicalName, env) {
|
|
152
|
-
const exact = this.secretsStoreName(logicalName, env);
|
|
153
|
-
return (name) => name === exact;
|
|
154
|
-
}
|
|
155
|
-
workerName(workerKey, env) {
|
|
156
|
-
if (this.conventions?.workerName) return this.conventions.workerName(this.tenant.slug, workerKey, env, this.tenant.id);
|
|
157
|
-
if (env === "local") return `${this.tenant.slug}-${workerKey}-${this.tenant.id}`;
|
|
158
|
-
return `${this.tenant.slug}-${workerKey}-${env}-${this.tenant.id}`;
|
|
159
|
-
}
|
|
160
|
-
/** Whether stack {@link NamingConventions.d1Shard} is configured. */
|
|
161
|
-
hasD1ShardConvention() {
|
|
162
|
-
return Boolean(this.conventions?.d1Shard);
|
|
163
|
-
}
|
|
164
|
-
d1MatchPattern(logicalName, env) {
|
|
165
|
-
if (this.conventions?.d1Shard) return (name) => {
|
|
166
|
-
const shardDate = this.extractD1ShardDate(name);
|
|
167
|
-
if (!shardDate) return false;
|
|
168
|
-
return this.d1ShardName(logicalName, shardDate, env) === name;
|
|
169
|
-
};
|
|
170
|
-
const suffix = `_t_${this.tenant.id}_${env}`;
|
|
171
|
-
if (logicalName === "default" || logicalName === "") return (name) => /^db_\d{8}_t_/.test(name) && name.endsWith(suffix);
|
|
172
|
-
const prefix = `db_${logicalName}_`;
|
|
173
|
-
return (name) => name.startsWith(prefix) && name.endsWith(suffix);
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Default: exact {@link r2BucketName}, or legacy dated buckets
|
|
177
|
-
* `r2-{logical}-{YYYYMMDD}-t-{tenant}-{env}` from older Tamer versions.
|
|
178
|
-
* Custom {@link NamingConventions.r2Bucket}: exact name only (uses today's date
|
|
179
|
-
* when calling the hook, same as apply).
|
|
180
|
-
*/
|
|
181
|
-
r2MatchPattern(logicalName, env) {
|
|
182
|
-
if (this.conventions?.r2Bucket) {
|
|
183
|
-
const expected = this.r2BucketName(logicalName, env);
|
|
184
|
-
return (name) => name === expected;
|
|
185
|
-
}
|
|
186
|
-
const exactNew = `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
187
|
-
const legacyDated = /* @__PURE__ */ new RegExp(`^r2-${reLiteral(logicalName)}-\\d{8}-t-${reLiteral(this.tenant.id)}-${reLiteral(env)}$`);
|
|
188
|
-
return (name) => name === exactNew || legacyDated.test(name);
|
|
189
|
-
}
|
|
190
|
-
extractD1ShardDate(name) {
|
|
191
|
-
const compact = name.match(/_(\d{8})_t_/);
|
|
192
|
-
if (compact) {
|
|
193
|
-
const d = compact[1];
|
|
194
|
-
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
195
|
-
}
|
|
196
|
-
const underscored = name.match(/_(\d{4})_(\d{2})_(\d{2})_t_/);
|
|
197
|
-
if (underscored) return `${underscored[1]}-${underscored[2]}-${underscored[3]}`;
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
extractR2Date(name) {
|
|
201
|
-
const match = name.match(/r2-\w+-(\d{8})-t-/);
|
|
202
|
-
if (match) {
|
|
203
|
-
const d = match[1];
|
|
204
|
-
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
205
|
-
}
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
//#endregion
|
|
211
|
-
//#region src/core/config/namingFromConfig.ts
|
|
212
|
-
function namingFromConfig(config) {
|
|
213
|
-
const conventions = "naming" in config && config.naming ? config.naming : void 0;
|
|
214
|
-
return new NamingEngine(config.tenant, conventions);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region src/core/routes/routes.resolve.ts
|
|
219
|
-
const DEFAULT_PROD_ENVS = ["prod", "production"];
|
|
220
|
-
const DEFAULT_SKIP_ENVS = ["local"];
|
|
221
|
-
/**
|
|
222
|
-
* Per `docs/handoff.md` §6:
|
|
223
|
-
* - prod / production → bare apex (`todo.com`)
|
|
224
|
-
* - any other env (including ephemeral `pr-*`) → `{env}.{apex}`
|
|
225
|
-
* - `local` (or anything in `skipEnvs`) → no route
|
|
226
|
-
*
|
|
227
|
-
* The resource-name `-{env}` suffix on workers/D1/R2/KV is decoupled from
|
|
228
|
-
* URLs; this function only computes the URL.
|
|
229
|
-
*/
|
|
230
|
-
function effectiveHostForEnv(route, env) {
|
|
231
|
-
if ((route.skipEnvs ?? DEFAULT_SKIP_ENVS).includes(env)) return void 0;
|
|
232
|
-
if ((route.prodEnvs ?? DEFAULT_PROD_ENVS).includes(env)) return route.host;
|
|
233
|
-
return `${env}.${route.host}`;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Expand one Tamer route into a wrangler `Route` (or `undefined` if the env
|
|
237
|
-
* should not receive the route at all).
|
|
238
|
-
*/
|
|
239
|
-
function expandRouteForEnv(route, env) {
|
|
240
|
-
const host = effectiveHostForEnv(route, env);
|
|
241
|
-
if (!host) return void 0;
|
|
242
|
-
const zone = route.zone ?? route.host;
|
|
243
|
-
if (route.customDomain) return {
|
|
244
|
-
pattern: host,
|
|
245
|
-
custom_domain: true
|
|
246
|
-
};
|
|
247
|
-
return {
|
|
248
|
-
pattern: `${host}${route.path ?? "/*"}`,
|
|
249
|
-
zone_name: zone
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Expand `tamerRoutes` for the given env, dropping any that resolve to
|
|
254
|
-
* `undefined` (`local`, `skipEnvs`).
|
|
255
|
-
*
|
|
256
|
-
* Note: ephemeral envs (matching `tenant.ephemeralEnvPattern`) follow the
|
|
257
|
-
* same `{env}.{apex}` prefix rule as any non-prod env — e.g. an env named
|
|
258
|
-
* `pr-1234` resolves to `pr-1234.todo.com`. Callers that want a different
|
|
259
|
-
* URL scheme for ephemeral envs should special-case before calling.
|
|
260
|
-
*/
|
|
261
|
-
function effectiveRoutesForEnv(tamerRoutes, env) {
|
|
262
|
-
if (!tamerRoutes || tamerRoutes.length === 0) return [];
|
|
263
|
-
const out = [];
|
|
264
|
-
for (const r of tamerRoutes) {
|
|
265
|
-
const expanded = expandRouteForEnv(r, env);
|
|
266
|
-
if (expanded) out.push(expanded);
|
|
267
|
-
}
|
|
268
|
-
return out;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Zone-name routes are attached via the Cloudflare Workers Routes HTTP API
|
|
272
|
-
* (`/zones/{id}/workers/routes`), not via `wrangler.json`, so deploys stay
|
|
273
|
-
* consistent with `tamer drift` / destroy.
|
|
274
|
-
*/
|
|
275
|
-
function isApiManagedZoneRoute(r) {
|
|
276
|
-
return typeof r === "object" && r !== null && "zone_name" in r && typeof r.zone_name === "string" && "pattern" in r && typeof r.pattern === "string" && !("custom_domain" in r && r.custom_domain === true);
|
|
277
|
-
}
|
|
278
|
-
/** Custom-domain `tamerRoutes` stay in wrangler until a dedicated API path exists. */
|
|
279
|
-
function isWranglerOnlyTamerRoute(r) {
|
|
280
|
-
return typeof r === "object" && r !== null && "custom_domain" in r && r.custom_domain === true;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
//#endregion
|
|
284
|
-
//#region src/core/wrangler/wranglerOutFile.ts
|
|
285
|
-
/** Reject path segments in generated Wrangler config filename. */
|
|
286
|
-
function assertSafeWranglerOutFile(name) {
|
|
287
|
-
const trimmed = name.trim();
|
|
288
|
-
if (!trimmed) throw new Error("wranglerOutFile cannot be empty");
|
|
289
|
-
if (trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("..")) throw new Error(`Invalid wranglerOutFile "${name}": use a basename only (e.g. wrangler.json)`);
|
|
290
|
-
return trimmed;
|
|
291
|
-
}
|
|
292
|
-
/** Extra CLI args so Wrangler uses a non-default config file. */
|
|
293
|
-
function wranglerConfigCliArgs(outFile) {
|
|
294
|
-
if (outFile === "wrangler.json") return [];
|
|
295
|
-
return ["--config", outFile];
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
//#endregion
|
|
299
|
-
//#region src/core/references/references.ts
|
|
300
|
-
var TamerReferenceError = class extends Error {
|
|
301
|
-
constructor(message, fieldPath) {
|
|
302
|
-
super(`${message} (at ${fieldPath})`);
|
|
303
|
-
this.fieldPath = fieldPath;
|
|
304
|
-
this.name = "TamerReferenceError";
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
const REF_RE = /\$\{tamer:([a-z0-9_]+):([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\}/g;
|
|
308
|
-
/**
|
|
309
|
-
* Scan a string for any `${tamer:...}` references. Returns true when at
|
|
310
|
-
* least one reference is present (used for cheap pre-checks).
|
|
311
|
-
*/
|
|
312
|
-
function stringHasReference(s) {
|
|
313
|
-
REF_RE.lastIndex = 0;
|
|
314
|
-
return REF_RE.test(s);
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Resolve every `${tamer:...}` reference in `value`. Replacement preserves
|
|
318
|
-
* surrounding text for partial-string interpolation. `fieldPath` is included
|
|
319
|
-
* in any thrown {@link TamerReferenceError} for actionable diagnostics.
|
|
320
|
-
*/
|
|
321
|
-
function resolveReferencesInString(value, ctx, fieldPath) {
|
|
322
|
-
if (!stringHasReference(value)) return value;
|
|
323
|
-
return value.replace(REF_RE, (match, kind, logicalName, field) => {
|
|
324
|
-
try {
|
|
325
|
-
return lookupReference(kind, logicalName, field, ctx, fieldPath);
|
|
326
|
-
} catch (err) {
|
|
327
|
-
if (ctx.tolerant && err instanceof TamerReferenceError) return match;
|
|
328
|
-
throw err;
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Walk a `vars` record (or any flat string→string map) replacing references
|
|
334
|
-
* in every value. Returns a new object; the input is not mutated.
|
|
335
|
-
*/
|
|
336
|
-
function resolveReferencesInVars(vars, ctx, fieldPathPrefix) {
|
|
337
|
-
if (!vars) return vars;
|
|
338
|
-
const out = {};
|
|
339
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
340
|
-
if (typeof value !== "string") {
|
|
341
|
-
out[key] = value;
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
out[key] = resolveReferencesInString(value, ctx, `${fieldPathPrefix}.${key}`);
|
|
345
|
-
}
|
|
346
|
-
return out;
|
|
347
|
-
}
|
|
348
|
-
function lookupReference(kind, logicalName, field, ctx, fieldPath) {
|
|
349
|
-
switch (kind) {
|
|
350
|
-
case "d1": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "d1_database" && entry.logicalName === logicalName);
|
|
351
|
-
case "r2": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "r2_bucket" && entry.logicalName === logicalName);
|
|
352
|
-
case "kv": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "kv_namespace" && entry.logicalName === logicalName);
|
|
353
|
-
case "queue": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "queue" && entry.logicalName === logicalName);
|
|
354
|
-
case "hyperdrive": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "hyperdrive" && entry.logicalName === logicalName);
|
|
355
|
-
case "vectorize": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "vectorize" && entry.logicalName === logicalName);
|
|
356
|
-
case "ai_gateway": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "ai_gateway" && entry.logicalName === logicalName);
|
|
357
|
-
case "pipeline": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "pipeline" && entry.logicalName === logicalName);
|
|
358
|
-
case "workflow": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "workflow" && entry.logicalName === logicalName);
|
|
359
|
-
case "secret_store": return lookupResource(ctx, kind, logicalName, field, fieldPath, (entry) => entry.type === "secrets_store" && entry.logicalName === logicalName);
|
|
360
|
-
case "dispatch_namespace": return lookupDispatchNamespace(ctx, logicalName, field, fieldPath);
|
|
361
|
-
case "worker": return lookupWorker(ctx, logicalName, field, fieldPath);
|
|
362
|
-
case "import": return lookupImport(ctx, logicalName, field, fieldPath);
|
|
363
|
-
case "logpush_pipelines": return lookupLogpushPipelines(ctx, logicalName, field, fieldPath);
|
|
364
|
-
case "config": return lookupConfigField(ctx, logicalName, field, fieldPath);
|
|
365
|
-
default: throw new TamerReferenceError(`Unknown reference kind "${kind}" — expected one of d1 | r2 | kv | queue | hyperdrive | vectorize | ai_gateway | pipeline | workflow | secret_store | dispatch_namespace | worker | import | logpush_pipelines | config`, fieldPath);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
function lookupConfigField(ctx, _logicalName, field, fieldPath) {
|
|
369
|
-
if (field === "account_id") {
|
|
370
|
-
const id = (ctx.accountId ?? ctx.config.account_id ?? "").trim();
|
|
371
|
-
if (!id) throw new TamerReferenceError(`Reference \${tamer:config:stack.account_id} needs the stack Cloudflare account id — set top-level account_id in tamer/project.config.ts or pass CLOUDFLARE_ACCOUNT_ID when running tamer.`, fieldPath);
|
|
372
|
-
return id;
|
|
373
|
-
}
|
|
374
|
-
throw new TamerReferenceError(`Unknown field "${field}" on config reference — expected account_id`, fieldPath);
|
|
375
|
-
}
|
|
376
|
-
function getLogpushPipelinesEntry(ctx, logicalName, fieldPath) {
|
|
377
|
-
const all = ctx.state.getAll();
|
|
378
|
-
const entry = Object.values(all).find((e) => e.type === "logpush_pipelines" && e.logicalName === logicalName);
|
|
379
|
-
if (!entry) throw new TamerReferenceError(`Reference \${tamer:logpush_pipelines:${logicalName}.…} cannot be resolved — no pipelines graph in state for logpush job "${logicalName}". Run a full \`tamer apply\` (including the Logpush / pipelinesAuto step) for env "${ctx.env}" first.`, fieldPath);
|
|
380
|
-
return entry;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Exposes fields from the `logpush_pipelines:*` D1 state row (after
|
|
384
|
-
* `ensurePipelinesLogpushProvision` has run) for `outputs` and `vars`, e.g.
|
|
385
|
-
* `${tamer:logpush_pipelines:workers-trace.r2_data_catalog_table_name}`.
|
|
386
|
-
*/
|
|
387
|
-
function lookupLogpushPipelines(ctx, logicalName, field, fieldPath) {
|
|
388
|
-
const entry = getLogpushPipelinesEntry(ctx, logicalName, fieldPath);
|
|
389
|
-
switch (field) {
|
|
390
|
-
case "r2_data_catalog_table_name":
|
|
391
|
-
case "iceberg_table": {
|
|
392
|
-
const v = entry.r2DataCatalogTableName?.trim();
|
|
393
|
-
if (!v) throw new TamerReferenceError(`logpush_pipelines state for "${logicalName}" has no r2DataCatalogTableName (sink not yet created, or pre-upgrade state). Re-run a full \`tamer apply\` for env "${ctx.env}" after pipelinesAuto provisions the sink, or set table manually in consuming stack.`, fieldPath);
|
|
394
|
-
return v;
|
|
395
|
-
}
|
|
396
|
-
case "r2_data_catalog_table_name_pipelines":
|
|
397
|
-
case "iceberg_table_pipelines": {
|
|
398
|
-
const v = entry.r2DataCatalogTableNamePipelines?.trim();
|
|
399
|
-
if (v) return v;
|
|
400
|
-
const fallback = entry.r2DataCatalogTableName?.trim();
|
|
401
|
-
if (!fallback) throw new TamerReferenceError(`logpush_pipelines state for "${logicalName}" has no table name (sink not yet created). Re-run \`tamer apply\` for env "${ctx.env}".`, fieldPath);
|
|
402
|
-
return fallback;
|
|
403
|
-
}
|
|
404
|
-
case "r2_data_catalog_namespace":
|
|
405
|
-
case "iceberg_namespace": return (entry.r2DataCatalogNamespace ?? "default").trim() || "default";
|
|
406
|
-
case "name": return entry.pipelineName;
|
|
407
|
-
case "id": return entry.pipelineId;
|
|
408
|
-
default: throw new TamerReferenceError(`Unknown field "${field}" on logpush_pipelines reference — expected r2_data_catalog_table_name | r2_data_catalog_table_name_pipelines | r2_data_catalog_namespace | name | id | iceberg_table | iceberg_table_pipelines | iceberg_namespace`, fieldPath);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Resolve a `${tamer:import:<stack>.<output>}` against pre-fetched sibling
|
|
413
|
-
* stack outputs. The pre-fetch (`fetchStackImports`) loads every imported
|
|
414
|
-
* stack's `cfi_state:{stack}` row before resolution begins; this lookup is
|
|
415
|
-
* pure map access. Throws if the stack isn't in `ctx.imports` (config
|
|
416
|
-
* never declared it / pre-fetch wasn't wired in for this command) or if
|
|
417
|
-
* the named output hasn't been published yet (sibling stack hasn't run
|
|
418
|
-
* `apply` since the output was declared, or has been destroyed).
|
|
419
|
-
*/
|
|
420
|
-
function lookupImport(ctx, stackName, outputName, fieldPath) {
|
|
421
|
-
const imports = ctx.imports;
|
|
422
|
-
if (!imports || !(stackName in imports)) throw new TamerReferenceError(`Reference \${tamer:import:${stackName}.${outputName}} cannot be resolved — no imported stack "${stackName}" available. Ensure stack "${stackName}" exists in env "${ctx.env}" (run 'tamer apply' there first) and that the current command pre-fetches sibling stacks.`, fieldPath);
|
|
423
|
-
const stackOutputs = imports[stackName];
|
|
424
|
-
if (!(outputName in stackOutputs)) {
|
|
425
|
-
const available = Object.keys(stackOutputs).sort();
|
|
426
|
-
throw new TamerReferenceError(`Reference \${tamer:import:${stackName}.${outputName}} cannot be resolved — output "${outputName}" not found on imported stack "${stackName}".${available.length > 0 ? ` Available outputs on stack "${stackName}": ${available.join(", ")}.` : ` Stack "${stackName}" has no published outputs — run 'tamer apply' there with an \`outputs:\` block.`}`, fieldPath);
|
|
427
|
-
}
|
|
428
|
-
return stackOutputs[outputName];
|
|
429
|
-
}
|
|
430
|
-
function lookupResource(ctx, kind, logicalName, field, fieldPath, predicate) {
|
|
431
|
-
const all = ctx.state.getAll();
|
|
432
|
-
const entry = Object.values(all).find(predicate);
|
|
433
|
-
if (!entry) throw new TamerReferenceError(`Reference \${tamer:${kind}:${logicalName}.${field}} cannot be resolved — no ${kind} resource named "${logicalName}" in state. Run 'tamer apply --env ${ctx.env}' first.`, fieldPath);
|
|
434
|
-
switch (field) {
|
|
435
|
-
case "name": return resourceName(entry);
|
|
436
|
-
case "id": return resourceId(entry, kind, logicalName, fieldPath);
|
|
437
|
-
case "binding": return resourceBinding(entry);
|
|
438
|
-
default: throw new TamerReferenceError(`Unknown field "${field}" on ${kind} reference — expected name | id | binding`, fieldPath);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
function resourceName(entry) {
|
|
442
|
-
switch (entry.type) {
|
|
443
|
-
case "d1_database":
|
|
444
|
-
case "kv_namespace":
|
|
445
|
-
case "queue":
|
|
446
|
-
case "hyperdrive":
|
|
447
|
-
case "vectorize":
|
|
448
|
-
case "ai_gateway":
|
|
449
|
-
case "pipeline":
|
|
450
|
-
case "workflow":
|
|
451
|
-
case "secrets_store":
|
|
452
|
-
case "dispatch_namespace":
|
|
453
|
-
case "r2_bucket": return entry.derivedName;
|
|
454
|
-
case "dns_record": return entry.name;
|
|
455
|
-
case "logpush_job": return entry.derivedName;
|
|
456
|
-
case "logpush_pipelines": return entry.pipelineName;
|
|
457
|
-
case "worker_route": return entry.pattern;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
function resourceId(entry, kind, logicalName, fieldPath) {
|
|
461
|
-
switch (entry.type) {
|
|
462
|
-
case "d1_database":
|
|
463
|
-
case "kv_namespace":
|
|
464
|
-
case "queue":
|
|
465
|
-
case "hyperdrive":
|
|
466
|
-
case "vectorize":
|
|
467
|
-
case "ai_gateway":
|
|
468
|
-
case "pipeline":
|
|
469
|
-
case "workflow":
|
|
470
|
-
case "secrets_store": return entry.cfId;
|
|
471
|
-
case "r2_bucket": throw new TamerReferenceError(`R2 bucket "${logicalName}" has no .id (R2 buckets are addressed by name); use \${tamer:${kind}:${logicalName}.name}`, fieldPath);
|
|
472
|
-
case "dispatch_namespace": return entry.derivedName;
|
|
473
|
-
case "dns_record": return entry.recordId;
|
|
474
|
-
case "logpush_job": return String(entry.cfJobId);
|
|
475
|
-
case "logpush_pipelines": return entry.pipelineId;
|
|
476
|
-
case "worker_route": return entry.routeId;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
function resourceBinding(entry) {
|
|
480
|
-
switch (entry.type) {
|
|
481
|
-
case "d1_database":
|
|
482
|
-
case "r2_bucket":
|
|
483
|
-
case "kv_namespace":
|
|
484
|
-
case "queue":
|
|
485
|
-
case "hyperdrive":
|
|
486
|
-
case "vectorize":
|
|
487
|
-
case "ai_gateway":
|
|
488
|
-
case "pipeline":
|
|
489
|
-
case "workflow":
|
|
490
|
-
case "secrets_store": return entry.bindingKey;
|
|
491
|
-
case "dispatch_namespace": return entry.derivedName;
|
|
492
|
-
case "dns_record": throw new Error("internal: dns_record has no .binding — use .name or .id in config references");
|
|
493
|
-
case "logpush_job": throw new Error("internal: logpush_job has no .binding — use .name or .id in config references");
|
|
494
|
-
case "logpush_pipelines": throw new Error("internal: logpush_pipelines has no .binding — use .name or .id in config references");
|
|
495
|
-
case "worker_route": return entry.routeId;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
function lookupDispatchNamespace(ctx, logicalName, field, fieldPath) {
|
|
499
|
-
if (!getDispatchNamespaces(ctx.config).find((d) => d.logicalName === logicalName)) throw new TamerReferenceError(`Reference \${tamer:dispatch_namespace:${logicalName}.${field}} cannot be resolved — no dispatchNamespaces entry named "${logicalName}" in the Tamer project config`, fieldPath);
|
|
500
|
-
if (field !== "name" && field !== "id") throw new TamerReferenceError(`Unknown field "${field}" on dispatch_namespace reference — expected name | id`, fieldPath);
|
|
501
|
-
const all = ctx.state.getAll();
|
|
502
|
-
const stateEntry = Object.values(all).find((e) => e.type === "dispatch_namespace" && e.logicalName === logicalName);
|
|
503
|
-
if (!stateEntry || stateEntry.type !== "dispatch_namespace") throw new TamerReferenceError(`Reference \${tamer:dispatch_namespace:${logicalName}.${field}} unresolved — no state entry. Run 'tamer apply --env ${ctx.env}' first.`, fieldPath);
|
|
504
|
-
return stateEntry.derivedName;
|
|
505
|
-
}
|
|
506
|
-
function lookupWorker(ctx, workerKey, field, fieldPath) {
|
|
507
|
-
let target;
|
|
508
|
-
if (ctx.config.workers && ctx.config.workers[workerKey]) target = ctx.config.workers[workerKey];
|
|
509
|
-
else if (ctx.config.worker && workerKey === "default") target = ctx.config.worker;
|
|
510
|
-
if (!target) throw new TamerReferenceError(`Reference \${tamer:worker:${workerKey}.${field}} cannot be resolved — no worker key "${workerKey}" in the Tamer project config`, fieldPath);
|
|
511
|
-
if (field !== "name") throw new TamerReferenceError(`Unknown field "${field}" on worker reference — only "name" is supported (the env-suffixed deployed script name)`, fieldPath);
|
|
512
|
-
return resolveDeployedWorkerName(ctx.config, workerKey, target, ctx.env, ctx.naming);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
//#endregion
|
|
516
|
-
//#region src/core/config/resolver.ts
|
|
517
|
-
/** Wrangler script name after env suffix rules (matches `tamer deploy`). */
|
|
518
|
-
function resolveDeployedWorkerName(_config, workerKey, workerConfig, env, naming) {
|
|
519
|
-
const sn = workerConfig.scriptName?.trim();
|
|
520
|
-
if (sn) {
|
|
521
|
-
if (env === "local") return sn;
|
|
522
|
-
return `${sn}-${env}`;
|
|
523
|
-
}
|
|
524
|
-
return naming.workerName(workerKey, env);
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Map from base service-binding target name (`scriptName` for envs other than
|
|
528
|
-
* `local`, or the local-deployed name) → env-suffixed deployed name for every
|
|
529
|
-
* worker in `config`. Used to auto-rewrite intra-stack `services[].service`
|
|
530
|
-
* fields so fixtures don't have to repeat env overrides for every env.
|
|
531
|
-
*/
|
|
532
|
-
function buildIntraStackScriptNameMap(config, env, naming) {
|
|
533
|
-
const map = /* @__PURE__ */ new Map();
|
|
534
|
-
if (config.workers) for (const [key, wc] of Object.entries(config.workers)) {
|
|
535
|
-
const baseName = wc.scriptName?.trim() ?? naming.workerName(key, "local");
|
|
536
|
-
const deployed = resolveDeployedWorkerName(config, key, wc, env, naming);
|
|
537
|
-
map.set(baseName, deployed);
|
|
538
|
-
}
|
|
539
|
-
if (config.worker) {
|
|
540
|
-
const w = config.worker;
|
|
541
|
-
const baseName = w.scriptName?.trim() ?? naming.workerName("default", "local");
|
|
542
|
-
const deployed = resolveDeployedWorkerName(config, "default", w, env, naming);
|
|
543
|
-
map.set(baseName, deployed);
|
|
544
|
-
}
|
|
545
|
-
return map;
|
|
546
|
-
}
|
|
547
|
-
/** Returns a worker config copy whose `services[].service` is rewritten to env-suffixed deployed names. */
|
|
548
|
-
function rewriteIntraStackServiceTargets(workerConfig, baseToDeployed) {
|
|
549
|
-
const services = workerConfig.services;
|
|
550
|
-
if (!services || services.length === 0) return workerConfig;
|
|
551
|
-
let rewroteAny = false;
|
|
552
|
-
const rewritten = services.map((s) => {
|
|
553
|
-
const target = baseToDeployed.get(s.service);
|
|
554
|
-
if (!target || target === s.service) return s;
|
|
555
|
-
rewroteAny = true;
|
|
556
|
-
return {
|
|
557
|
-
...s,
|
|
558
|
-
service: target
|
|
559
|
-
};
|
|
560
|
-
});
|
|
561
|
-
if (!rewroteAny) return workerConfig;
|
|
562
|
-
return {
|
|
563
|
-
...workerConfig,
|
|
564
|
-
services: rewritten
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
function mergeVars(base = {}, override = {}) {
|
|
568
|
-
return {
|
|
569
|
-
...base,
|
|
570
|
-
...override
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
/** Same env merge as `resolveWorkerConfig` (for deploy topo-sort service edges). */
|
|
574
|
-
function mergedWorkerConfigForEnv(workerConfig, env, tenant) {
|
|
575
|
-
let merged = { ...workerConfig };
|
|
576
|
-
if (env === "local" && workerConfig.local) merged = {
|
|
577
|
-
...merged,
|
|
578
|
-
...workerConfig.local,
|
|
579
|
-
vars: mergeVars(workerConfig.vars, workerConfig.local.vars)
|
|
580
|
-
};
|
|
581
|
-
else if (workerConfig.env?.[env]) {
|
|
582
|
-
const envOverride = workerConfig.env[env];
|
|
583
|
-
merged = {
|
|
584
|
-
...merged,
|
|
585
|
-
...envOverride,
|
|
586
|
-
vars: mergeVars(workerConfig.vars, envOverride.vars)
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
const mv = merged.vars;
|
|
590
|
-
if (mv && Object.prototype.hasOwnProperty.call(mv, "BRANCH_SUFFIX")) merged = {
|
|
591
|
-
...merged,
|
|
592
|
-
vars: {
|
|
593
|
-
...mv,
|
|
594
|
-
BRANCH_SUFFIX: isEphemeralEnv(env, tenant) ? env : ""
|
|
595
|
-
}
|
|
596
|
-
};
|
|
597
|
-
return merged;
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* Align `dispatch_namespaces[].namespace` and `vars.WFP_NAMESPACE` with
|
|
601
|
-
* {@link effectiveDispatchNamespaceName} for envs that have no explicit
|
|
602
|
-
* `worker.env[env]` block (e.g. `pr-*` shared namespace).
|
|
603
|
-
*/
|
|
604
|
-
function applyDispatchNamespaceEnvOverrides(config, merged, env) {
|
|
605
|
-
const dns = getDispatchNamespaces(config);
|
|
606
|
-
if (dns.length === 0) return merged;
|
|
607
|
-
const resolved = effectiveDispatchNamespaceName(dns[0], env, config.tenant);
|
|
608
|
-
const m = merged;
|
|
609
|
-
let next = merged;
|
|
610
|
-
if (m.dispatch_namespaces?.length) next = {
|
|
611
|
-
...next,
|
|
612
|
-
dispatch_namespaces: m.dispatch_namespaces.map((d) => ({
|
|
613
|
-
...d,
|
|
614
|
-
namespace: resolved
|
|
615
|
-
}))
|
|
616
|
-
};
|
|
617
|
-
if (m.vars && typeof m.vars.WFP_NAMESPACE === "string" && m.vars.WFP_NAMESPACE === dns[0].namespace) {
|
|
618
|
-
const v = next.vars;
|
|
619
|
-
next = {
|
|
620
|
-
...next,
|
|
621
|
-
vars: {
|
|
622
|
-
...v,
|
|
623
|
-
WFP_NAMESPACE: resolved
|
|
624
|
-
}
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
return next;
|
|
628
|
-
}
|
|
629
|
-
/**
|
|
630
|
-
* Walk the merged worker config and replace `${tamer:<kind>:<logical>.<field>}`
|
|
631
|
-
* references in `vars` and `tamerRoutes[].host` / `.zone` against the current
|
|
632
|
-
* state snapshot. Also resolves `r2_buckets[].bucket_name`,
|
|
633
|
-
* **`services[].service`**, **`dispatch_namespaces[].namespace`**, and
|
|
634
|
-
* `resources.d1[].databaseName` when `ownership` is `external`. Throws
|
|
635
|
-
* `TamerReferenceError` (with field path) if any
|
|
636
|
-
* reference is unresolved — bubbles up to the caller as a fatal.
|
|
637
|
-
*/
|
|
638
|
-
function resolveCrossResourceReferences(merged, ctx) {
|
|
639
|
-
const refCtx = {
|
|
640
|
-
config: ctx.config,
|
|
641
|
-
env: ctx.env,
|
|
642
|
-
state: ctx.state,
|
|
643
|
-
naming: ctx.naming,
|
|
644
|
-
tolerant: ctx.tolerant,
|
|
645
|
-
imports: ctx.imports,
|
|
646
|
-
accountId: ctx.accountId
|
|
647
|
-
};
|
|
648
|
-
const m = merged;
|
|
649
|
-
let next = merged;
|
|
650
|
-
if (m.vars) {
|
|
651
|
-
const resolvedVars = resolveReferencesInVars(materializeVars(m.vars), refCtx, `worker[${ctx.workerKey}].vars`);
|
|
652
|
-
if (resolvedVars && resolvedVars !== m.vars) next = {
|
|
653
|
-
...next,
|
|
654
|
-
vars: resolvedVars
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
const tamerRoutes = next.tamerRoutes;
|
|
658
|
-
if (tamerRoutes && tamerRoutes.length > 0) {
|
|
659
|
-
let mutated = false;
|
|
660
|
-
const resolvedRoutes = tamerRoutes.map((r, idx) => {
|
|
661
|
-
const fieldBase = `worker[${ctx.workerKey}].tamerRoutes[${idx}]`;
|
|
662
|
-
const host = resolveReferencesInString(r.host, refCtx, `${fieldBase}.host`);
|
|
663
|
-
const zone = r.zone ? resolveReferencesInString(r.zone, refCtx, `${fieldBase}.zone`) : r.zone;
|
|
664
|
-
if (host !== r.host || zone !== r.zone) mutated = true;
|
|
665
|
-
return {
|
|
666
|
-
...r,
|
|
667
|
-
host,
|
|
668
|
-
...zone !== void 0 ? { zone } : {}
|
|
669
|
-
};
|
|
670
|
-
});
|
|
671
|
-
if (mutated) next = {
|
|
672
|
-
...next,
|
|
673
|
-
tamerRoutes: resolvedRoutes
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
const r2Buckets = next.r2_buckets;
|
|
677
|
-
if (r2Buckets && r2Buckets.length > 0) {
|
|
678
|
-
let mutated = false;
|
|
679
|
-
const resolvedBuckets = r2Buckets.map((b, idx) => {
|
|
680
|
-
const raw = b.bucket_name;
|
|
681
|
-
if (raw === void 0) return b;
|
|
682
|
-
const fieldBase = `worker[${ctx.workerKey}].r2_buckets[${idx}].bucket_name`;
|
|
683
|
-
const bucket_name = resolveReferencesInString(materializeTamerResolvable(raw), refCtx, fieldBase);
|
|
684
|
-
if (bucket_name !== raw) mutated = true;
|
|
685
|
-
return {
|
|
686
|
-
...b,
|
|
687
|
-
bucket_name
|
|
688
|
-
};
|
|
689
|
-
});
|
|
690
|
-
if (mutated) next = {
|
|
691
|
-
...next,
|
|
692
|
-
r2_buckets: resolvedBuckets
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
const svc = next.services;
|
|
696
|
-
if (svc && svc.length > 0) {
|
|
697
|
-
let mutated = false;
|
|
698
|
-
const resolvedSvc = svc.map((s, idx) => {
|
|
699
|
-
const raw = s.service;
|
|
700
|
-
const fieldBase = `worker[${ctx.workerKey}].services[${idx}].service`;
|
|
701
|
-
const service = resolveReferencesInString(materializeTamerResolvable(raw), refCtx, fieldBase);
|
|
702
|
-
if (service !== raw) mutated = true;
|
|
703
|
-
return {
|
|
704
|
-
...s,
|
|
705
|
-
service
|
|
706
|
-
};
|
|
707
|
-
});
|
|
708
|
-
if (mutated) next = {
|
|
709
|
-
...next,
|
|
710
|
-
services: resolvedSvc
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
|
-
const dispatchNsMerged = next.dispatch_namespaces;
|
|
714
|
-
if (dispatchNsMerged && dispatchNsMerged.length > 0) {
|
|
715
|
-
let mutated = false;
|
|
716
|
-
const resolvedDn = dispatchNsMerged.map((d, idx) => {
|
|
717
|
-
const raw = d.namespace;
|
|
718
|
-
const fieldBase = `worker[${ctx.workerKey}].dispatch_namespaces[${idx}].namespace`;
|
|
719
|
-
const namespace = resolveReferencesInString(materializeTamerResolvable(raw), refCtx, fieldBase);
|
|
720
|
-
if (namespace !== raw) mutated = true;
|
|
721
|
-
return {
|
|
722
|
-
...d,
|
|
723
|
-
namespace
|
|
724
|
-
};
|
|
725
|
-
});
|
|
726
|
-
if (mutated) next = {
|
|
727
|
-
...next,
|
|
728
|
-
dispatch_namespaces: resolvedDn
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
const resBlock = next.resources;
|
|
732
|
-
if (resBlock?.d1 && resBlock.d1.length > 0) {
|
|
733
|
-
let mutated = false;
|
|
734
|
-
const d1Resolved = resBlock.d1.map((d1c, idx) => {
|
|
735
|
-
if (d1c.ownership !== "external" || !d1c.databaseName) return d1c;
|
|
736
|
-
const fieldBase = `worker[${ctx.workerKey}].resources.d1[${idx}].databaseName`;
|
|
737
|
-
const databaseName = resolveReferencesInString(materializeTamerResolvable(d1c.databaseName), refCtx, fieldBase);
|
|
738
|
-
if (databaseName !== d1c.databaseName) mutated = true;
|
|
739
|
-
return {
|
|
740
|
-
...d1c,
|
|
741
|
-
databaseName
|
|
742
|
-
};
|
|
743
|
-
});
|
|
744
|
-
if (mutated) next = {
|
|
745
|
-
...next,
|
|
746
|
-
resources: {
|
|
747
|
-
...resBlock,
|
|
748
|
-
d1: d1Resolved
|
|
749
|
-
}
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
return next;
|
|
753
|
-
}
|
|
754
|
-
function stripTamerFields(config) {
|
|
755
|
-
const { path, config: configPath, resources, local, env, scriptName: _scriptName, wranglerOutFile: _out, dispatchNamespace: _dispatchNs, tamerRoutes: _tamerRoutes, tamerStaleRouteSweepZones: _tamerStaleRouteSweepZones, ...rest } = config;
|
|
756
|
-
return rest;
|
|
757
|
-
}
|
|
758
|
-
/**
|
|
759
|
-
* Env merge + intra-stack `services` rewrite + sibling-stack resolution for
|
|
760
|
-
* **`resources.d1[].databaseName` only** when `ownership: "external"`.
|
|
761
|
-
*
|
|
762
|
-
* Use before {@link ResourceModule.pickResources} during `apply` / `sync` /
|
|
763
|
-
* `drift` so imported D1 names are known **without** resolving worker `vars`
|
|
764
|
-
* (those references often need resources created earlier in the same `apply`).
|
|
765
|
-
*/
|
|
766
|
-
function mergeWorkerConfigForResourcePick(config, workerKey, workerConfig, env, accountId, naming, state, opts = {}) {
|
|
767
|
-
let merged = mergedWorkerConfigForEnv(workerConfig, env, config.tenant);
|
|
768
|
-
merged = applyDispatchNamespaceEnvOverrides(config, merged, env);
|
|
769
|
-
const intraMap = buildIntraStackScriptNameMap(config, env, naming);
|
|
770
|
-
merged = rewriteIntraStackServiceTargets(merged, intraMap);
|
|
771
|
-
const refCtx = {
|
|
772
|
-
config,
|
|
773
|
-
env,
|
|
774
|
-
state,
|
|
775
|
-
naming,
|
|
776
|
-
tolerant: opts.referencesMode === "tolerant",
|
|
777
|
-
imports: opts.imports,
|
|
778
|
-
accountId
|
|
779
|
-
};
|
|
780
|
-
const resBlock = merged.resources;
|
|
781
|
-
if (!resBlock?.d1?.length) return merged;
|
|
782
|
-
const d1Resolved = resBlock.d1.map((d1c, idx) => {
|
|
783
|
-
if (d1c.ownership !== "external" || !d1c.databaseName) return d1c;
|
|
784
|
-
const fieldBase = `worker[${workerKey}].resources.d1[${idx}].databaseName`;
|
|
785
|
-
const databaseName = resolveReferencesInString(materializeTamerResolvable(d1c.databaseName), refCtx, fieldBase);
|
|
786
|
-
return {
|
|
787
|
-
...d1c,
|
|
788
|
-
databaseName
|
|
789
|
-
};
|
|
790
|
-
});
|
|
791
|
-
return {
|
|
792
|
-
...merged,
|
|
793
|
-
resources: {
|
|
794
|
-
...resBlock,
|
|
795
|
-
d1: d1Resolved
|
|
796
|
-
}
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
/**
|
|
800
|
-
* Env-merged worker config with every `${tamer:…}` site resolved for wrangler
|
|
801
|
-
* (`vars`, `tamerRoutes`, `r2_buckets[].bucket_name`, external D1 names).
|
|
802
|
-
* Used by {@link resolveWorkerConfig} after resource state is up to date.
|
|
803
|
-
*/
|
|
804
|
-
function mergeWorkerConfigWithResolvedRefs(config, workerKey, workerConfig, env, accountId, naming, state, opts = {}) {
|
|
805
|
-
let merged = mergedWorkerConfigForEnv(workerConfig, env, config.tenant);
|
|
806
|
-
merged = applyDispatchNamespaceEnvOverrides(config, merged, env);
|
|
807
|
-
const intraMap = buildIntraStackScriptNameMap(config, env, naming);
|
|
808
|
-
merged = rewriteIntraStackServiceTargets(merged, intraMap);
|
|
809
|
-
return resolveCrossResourceReferences(merged, {
|
|
810
|
-
config,
|
|
811
|
-
env,
|
|
812
|
-
state,
|
|
813
|
-
naming,
|
|
814
|
-
workerKey,
|
|
815
|
-
tolerant: opts.referencesMode === "tolerant",
|
|
816
|
-
imports: opts.imports,
|
|
817
|
-
accountId
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
async function resolveWorkerConfig(config, workerKey, workerConfig, env, baseDir, accountId, naming, state, opts = {}) {
|
|
821
|
-
const merged = mergeWorkerConfigWithResolvedRefs(config, workerKey, workerConfig, env, accountId, naming, state, opts);
|
|
822
|
-
const workerDir = workerConfig.path ? resolve(baseDir, workerConfig.path) : baseDir;
|
|
823
|
-
const m = merged;
|
|
824
|
-
const workerName = resolveDeployedWorkerName(config, workerKey, merged, env, naming);
|
|
825
|
-
const wranglerOutFile = assertSafeWranglerOutFile(m.wranglerOutFile?.trim() || "wrangler.json");
|
|
826
|
-
const dispatchNamespace = m.dispatchNamespace?.trim() || void 0;
|
|
827
|
-
const stripped = stripTamerFields(merged);
|
|
828
|
-
const tamerRoutes = merged.tamerRoutes;
|
|
829
|
-
const expandedRoutes = effectiveRoutesForEnv(tamerRoutes, env);
|
|
830
|
-
const apiManagedRoutes = expandedRoutes.filter(isApiManagedZoneRoute);
|
|
831
|
-
const wranglerTamerRoutes = expandedRoutes.filter(isWranglerOnlyTamerRoute);
|
|
832
|
-
const mergedRoutes = [...stripped.routes ?? [], ...wranglerTamerRoutes];
|
|
833
|
-
/** Non-local deploys emit `routes: []` when there are none — omitting `routes` can leave stale Wrangler-published custom domains attached from a prior config. */
|
|
834
|
-
const wranglerRoutes = mergedRoutes.length > 0 ? mergedRoutes : env === "local" ? void 0 : [];
|
|
835
|
-
return {
|
|
836
|
-
workerKey,
|
|
837
|
-
workerName,
|
|
838
|
-
workerDir,
|
|
839
|
-
env,
|
|
840
|
-
wranglerOutFile,
|
|
841
|
-
dispatchNamespace,
|
|
842
|
-
wranglerConfig: {
|
|
843
|
-
...stripped,
|
|
844
|
-
...wranglerRoutes !== void 0 ? { routes: wranglerRoutes } : {},
|
|
845
|
-
name: workerName,
|
|
846
|
-
account_id: accountId,
|
|
847
|
-
compatibility_date: stripped.compatibility_date ?? config.compatibility_date
|
|
848
|
-
},
|
|
849
|
-
resources: merged.resources ?? workerConfig.resources ?? {},
|
|
850
|
-
apiManagedRoutes
|
|
851
|
-
};
|
|
852
|
-
}
|
|
1
|
+
import { B as getWorkers } from "./tamer.mjs";
|
|
2
|
+
import { n as r2S3CredentialsFromEnv, t as emptyR2BucketViaS3 } from "./r2S3EmptyBucket-B9_pHfvB.mjs";
|
|
3
|
+
import { n as logApplyChange } from "./planFormat-5XMJK879.mjs";
|
|
853
4
|
|
|
854
|
-
//#endregion
|
|
855
5
|
//#region src/core/naming/resolveCloudflareName.ts
|
|
856
6
|
function resolveOverride(fn, tenantId, env, ctx) {
|
|
857
7
|
if (!fn) return void 0;
|
|
@@ -3879,132 +3029,5 @@ function getResourceModule(kind) {
|
|
|
3879
3029
|
}
|
|
3880
3030
|
|
|
3881
3031
|
//#endregion
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
/**
|
|
3885
|
-
* Walk the merged `CfiConfig` and collect every `${tamer:import:…}` ref
|
|
3886
|
-
* site along with where it was found. Used both to drive the pre-fetch
|
|
3887
|
-
* (which sibling stacks to load) and by `tamer status` to render an
|
|
3888
|
-
* "inbound imports" panel even before any `apply` has run.
|
|
3889
|
-
*
|
|
3890
|
-
* Self-imports (current stack importing from its own name) are filtered
|
|
3891
|
-
* out — they are almost always a config typo and would otherwise
|
|
3892
|
-
* silently resolve via the same row this command is about to write.
|
|
3893
|
-
*/
|
|
3894
|
-
function scanConfigForImports(config) {
|
|
3895
|
-
const selfStack = stackNameForConfig(config);
|
|
3896
|
-
const refs = [];
|
|
3897
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3898
|
-
const push = (raw, fieldPath) => {
|
|
3899
|
-
if (!raw) return;
|
|
3900
|
-
IMPORT_RE.lastIndex = 0;
|
|
3901
|
-
let m;
|
|
3902
|
-
while ((m = IMPORT_RE.exec(raw)) !== null) {
|
|
3903
|
-
const stack = m[1];
|
|
3904
|
-
const output = m[2];
|
|
3905
|
-
if (stack === selfStack) continue;
|
|
3906
|
-
const key = `${fieldPath}::${stack}.${output}`;
|
|
3907
|
-
if (seen.has(key)) continue;
|
|
3908
|
-
seen.add(key);
|
|
3909
|
-
refs.push({
|
|
3910
|
-
stack,
|
|
3911
|
-
output,
|
|
3912
|
-
fieldPath
|
|
3913
|
-
});
|
|
3914
|
-
}
|
|
3915
|
-
};
|
|
3916
|
-
const walkVars = (vars, pathPrefix) => {
|
|
3917
|
-
if (!vars) return;
|
|
3918
|
-
for (const [k, v] of Object.entries(vars)) push(materializeTamerResolvable(v), `${pathPrefix}.${k}`);
|
|
3919
|
-
};
|
|
3920
|
-
const walkR2BucketNames = (w, pathPrefix) => {
|
|
3921
|
-
if (!w.r2_buckets) return;
|
|
3922
|
-
w.r2_buckets.forEach((b, i) => {
|
|
3923
|
-
if (b.bucket_name === void 0) return;
|
|
3924
|
-
push(materializeTamerResolvable(b.bucket_name), `${pathPrefix}.r2_buckets[${i}].bucket_name`);
|
|
3925
|
-
});
|
|
3926
|
-
};
|
|
3927
|
-
const walkD1DatabaseNames = (w, pathPrefix) => {
|
|
3928
|
-
const d1 = w.resources?.d1;
|
|
3929
|
-
if (!d1) return;
|
|
3930
|
-
d1.forEach((d, i) => {
|
|
3931
|
-
if (d.databaseName === void 0) return;
|
|
3932
|
-
push(materializeTamerResolvable(d.databaseName), `${pathPrefix}.resources.d1[${i}].databaseName`);
|
|
3933
|
-
});
|
|
3934
|
-
};
|
|
3935
|
-
/** Service bindings / WfP namespace strings may carry `${tamer:import:…}`. */
|
|
3936
|
-
const walkBindingsWithRefs = (w, pathPrefix) => {
|
|
3937
|
-
w.services?.forEach((s, i) => {
|
|
3938
|
-
if (s.service === void 0) return;
|
|
3939
|
-
push(materializeTamerResolvable(s.service), `${pathPrefix}.services[${i}].service`);
|
|
3940
|
-
});
|
|
3941
|
-
w.dispatch_namespaces?.forEach((d, i) => {
|
|
3942
|
-
if (d.namespace === void 0) return;
|
|
3943
|
-
push(materializeTamerResolvable(d.namespace), `${pathPrefix}.dispatch_namespaces[${i}].namespace`);
|
|
3944
|
-
});
|
|
3945
|
-
};
|
|
3946
|
-
if (config.worker) {
|
|
3947
|
-
walkVars(config.worker.vars, "worker.vars");
|
|
3948
|
-
walkR2BucketNames(config.worker, "worker");
|
|
3949
|
-
walkD1DatabaseNames(config.worker, "worker");
|
|
3950
|
-
walkBindingsWithRefs(config.worker, "worker");
|
|
3951
|
-
if (config.worker.tamerRoutes) config.worker.tamerRoutes.forEach((r, i) => {
|
|
3952
|
-
push(r.host, `worker.tamerRoutes[${i}].host`);
|
|
3953
|
-
push(r.zone, `worker.tamerRoutes[${i}].zone`);
|
|
3954
|
-
});
|
|
3955
|
-
}
|
|
3956
|
-
if (config.workers) for (const [key, w] of Object.entries(config.workers)) {
|
|
3957
|
-
walkVars(w.vars, `worker[${key}].vars`);
|
|
3958
|
-
walkR2BucketNames(w, `worker[${key}]`);
|
|
3959
|
-
walkD1DatabaseNames(w, `worker[${key}]`);
|
|
3960
|
-
walkBindingsWithRefs(w, `worker[${key}]`);
|
|
3961
|
-
if (w.tamerRoutes) w.tamerRoutes.forEach((r, i) => {
|
|
3962
|
-
push(r.host, `worker[${key}].tamerRoutes[${i}].host`);
|
|
3963
|
-
push(r.zone, `worker[${key}].tamerRoutes[${i}].zone`);
|
|
3964
|
-
});
|
|
3965
|
-
}
|
|
3966
|
-
if (config.outputs) for (const [name, source] of Object.entries(config.outputs)) push(materializeTamerResolvable(source), `outputs.${name}`);
|
|
3967
|
-
return refs;
|
|
3968
|
-
}
|
|
3969
|
-
/** Distinct sibling stack names referenced anywhere in `config`. */
|
|
3970
|
-
function importedStackNames(config) {
|
|
3971
|
-
const refs = scanConfigForImports(config);
|
|
3972
|
-
return [...new Set(refs.map((r) => r.stack))].sort();
|
|
3973
|
-
}
|
|
3974
|
-
/**
|
|
3975
|
-
* Hydrate every imported sibling stack's persisted outputs and return
|
|
3976
|
-
* them shaped for {@link ReferenceContext.imports}.
|
|
3977
|
-
*
|
|
3978
|
-
* - `local` env: returns `{}` immediately. Local mode never persists
|
|
3979
|
-
* state, so cross-stack imports are inherently unresolvable. Callers
|
|
3980
|
-
* running in tolerant mode (`plan`, `status`) will see the placeholder
|
|
3981
|
-
* verbatim; strict callers (`apply`, `deploy`) will fail at resolution
|
|
3982
|
-
* with a clear "no imported stack" message.
|
|
3983
|
-
* - Missing sibling state row: recorded as an empty outputs map, so
|
|
3984
|
-
* `lookupImport` can produce a "no published outputs" diagnostic
|
|
3985
|
-
* (vs. the generic "stack not pre-fetched" error).
|
|
3986
|
-
*
|
|
3987
|
-
* The {@link CFApiClient} is shared with the caller for socket reuse.
|
|
3988
|
-
*/
|
|
3989
|
-
async function fetchStackImports(api, config, env) {
|
|
3990
|
-
const stacks = importedStackNames(config);
|
|
3991
|
-
if (stacks.length === 0 || env === "local") return {};
|
|
3992
|
-
const out = {};
|
|
3993
|
-
for (const stack of stacks) {
|
|
3994
|
-
const sibling = new StateManager(config.tenant.id, env, stack);
|
|
3995
|
-
try {
|
|
3996
|
-
await sibling.hydrate(api);
|
|
3997
|
-
} catch (err) {
|
|
3998
|
-
throw new Error(`Failed to hydrate imported stack "${stack}" from env "${env}": ${err instanceof Error ? err.message : String(err)}`);
|
|
3999
|
-
}
|
|
4000
|
-
const persisted = sibling.getStackOutputs();
|
|
4001
|
-
const flat = {};
|
|
4002
|
-
for (const [name, v] of Object.entries(persisted)) flat[name] = v.value;
|
|
4003
|
-
out[stack] = flat;
|
|
4004
|
-
}
|
|
4005
|
-
return out;
|
|
4006
|
-
}
|
|
4007
|
-
|
|
4008
|
-
//#endregion
|
|
4009
|
-
export { wranglerConfigCliArgs as _, resourceModules as a, d1CloudflareDatabaseName as c, mergeWorkerConfigForResourcePick as d, mergedWorkerConfigForEnv as f, resolveReferencesInString as g, rewriteIntraStackServiceTargets as h, getResourceModule as i, d1SkipsProvisionAndMigrate as l, resolveWorkerConfig as m, importedStackNames as n, secretsStoreDeriveName as o, resolveDeployedWorkerName as p, scanConfigForImports as r, logicalNamesForResourceKind as s, fetchStackImports as t, buildIntraStackScriptNameMap as u, namingFromConfig as v };
|
|
4010
|
-
//# sourceMappingURL=fetchStackImports-ClUYZy_U.mjs.map
|
|
3032
|
+
export { d1CloudflareDatabaseName as a, logicalNamesForResourceKind as i, resourceModules as n, d1SkipsProvisionAndMigrate as o, secretsStoreDeriveName as r, getResourceModule as t };
|
|
3033
|
+
//# sourceMappingURL=registry-EWWdkLf7.mjs.map
|