@dragonmastery/tamer 0.31.1 → 0.31.5
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/dist/{apply-BjrYbyHn.mjs → apply-C_70Hgcf.mjs} +7 -7
- package/dist/{apply-BjrYbyHn.mjs.map → apply-C_70Hgcf.mjs.map} +1 -1
- package/dist/{bootstrap-D__dHw1w.mjs → bootstrap-CQS5s33A.mjs} +2 -2
- package/dist/{bootstrap-D__dHw1w.mjs.map → bootstrap-CQS5s33A.mjs.map} +1 -1
- package/dist/{cloudflareSnapshot-C6cF8GG8.mjs → cloudflareSnapshot-CFErW72O.mjs} +3 -3
- package/dist/{cloudflareSnapshot-C6cF8GG8.mjs.map → cloudflareSnapshot-CFErW72O.mjs.map} +1 -1
- package/dist/{deploy-C6fX9td0.mjs → deploy-D-GXzsWR.mjs} +4 -4
- package/dist/{deploy-C6fX9td0.mjs.map → deploy-D-GXzsWR.mjs.map} +1 -1
- package/dist/{destroy-vfk2Zbfj.mjs → destroy-DJRw_qLX.mjs} +7 -7
- package/dist/{destroy-vfk2Zbfj.mjs.map → destroy-DJRw_qLX.mjs.map} +1 -1
- package/dist/{destroy-tenant-T_94ed9x.mjs → destroy-tenant-DFHfNImL.mjs} +2 -2
- package/dist/{destroy-tenant-T_94ed9x.mjs.map → destroy-tenant-DFHfNImL.mjs.map} +1 -1
- package/dist/{dev-BLthyLml.mjs → dev-caJxohHI.mjs} +4 -4
- package/dist/{dev-BLthyLml.mjs.map → dev-caJxohHI.mjs.map} +1 -1
- package/dist/{dns-records.sync-DqYROe07.mjs → dns-records.sync-Ck0Q2OK3.mjs} +2 -2
- package/dist/{dns-records.sync-DqYROe07.mjs.map → dns-records.sync-Ck0Q2OK3.mjs.map} +1 -1
- package/dist/{drift-BCxWdYHG.mjs → drift-5_LwAdZo.mjs} +3 -3
- package/dist/{drift-CeemyFqL.mjs → drift-C-qnJ-mH.mjs} +4 -4
- package/dist/{drift-CeemyFqL.mjs.map → drift-C-qnJ-mH.mjs.map} +1 -1
- package/dist/{events-otk0l3aJ.mjs → events-Bor7XgLC.mjs} +2 -2
- package/dist/{events-otk0l3aJ.mjs.map → events-Bor7XgLC.mjs.map} +1 -1
- package/dist/{import-OvohE-H2.mjs → import-Vn9lhWic.mjs} +2 -2
- package/dist/{import-OvohE-H2.mjs.map → import-Vn9lhWic.mjs.map} +1 -1
- package/dist/{migrate-CroDjbJz.mjs → migrate-skvsDG6d.mjs} +2 -2
- package/dist/{migrate-CroDjbJz.mjs.map → migrate-skvsDG6d.mjs.map} +1 -1
- package/dist/{plan-C2urqJOz.mjs → plan-BLy8FaE2.mjs} +6 -6
- package/dist/{plan-C2urqJOz.mjs.map → plan-BLy8FaE2.mjs.map} +1 -1
- package/dist/{provision-tenant-BJ1KugON.mjs → provision-tenant-CleOYFwr.mjs} +2 -2
- package/dist/{provision-tenant-BJ1KugON.mjs.map → provision-tenant-CleOYFwr.mjs.map} +1 -1
- package/dist/{stackOutputs-Cltzl2g0.mjs → stackOutputs-BLvUMsQO.mjs} +2 -2
- package/dist/{stackOutputs-Cltzl2g0.mjs.map → stackOutputs-BLvUMsQO.mjs.map} +1 -1
- package/dist/{status-DkkS5lc9.mjs → status-BxStsax8.mjs} +3 -3
- package/dist/{status-DkkS5lc9.mjs.map → status-BxStsax8.mjs.map} +1 -1
- package/dist/{sync-CpfxqlOx.mjs → sync-KTzMVc_o.mjs} +4 -4
- package/dist/{sync-CpfxqlOx.mjs.map → sync-KTzMVc_o.mjs.map} +1 -1
- package/dist/tamer.mjs +353 -263
- package/dist/tamer.mjs.map +1 -1
- package/dist/{types-BzzHwIdw.mjs → types-D7qKnGsm.mjs} +2 -2
- package/dist/{types-BzzHwIdw.mjs.map → types-D7qKnGsm.mjs.map} +1 -1
- package/dist/{verifyPlanFile-BmEadIqm.mjs → verifyPlanFile-CR2bELdE.mjs} +2 -2
- package/dist/{verifyPlanFile-BmEadIqm.mjs.map → verifyPlanFile-CR2bELdE.mjs.map} +1 -1
- package/dist/{worker-route-x8q3K4-z.mjs → worker-route-tOqVbhv3.mjs} +2 -2
- package/dist/{worker-route-x8q3K4-z.mjs.map → worker-route-tOqVbhv3.mjs.map} +1 -1
- package/dist/{workers-D3Ekf3mF.mjs → workers-6r2ONF9J.mjs} +2 -2
- package/dist/{workers-D3Ekf3mF.mjs.map → workers-6r2ONF9J.mjs.map} +1 -1
- package/package.json +1 -1
package/dist/tamer.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { c as TAMER_OVERLAY_ENV_KEY, f as getDispatchNamespaces, n as materializeTamerResolvable, r as materializeVars, t as materializeCloudflareBindings } from "./normalize-DVSTRZhO.mjs";
|
|
3
|
-
import { basename, dirname, resolve } from "path";
|
|
3
|
+
import { basename, dirname, relative, resolve } from "path";
|
|
4
4
|
import { existsSync, readFileSync } from "fs";
|
|
5
5
|
import * as readline from "readline/promises";
|
|
6
6
|
|
|
@@ -5553,216 +5553,6 @@ function base64ToBytes(base64$1) {
|
|
|
5553
5553
|
return new Uint8Array(Buffer.from(base64$1, "base64"));
|
|
5554
5554
|
}
|
|
5555
5555
|
|
|
5556
|
-
//#endregion
|
|
5557
|
-
//#region src/core/naming/NamingEngine.ts
|
|
5558
|
-
function reLiteral(s) {
|
|
5559
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5560
|
-
}
|
|
5561
|
-
var NamingEngine = class {
|
|
5562
|
-
constructor(tenant, conventions) {
|
|
5563
|
-
this.tenant = tenant;
|
|
5564
|
-
this.conventions = conventions;
|
|
5565
|
-
}
|
|
5566
|
-
/** Tenant id for per-resource {@link CloudflareNameFn} overrides. */
|
|
5567
|
-
get tenantId() {
|
|
5568
|
-
return this.tenant.id;
|
|
5569
|
-
}
|
|
5570
|
-
d1SingleName(logicalName, env) {
|
|
5571
|
-
if (this.conventions?.d1Single) return this.conventions.d1Single(logicalName, this.tenant.id, env);
|
|
5572
|
-
return `db_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
5573
|
-
}
|
|
5574
|
-
d1ShardName(logicalName, shardDate, env) {
|
|
5575
|
-
if (this.conventions?.d1Shard) return this.conventions.d1Shard(logicalName, shardDate, this.tenant.id, env);
|
|
5576
|
-
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
5577
|
-
if (logicalName === "default" || logicalName === "") return `db_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
5578
|
-
return `db_${logicalName}_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
5579
|
-
}
|
|
5580
|
-
d1SingleBindingKey(logicalName) {
|
|
5581
|
-
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5582
|
-
}
|
|
5583
|
-
d1ShardBindingKey(logicalName, shardDate) {
|
|
5584
|
-
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
5585
|
-
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_${dateNoDashes}_T_${this.tenant.id.toUpperCase()}`;
|
|
5586
|
-
}
|
|
5587
|
-
r2BucketName(logicalName, env) {
|
|
5588
|
-
if (this.conventions?.r2Bucket) {
|
|
5589
|
-
const dateNoDashes = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
5590
|
-
return this.conventions.r2Bucket(logicalName, dateNoDashes, this.tenant.id, env);
|
|
5591
|
-
}
|
|
5592
|
-
return `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
5593
|
-
}
|
|
5594
|
-
/**
|
|
5595
|
-
* Wrangler `r2_buckets[].binding`: logical + tenant only (same idea as {@link kvBindingKey}).
|
|
5596
|
-
* Stable across envs; default {@link r2BucketName} is `r2-{logical}-t-{tenant}-{env}`.
|
|
5597
|
-
*/
|
|
5598
|
-
r2BindingKey(logicalName) {
|
|
5599
|
-
return `R2_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5600
|
-
}
|
|
5601
|
-
kvNamespaceName(logicalName, env) {
|
|
5602
|
-
return `kv_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
5603
|
-
}
|
|
5604
|
-
kvBindingKey(logicalName) {
|
|
5605
|
-
return `KV_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5606
|
-
}
|
|
5607
|
-
queueName(logicalName, env) {
|
|
5608
|
-
return `q-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
5609
|
-
}
|
|
5610
|
-
queueBindingKey(logicalName) {
|
|
5611
|
-
return `Q_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5612
|
-
}
|
|
5613
|
-
hyperdriveName(logicalName, env) {
|
|
5614
|
-
return `hd-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
5615
|
-
}
|
|
5616
|
-
hyperdriveBindingKey(logicalName) {
|
|
5617
|
-
return `HD_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5618
|
-
}
|
|
5619
|
-
vectorizeName(logicalName, env) {
|
|
5620
|
-
return `vec-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
5621
|
-
}
|
|
5622
|
-
vectorizeBindingKey(logicalName) {
|
|
5623
|
-
return `VEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5624
|
-
}
|
|
5625
|
-
/**
|
|
5626
|
-
* AI Gateway slug (== Cloudflare gateway id). Per the Cloudflare API,
|
|
5627
|
-
* gateway ids are case-sensitive lowercase ascii with `-`/`_`. Format:
|
|
5628
|
-
* `aigw-{logical}-t-{tenantId}-{env}`.
|
|
5629
|
-
*/
|
|
5630
|
-
aiGatewayId(logicalName, env) {
|
|
5631
|
-
return `aigw-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
5632
|
-
}
|
|
5633
|
-
/**
|
|
5634
|
-
* Stable cross-reference binding key for AI Gateway. AI Gateway has no
|
|
5635
|
-
* Wrangler binding kind today, so this is only consumed by
|
|
5636
|
-
* `${tamer:ai_gateway:<logical>.binding}` interpolations.
|
|
5637
|
-
*/
|
|
5638
|
-
aiGatewayBindingKey(logicalName) {
|
|
5639
|
-
return `AI_GW_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5640
|
-
}
|
|
5641
|
-
/**
|
|
5642
|
-
* Cloudflare-side pipeline name. Pipelines V1 names must be lowercase
|
|
5643
|
-
* alphanumerics + hyphens (no underscores), so we mirror the R2 scheme.
|
|
5644
|
-
* Pattern: `pipe-{logical}-t-{tenantId}-{env}`.
|
|
5645
|
-
*/
|
|
5646
|
-
pipelineName(logicalName, env) {
|
|
5647
|
-
return `pipe-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
5648
|
-
}
|
|
5649
|
-
/**
|
|
5650
|
-
* Wrangler binding key emitted in `pipelines[]`. Uppercased logical with
|
|
5651
|
-
* the tenant id appended so two tenants can share a worker namespace
|
|
5652
|
-
* without colliding bindings.
|
|
5653
|
-
*/
|
|
5654
|
-
pipelineBindingKey(logicalName) {
|
|
5655
|
-
return `PIPE_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5656
|
-
}
|
|
5657
|
-
pipelineMatchPattern(logicalName, env) {
|
|
5658
|
-
const exact = this.pipelineName(logicalName, env);
|
|
5659
|
-
return (name) => name === exact;
|
|
5660
|
-
}
|
|
5661
|
-
/**
|
|
5662
|
-
* Cloudflare-side workflow name. Workflow names accept lowercase
|
|
5663
|
-
* alphanumerics + hyphens; we mirror the pipelines/AI-Gateway hyphen
|
|
5664
|
-
* scheme. Pattern: `wf-{logical}-t-{tenantId}-{env}`.
|
|
5665
|
-
*/
|
|
5666
|
-
workflowName(logicalName, env) {
|
|
5667
|
-
if (this.conventions?.workflow) return this.conventions.workflow(logicalName, this.tenant.id, env);
|
|
5668
|
-
return `wf-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
5669
|
-
}
|
|
5670
|
-
/**
|
|
5671
|
-
* Wrangler binding key emitted in `workflows[]`. Uppercased logical with
|
|
5672
|
-
* the tenant id appended so two tenants sharing a script can't collide.
|
|
5673
|
-
*/
|
|
5674
|
-
workflowBindingKey(logicalName) {
|
|
5675
|
-
return `WF_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5676
|
-
}
|
|
5677
|
-
workflowMatchPattern(logicalName, env) {
|
|
5678
|
-
const exact = this.workflowName(logicalName, env);
|
|
5679
|
-
return (name) => name === exact;
|
|
5680
|
-
}
|
|
5681
|
-
/**
|
|
5682
|
-
* Cloudflare Secrets Store name. Account-scoped — the API allows free-form
|
|
5683
|
-
* names (the dashboard examples use both `service_x_keys` and dashed
|
|
5684
|
-
* variants), so we mirror our hyphen convention for consistency with
|
|
5685
|
-
* pipelines / workflows / AI Gateway. Pattern:
|
|
5686
|
-
* `sec-{logical}-t-{tenantId}-{env}`.
|
|
5687
|
-
*/
|
|
5688
|
-
secretsStoreName(logicalName, env) {
|
|
5689
|
-
return `sec-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
5690
|
-
}
|
|
5691
|
-
/**
|
|
5692
|
-
* Stable cross-reference key for the store. Secrets Store has no Wrangler
|
|
5693
|
-
* binding kind directly — `secrets_store_secrets[]` references the
|
|
5694
|
-
* resolved `store_id`, not the store name — so this only powers
|
|
5695
|
-
* `${tamer:secret_store:<n>.binding}` interpolations.
|
|
5696
|
-
*/
|
|
5697
|
-
secretsStoreBindingKey(logicalName) {
|
|
5698
|
-
return `SEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
5699
|
-
}
|
|
5700
|
-
secretsStoreMatchPattern(logicalName, env) {
|
|
5701
|
-
const exact = this.secretsStoreName(logicalName, env);
|
|
5702
|
-
return (name) => name === exact;
|
|
5703
|
-
}
|
|
5704
|
-
workerName(workerKey, env) {
|
|
5705
|
-
if (this.conventions?.workerName) return this.conventions.workerName(this.tenant.slug, workerKey, env, this.tenant.id);
|
|
5706
|
-
if (env === "local") return `${this.tenant.slug}-${workerKey}-${this.tenant.id}`;
|
|
5707
|
-
return `${this.tenant.slug}-${workerKey}-${env}-${this.tenant.id}`;
|
|
5708
|
-
}
|
|
5709
|
-
/** Whether stack {@link NamingConventions.d1Shard} is configured. */
|
|
5710
|
-
hasD1ShardConvention() {
|
|
5711
|
-
return Boolean(this.conventions?.d1Shard);
|
|
5712
|
-
}
|
|
5713
|
-
d1MatchPattern(logicalName, env) {
|
|
5714
|
-
if (this.conventions?.d1Shard) return (name) => {
|
|
5715
|
-
const shardDate = this.extractD1ShardDate(name);
|
|
5716
|
-
if (!shardDate) return false;
|
|
5717
|
-
return this.d1ShardName(logicalName, shardDate, env) === name;
|
|
5718
|
-
};
|
|
5719
|
-
const suffix = `_t_${this.tenant.id}_${env}`;
|
|
5720
|
-
if (logicalName === "default" || logicalName === "") return (name) => /^db_\d{8}_t_/.test(name) && name.endsWith(suffix);
|
|
5721
|
-
const prefix = `db_${logicalName}_`;
|
|
5722
|
-
return (name) => name.startsWith(prefix) && name.endsWith(suffix);
|
|
5723
|
-
}
|
|
5724
|
-
/**
|
|
5725
|
-
* Default: exact {@link r2BucketName}, or legacy dated buckets
|
|
5726
|
-
* `r2-{logical}-{YYYYMMDD}-t-{tenant}-{env}` from older Tamer versions.
|
|
5727
|
-
* Custom {@link NamingConventions.r2Bucket}: exact name only (uses today's date
|
|
5728
|
-
* when calling the hook, same as apply).
|
|
5729
|
-
*/
|
|
5730
|
-
r2MatchPattern(logicalName, env) {
|
|
5731
|
-
if (this.conventions?.r2Bucket) {
|
|
5732
|
-
const expected = this.r2BucketName(logicalName, env);
|
|
5733
|
-
return (name) => name === expected;
|
|
5734
|
-
}
|
|
5735
|
-
const exactNew = `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
5736
|
-
const legacyDated = /* @__PURE__ */ new RegExp(`^r2-${reLiteral(logicalName)}-\\d{8}-t-${reLiteral(this.tenant.id)}-${reLiteral(env)}$`);
|
|
5737
|
-
return (name) => name === exactNew || legacyDated.test(name);
|
|
5738
|
-
}
|
|
5739
|
-
extractD1ShardDate(name) {
|
|
5740
|
-
const compact = name.match(/_(\d{8})_t_/);
|
|
5741
|
-
if (compact) {
|
|
5742
|
-
const d = compact[1];
|
|
5743
|
-
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
5744
|
-
}
|
|
5745
|
-
const underscored = name.match(/_(\d{4})_(\d{2})_(\d{2})_t_/);
|
|
5746
|
-
if (underscored) return `${underscored[1]}-${underscored[2]}-${underscored[3]}`;
|
|
5747
|
-
return null;
|
|
5748
|
-
}
|
|
5749
|
-
extractR2Date(name) {
|
|
5750
|
-
const match = name.match(/r2-\w+-(\d{8})-t-/);
|
|
5751
|
-
if (match) {
|
|
5752
|
-
const d = match[1];
|
|
5753
|
-
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
5754
|
-
}
|
|
5755
|
-
return null;
|
|
5756
|
-
}
|
|
5757
|
-
};
|
|
5758
|
-
|
|
5759
|
-
//#endregion
|
|
5760
|
-
//#region src/core/config/namingFromConfig.ts
|
|
5761
|
-
function namingFromConfig(config$1) {
|
|
5762
|
-
const conventions = "naming" in config$1 && config$1.naming ? config$1.naming : void 0;
|
|
5763
|
-
return new NamingEngine(config$1.tenant, conventions);
|
|
5764
|
-
}
|
|
5765
|
-
|
|
5766
5556
|
//#endregion
|
|
5767
5557
|
//#region src/features/dispatch-namespace/dispatch-namespace.resolve.ts
|
|
5768
5558
|
const ephemeralPredicateCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -7314,6 +7104,216 @@ function requiredSecretsForWorker(workerConfig) {
|
|
|
7314
7104
|
return workerConfig.secrets?.required ?? [];
|
|
7315
7105
|
}
|
|
7316
7106
|
|
|
7107
|
+
//#endregion
|
|
7108
|
+
//#region src/core/naming/NamingEngine.ts
|
|
7109
|
+
function reLiteral(s) {
|
|
7110
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7111
|
+
}
|
|
7112
|
+
var NamingEngine = class {
|
|
7113
|
+
constructor(tenant, conventions) {
|
|
7114
|
+
this.tenant = tenant;
|
|
7115
|
+
this.conventions = conventions;
|
|
7116
|
+
}
|
|
7117
|
+
/** Tenant id for per-resource {@link CloudflareNameFn} overrides. */
|
|
7118
|
+
get tenantId() {
|
|
7119
|
+
return this.tenant.id;
|
|
7120
|
+
}
|
|
7121
|
+
d1SingleName(logicalName, env) {
|
|
7122
|
+
if (this.conventions?.d1Single) return this.conventions.d1Single(logicalName, this.tenant.id, env);
|
|
7123
|
+
return `db_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
7124
|
+
}
|
|
7125
|
+
d1ShardName(logicalName, shardDate, env) {
|
|
7126
|
+
if (this.conventions?.d1Shard) return this.conventions.d1Shard(logicalName, shardDate, this.tenant.id, env);
|
|
7127
|
+
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
7128
|
+
if (logicalName === "default" || logicalName === "") return `db_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
7129
|
+
return `db_${logicalName}_${dateNoDashes}_t_${this.tenant.id}_${env}`;
|
|
7130
|
+
}
|
|
7131
|
+
d1SingleBindingKey(logicalName) {
|
|
7132
|
+
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7133
|
+
}
|
|
7134
|
+
d1ShardBindingKey(logicalName, shardDate) {
|
|
7135
|
+
const dateNoDashes = shardDate.replace(/-/g, "");
|
|
7136
|
+
return `DB_${logicalName.toUpperCase().replace(/-/g, "_")}_${dateNoDashes}_T_${this.tenant.id.toUpperCase()}`;
|
|
7137
|
+
}
|
|
7138
|
+
r2BucketName(logicalName, env) {
|
|
7139
|
+
if (this.conventions?.r2Bucket) {
|
|
7140
|
+
const dateNoDashes = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
7141
|
+
return this.conventions.r2Bucket(logicalName, dateNoDashes, this.tenant.id, env);
|
|
7142
|
+
}
|
|
7143
|
+
return `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
7144
|
+
}
|
|
7145
|
+
/**
|
|
7146
|
+
* Wrangler `r2_buckets[].binding`: logical + tenant only (same idea as {@link kvBindingKey}).
|
|
7147
|
+
* Stable across envs; default {@link r2BucketName} is `r2-{logical}-t-{tenant}-{env}`.
|
|
7148
|
+
*/
|
|
7149
|
+
r2BindingKey(logicalName) {
|
|
7150
|
+
return `R2_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7151
|
+
}
|
|
7152
|
+
kvNamespaceName(logicalName, env) {
|
|
7153
|
+
return `kv_${logicalName}_t_${this.tenant.id}_${env}`;
|
|
7154
|
+
}
|
|
7155
|
+
kvBindingKey(logicalName) {
|
|
7156
|
+
return `KV_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7157
|
+
}
|
|
7158
|
+
queueName(logicalName, env) {
|
|
7159
|
+
return `q-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
7160
|
+
}
|
|
7161
|
+
queueBindingKey(logicalName) {
|
|
7162
|
+
return `Q_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7163
|
+
}
|
|
7164
|
+
hyperdriveName(logicalName, env) {
|
|
7165
|
+
return `hd-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
7166
|
+
}
|
|
7167
|
+
hyperdriveBindingKey(logicalName) {
|
|
7168
|
+
return `HD_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7169
|
+
}
|
|
7170
|
+
vectorizeName(logicalName, env) {
|
|
7171
|
+
return `vec-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
7172
|
+
}
|
|
7173
|
+
vectorizeBindingKey(logicalName) {
|
|
7174
|
+
return `VEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7175
|
+
}
|
|
7176
|
+
/**
|
|
7177
|
+
* AI Gateway slug (== Cloudflare gateway id). Per the Cloudflare API,
|
|
7178
|
+
* gateway ids are case-sensitive lowercase ascii with `-`/`_`. Format:
|
|
7179
|
+
* `aigw-{logical}-t-{tenantId}-{env}`.
|
|
7180
|
+
*/
|
|
7181
|
+
aiGatewayId(logicalName, env) {
|
|
7182
|
+
return `aigw-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
7183
|
+
}
|
|
7184
|
+
/**
|
|
7185
|
+
* Stable cross-reference binding key for AI Gateway. AI Gateway has no
|
|
7186
|
+
* Wrangler binding kind today, so this is only consumed by
|
|
7187
|
+
* `${tamer:ai_gateway:<logical>.binding}` interpolations.
|
|
7188
|
+
*/
|
|
7189
|
+
aiGatewayBindingKey(logicalName) {
|
|
7190
|
+
return `AI_GW_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7191
|
+
}
|
|
7192
|
+
/**
|
|
7193
|
+
* Cloudflare-side pipeline name. Pipelines V1 names must be lowercase
|
|
7194
|
+
* alphanumerics + hyphens (no underscores), so we mirror the R2 scheme.
|
|
7195
|
+
* Pattern: `pipe-{logical}-t-{tenantId}-{env}`.
|
|
7196
|
+
*/
|
|
7197
|
+
pipelineName(logicalName, env) {
|
|
7198
|
+
return `pipe-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
7199
|
+
}
|
|
7200
|
+
/**
|
|
7201
|
+
* Wrangler binding key emitted in `pipelines[]`. Uppercased logical with
|
|
7202
|
+
* the tenant id appended so two tenants can share a worker namespace
|
|
7203
|
+
* without colliding bindings.
|
|
7204
|
+
*/
|
|
7205
|
+
pipelineBindingKey(logicalName) {
|
|
7206
|
+
return `PIPE_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7207
|
+
}
|
|
7208
|
+
pipelineMatchPattern(logicalName, env) {
|
|
7209
|
+
const exact = this.pipelineName(logicalName, env);
|
|
7210
|
+
return (name) => name === exact;
|
|
7211
|
+
}
|
|
7212
|
+
/**
|
|
7213
|
+
* Cloudflare-side workflow name. Workflow names accept lowercase
|
|
7214
|
+
* alphanumerics + hyphens; we mirror the pipelines/AI-Gateway hyphen
|
|
7215
|
+
* scheme. Pattern: `wf-{logical}-t-{tenantId}-{env}`.
|
|
7216
|
+
*/
|
|
7217
|
+
workflowName(logicalName, env) {
|
|
7218
|
+
if (this.conventions?.workflow) return this.conventions.workflow(logicalName, this.tenant.id, env);
|
|
7219
|
+
return `wf-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
7220
|
+
}
|
|
7221
|
+
/**
|
|
7222
|
+
* Wrangler binding key emitted in `workflows[]`. Uppercased logical with
|
|
7223
|
+
* the tenant id appended so two tenants sharing a script can't collide.
|
|
7224
|
+
*/
|
|
7225
|
+
workflowBindingKey(logicalName) {
|
|
7226
|
+
return `WF_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7227
|
+
}
|
|
7228
|
+
workflowMatchPattern(logicalName, env) {
|
|
7229
|
+
const exact = this.workflowName(logicalName, env);
|
|
7230
|
+
return (name) => name === exact;
|
|
7231
|
+
}
|
|
7232
|
+
/**
|
|
7233
|
+
* Cloudflare Secrets Store name. Account-scoped — the API allows free-form
|
|
7234
|
+
* names (the dashboard examples use both `service_x_keys` and dashed
|
|
7235
|
+
* variants), so we mirror our hyphen convention for consistency with
|
|
7236
|
+
* pipelines / workflows / AI Gateway. Pattern:
|
|
7237
|
+
* `sec-{logical}-t-{tenantId}-{env}`.
|
|
7238
|
+
*/
|
|
7239
|
+
secretsStoreName(logicalName, env) {
|
|
7240
|
+
return `sec-${logicalName}-t-${this.tenant.id}-${env}`.toLowerCase();
|
|
7241
|
+
}
|
|
7242
|
+
/**
|
|
7243
|
+
* Stable cross-reference key for the store. Secrets Store has no Wrangler
|
|
7244
|
+
* binding kind directly — `secrets_store_secrets[]` references the
|
|
7245
|
+
* resolved `store_id`, not the store name — so this only powers
|
|
7246
|
+
* `${tamer:secret_store:<n>.binding}` interpolations.
|
|
7247
|
+
*/
|
|
7248
|
+
secretsStoreBindingKey(logicalName) {
|
|
7249
|
+
return `SEC_${logicalName.toUpperCase().replace(/-/g, "_")}_T_${this.tenant.id.toUpperCase()}`;
|
|
7250
|
+
}
|
|
7251
|
+
secretsStoreMatchPattern(logicalName, env) {
|
|
7252
|
+
const exact = this.secretsStoreName(logicalName, env);
|
|
7253
|
+
return (name) => name === exact;
|
|
7254
|
+
}
|
|
7255
|
+
workerName(workerKey, env) {
|
|
7256
|
+
if (this.conventions?.workerName) return this.conventions.workerName(this.tenant.slug, workerKey, env, this.tenant.id);
|
|
7257
|
+
if (env === "local") return `${this.tenant.slug}-${workerKey}-${this.tenant.id}`;
|
|
7258
|
+
return `${this.tenant.slug}-${workerKey}-${env}-${this.tenant.id}`;
|
|
7259
|
+
}
|
|
7260
|
+
/** Whether stack {@link NamingConventions.d1Shard} is configured. */
|
|
7261
|
+
hasD1ShardConvention() {
|
|
7262
|
+
return Boolean(this.conventions?.d1Shard);
|
|
7263
|
+
}
|
|
7264
|
+
d1MatchPattern(logicalName, env) {
|
|
7265
|
+
if (this.conventions?.d1Shard) return (name) => {
|
|
7266
|
+
const shardDate = this.extractD1ShardDate(name);
|
|
7267
|
+
if (!shardDate) return false;
|
|
7268
|
+
return this.d1ShardName(logicalName, shardDate, env) === name;
|
|
7269
|
+
};
|
|
7270
|
+
const suffix = `_t_${this.tenant.id}_${env}`;
|
|
7271
|
+
if (logicalName === "default" || logicalName === "") return (name) => /^db_\d{8}_t_/.test(name) && name.endsWith(suffix);
|
|
7272
|
+
const prefix = `db_${logicalName}_`;
|
|
7273
|
+
return (name) => name.startsWith(prefix) && name.endsWith(suffix);
|
|
7274
|
+
}
|
|
7275
|
+
/**
|
|
7276
|
+
* Default: exact {@link r2BucketName}, or legacy dated buckets
|
|
7277
|
+
* `r2-{logical}-{YYYYMMDD}-t-{tenant}-{env}` from older Tamer versions.
|
|
7278
|
+
* Custom {@link NamingConventions.r2Bucket}: exact name only (uses today's date
|
|
7279
|
+
* when calling the hook, same as apply).
|
|
7280
|
+
*/
|
|
7281
|
+
r2MatchPattern(logicalName, env) {
|
|
7282
|
+
if (this.conventions?.r2Bucket) {
|
|
7283
|
+
const expected = this.r2BucketName(logicalName, env);
|
|
7284
|
+
return (name) => name === expected;
|
|
7285
|
+
}
|
|
7286
|
+
const exactNew = `r2-${logicalName}-t-${this.tenant.id}-${env}`;
|
|
7287
|
+
const legacyDated = /* @__PURE__ */ new RegExp(`^r2-${reLiteral(logicalName)}-\\d{8}-t-${reLiteral(this.tenant.id)}-${reLiteral(env)}$`);
|
|
7288
|
+
return (name) => name === exactNew || legacyDated.test(name);
|
|
7289
|
+
}
|
|
7290
|
+
extractD1ShardDate(name) {
|
|
7291
|
+
const compact = name.match(/_(\d{8})_t_/);
|
|
7292
|
+
if (compact) {
|
|
7293
|
+
const d = compact[1];
|
|
7294
|
+
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
7295
|
+
}
|
|
7296
|
+
const underscored = name.match(/_(\d{4})_(\d{2})_(\d{2})_t_/);
|
|
7297
|
+
if (underscored) return `${underscored[1]}-${underscored[2]}-${underscored[3]}`;
|
|
7298
|
+
return null;
|
|
7299
|
+
}
|
|
7300
|
+
extractR2Date(name) {
|
|
7301
|
+
const match = name.match(/r2-\w+-(\d{8})-t-/);
|
|
7302
|
+
if (match) {
|
|
7303
|
+
const d = match[1];
|
|
7304
|
+
return `${d.slice(0, 4)}-${d.slice(4, 6)}-${d.slice(6, 8)}`;
|
|
7305
|
+
}
|
|
7306
|
+
return null;
|
|
7307
|
+
}
|
|
7308
|
+
};
|
|
7309
|
+
|
|
7310
|
+
//#endregion
|
|
7311
|
+
//#region src/core/config/namingFromConfig.ts
|
|
7312
|
+
function namingFromConfig(config$1) {
|
|
7313
|
+
const conventions = "naming" in config$1 && config$1.naming ? config$1.naming : void 0;
|
|
7314
|
+
return new NamingEngine(config$1.tenant, conventions);
|
|
7315
|
+
}
|
|
7316
|
+
|
|
7317
7317
|
//#endregion
|
|
7318
7318
|
//#region src/core/secrets/SecretsVault.ts
|
|
7319
7319
|
/**
|
|
@@ -7543,6 +7543,36 @@ function assertSecretName(name) {
|
|
|
7543
7543
|
if (!trimmed) throw new Error("secret name is required");
|
|
7544
7544
|
return trimmed;
|
|
7545
7545
|
}
|
|
7546
|
+
/** Resolve worker dir + declared secret names for `secrets load`. */
|
|
7547
|
+
async function resolveWorkerSecretsLoadTarget(ctx, workerKey, options) {
|
|
7548
|
+
const baseDir = process.cwd();
|
|
7549
|
+
const workers = await getWorkers(ctx.config, baseDir);
|
|
7550
|
+
const hit = workers.find(([key]) => key === workerKey);
|
|
7551
|
+
if (!hit) {
|
|
7552
|
+
const available = workers.map(([key]) => key).sort().join(", ");
|
|
7553
|
+
throw new Error(`secrets load: worker "${workerKey}" not found in config` + (available ? ` (available: ${available})` : ""));
|
|
7554
|
+
}
|
|
7555
|
+
const [, workerConfig] = hit;
|
|
7556
|
+
const imports = await fetchStackImports(ctx.api, ctx.config, ctx.env).catch(() => ({}));
|
|
7557
|
+
const required$1 = requiredSecretsForWorker(mergeWorkerConfigForResourcePick(ctx.config, workerKey, workerConfig, ctx.env, ctx.accountId, ctx.naming, ctx.state, {
|
|
7558
|
+
referencesMode: "tolerant",
|
|
7559
|
+
imports
|
|
7560
|
+
}));
|
|
7561
|
+
if (required$1.length === 0) {
|
|
7562
|
+
if (options?.skipUndeclared) return null;
|
|
7563
|
+
throw new Error(`secrets load: worker "${workerKey}" has no secrets.required — declare names in config first`);
|
|
7564
|
+
}
|
|
7565
|
+
return {
|
|
7566
|
+
workerKey,
|
|
7567
|
+
workerDir: workerConfig.path ? resolve(baseDir, workerConfig.path) : baseDir,
|
|
7568
|
+
required: required$1
|
|
7569
|
+
};
|
|
7570
|
+
}
|
|
7571
|
+
/** Path for logs — relative to cwd when possible. */
|
|
7572
|
+
function displayPathFromCwd(absOrRel) {
|
|
7573
|
+
const rel = relative(process.cwd(), resolve(process.cwd(), absOrRel));
|
|
7574
|
+
return rel && !rel.startsWith("..") ? rel.replace(/\\/g, "/") : absOrRel.replace(/\\/g, "/");
|
|
7575
|
+
}
|
|
7546
7576
|
/** Vault + master key for deploy auto-push (remote envs only). */
|
|
7547
7577
|
async function createDeploySecretsResources(api, env) {
|
|
7548
7578
|
const resolvedEnv = resolveSecretsEnv(env);
|
|
@@ -7702,9 +7732,25 @@ function parseDotenvContent(content) {
|
|
|
7702
7732
|
function readDotenvFile(filePath) {
|
|
7703
7733
|
return parseDotenvContent(readFileSync(resolve(process.cwd(), filePath), "utf8"));
|
|
7704
7734
|
}
|
|
7705
|
-
/** Default bulk-load file
|
|
7706
|
-
function
|
|
7707
|
-
return
|
|
7735
|
+
/** Default bulk-load file under a worker directory. */
|
|
7736
|
+
function defaultWorkerSecretsLoadFile(workerDir, env) {
|
|
7737
|
+
return `${workerDir.replace(/\\/g, "/")}/.dev.vars.${env}`;
|
|
7738
|
+
}
|
|
7739
|
+
/**
|
|
7740
|
+
* When loading for a worker, only `secrets.required` names are imported.
|
|
7741
|
+
* Returns keys to upsert; throws if the file contains undeclared names.
|
|
7742
|
+
*/
|
|
7743
|
+
function filterSecretsLoadEntriesForWorker(fileEntries, required$1) {
|
|
7744
|
+
const requiredSet = new Set(required$1);
|
|
7745
|
+
const extras = [];
|
|
7746
|
+
const entries = {};
|
|
7747
|
+
for (const [name, value] of Object.entries(fileEntries)) if (requiredSet.has(name)) entries[name] = value;
|
|
7748
|
+
else extras.push(name);
|
|
7749
|
+
if (extras.length > 0) throw new Error(`secrets load: file contains key(s) not in worker secrets.required: ${extras.sort().join(", ")}`);
|
|
7750
|
+
return {
|
|
7751
|
+
entries,
|
|
7752
|
+
missing: required$1.filter((name) => !(name in fileEntries)).sort()
|
|
7753
|
+
};
|
|
7708
7754
|
}
|
|
7709
7755
|
/**
|
|
7710
7756
|
* Reject plain `.dev.vars` — reserved for local `wrangler dev`, not vault seeding.
|
|
@@ -7715,19 +7761,15 @@ function assertRemoteSecretsLoadFile(filePath, env) {
|
|
|
7715
7761
|
|
|
7716
7762
|
//#endregion
|
|
7717
7763
|
//#region src/cli/commands/secrets/load.ts
|
|
7718
|
-
async function
|
|
7719
|
-
const
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
env,
|
|
7724
|
-
configPath: options.configPath
|
|
7725
|
-
});
|
|
7726
|
-
const fileEntries = readDotenvFile(file);
|
|
7764
|
+
async function loadSecretsForWorker(ctx, target, fileOverride) {
|
|
7765
|
+
const file = fileOverride?.trim() || defaultWorkerSecretsLoadFile(target.workerDir, ctx.env);
|
|
7766
|
+
assertRemoteSecretsLoadFile(file, ctx.env);
|
|
7767
|
+
const { entries: fileEntries, missing } = filterSecretsLoadEntriesForWorker(readDotenvFile(file), target.required);
|
|
7768
|
+
if (missing.length > 0) console.log(`secrets load: worker "${target.workerKey}" — skipping ${missing.length} declared secret(s) not in file: ${missing.join(", ")}`);
|
|
7727
7769
|
const names = Object.keys(fileEntries).sort();
|
|
7728
7770
|
if (names.length === 0) {
|
|
7729
|
-
console.log(
|
|
7730
|
-
return;
|
|
7771
|
+
console.log(`secrets load: worker "${target.workerKey}" — no entries to import from ${displayPathFromCwd(file)}`);
|
|
7772
|
+
return 0;
|
|
7731
7773
|
}
|
|
7732
7774
|
let count = 0;
|
|
7733
7775
|
for (const name of names) {
|
|
@@ -7737,7 +7779,37 @@ async function runSecretsLoad(options) {
|
|
|
7737
7779
|
await ctx.vault.upsert(name, encrypted, valueHash, { updatedBy: cliUpdatedBy() });
|
|
7738
7780
|
count += 1;
|
|
7739
7781
|
}
|
|
7740
|
-
console.log(`secrets: loaded ${count} secret(s) into ${ctx.env} vault from ${file}`);
|
|
7782
|
+
console.log(`secrets: loaded ${count} secret(s) into ${ctx.env} vault from ${displayPathFromCwd(file)} (worker ${target.workerKey})`);
|
|
7783
|
+
return count;
|
|
7784
|
+
}
|
|
7785
|
+
async function listWorkerSecretsLoadTargets(ctx, workerFilter) {
|
|
7786
|
+
const workers = await getWorkers(ctx.config, process.cwd());
|
|
7787
|
+
const out = [];
|
|
7788
|
+
for (const [workerKey] of workers) {
|
|
7789
|
+
if (workerFilter && workerKey !== workerFilter) continue;
|
|
7790
|
+
const target = await resolveWorkerSecretsLoadTarget(ctx, workerKey, { skipUndeclared: !workerFilter });
|
|
7791
|
+
if (target) out.push(target);
|
|
7792
|
+
}
|
|
7793
|
+
return out;
|
|
7794
|
+
}
|
|
7795
|
+
async function runSecretsLoad(options) {
|
|
7796
|
+
const env = resolveSecretsEnv(options.env);
|
|
7797
|
+
const workerKey = options.worker?.trim();
|
|
7798
|
+
const fileOverride = options.file?.trim();
|
|
7799
|
+
if (fileOverride && !workerKey) throw new Error("secrets load: --file requires --worker <name>");
|
|
7800
|
+
const ctx = await createSecretsContext({
|
|
7801
|
+
env,
|
|
7802
|
+
configPath: options.configPath
|
|
7803
|
+
});
|
|
7804
|
+
const targets = await listWorkerSecretsLoadTargets(ctx, workerKey);
|
|
7805
|
+
if (targets.length === 0) {
|
|
7806
|
+
const hint = workerKey ? `worker "${workerKey}" has no secrets.required` : "no workers declare secrets.required";
|
|
7807
|
+
console.log(`secrets load (${ctx.env}): ${hint}`);
|
|
7808
|
+
return;
|
|
7809
|
+
}
|
|
7810
|
+
let total = 0;
|
|
7811
|
+
for (const target of targets) total += await loadSecretsForWorker(ctx, target, workerKey ? fileOverride : void 0);
|
|
7812
|
+
if (!workerKey && targets.length > 1) console.log(`secrets load (${ctx.env}): ${total} secret(s) from ${targets.length} worker(s)`);
|
|
7741
7813
|
}
|
|
7742
7814
|
|
|
7743
7815
|
//#endregion
|
|
@@ -7969,13 +8041,7 @@ function secretsDrift(entries) {
|
|
|
7969
8041
|
detail: "removed from vault"
|
|
7970
8042
|
});
|
|
7971
8043
|
break;
|
|
7972
|
-
case "undeclared_on_worker":
|
|
7973
|
-
drift.unrecordedInState.push({
|
|
7974
|
-
logicalName: e.name,
|
|
7975
|
-
derivedName,
|
|
7976
|
-
detail: "undeclared on worker"
|
|
7977
|
-
});
|
|
7978
|
-
break;
|
|
8044
|
+
case "undeclared_on_worker": break;
|
|
7979
8045
|
}
|
|
7980
8046
|
}
|
|
7981
8047
|
return drift;
|
|
@@ -8030,8 +8096,20 @@ const STATUS_LABEL = {
|
|
|
8030
8096
|
never_deployed: "never deployed",
|
|
8031
8097
|
rotated_not_deployed: "rotated, not deployed",
|
|
8032
8098
|
removed_from_vault: "removed from vault",
|
|
8033
|
-
undeclared_on_worker: "
|
|
8099
|
+
undeclared_on_worker: "not in secrets.required"
|
|
8034
8100
|
};
|
|
8101
|
+
function isDeclaredIssue(status) {
|
|
8102
|
+
return status !== "in_sync" && status !== "undeclared_on_worker";
|
|
8103
|
+
}
|
|
8104
|
+
function sortEntries(entries) {
|
|
8105
|
+
return [...entries].sort((a, b) => secretDerivedName(a.worker, a.name).localeCompare(secretDerivedName(b.worker, b.name)));
|
|
8106
|
+
}
|
|
8107
|
+
function printEntry(entry) {
|
|
8108
|
+
const label = STATUS_LABEL[entry.status];
|
|
8109
|
+
const id = secretDerivedName(entry.worker, entry.name);
|
|
8110
|
+
const workerFlag = entry.onWorker ? "on worker" : "not on worker";
|
|
8111
|
+
console.log(` ${id} ${label} (${workerFlag})`);
|
|
8112
|
+
}
|
|
8035
8113
|
async function runSecretsVerify(options) {
|
|
8036
8114
|
const ctx = await createSecretsContext({
|
|
8037
8115
|
env: options.env,
|
|
@@ -8051,21 +8129,31 @@ async function runSecretsVerify(options) {
|
|
|
8051
8129
|
vault: vaultReaderFromVault(ctx.vault),
|
|
8052
8130
|
state: ctx.state
|
|
8053
8131
|
});
|
|
8132
|
+
const declared = sortEntries(entries.filter((e) => e.status !== "undeclared_on_worker"));
|
|
8133
|
+
const onWorkerOnly = sortEntries(entries.filter((e) => e.status === "undeclared_on_worker"));
|
|
8054
8134
|
console.log(`\nSecrets verify — env ${ctx.env}\n`);
|
|
8055
|
-
if (
|
|
8135
|
+
if (declared.length === 0 && onWorkerOnly.length === 0) {
|
|
8056
8136
|
console.log(" (no declared secrets)\n");
|
|
8057
8137
|
return 0;
|
|
8058
8138
|
}
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
const
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8139
|
+
if (declared.length > 0) {
|
|
8140
|
+
console.log(" Declared in config (secrets.required):\n");
|
|
8141
|
+
for (const entry of declared) printEntry(entry);
|
|
8142
|
+
console.log("");
|
|
8143
|
+
}
|
|
8144
|
+
if (onWorkerOnly.length > 0) {
|
|
8145
|
+
console.log(" On worker, not in secrets.required (outside Tamer management — add to config or remove from worker):\n");
|
|
8146
|
+
for (const entry of onWorkerOnly) printEntry(entry);
|
|
8147
|
+
console.log("");
|
|
8148
|
+
}
|
|
8149
|
+
const declaredIssues = declared.filter((e) => isDeclaredIssue(e.status)).length;
|
|
8150
|
+
if (declaredIssues === 0) {
|
|
8151
|
+
const suffix = onWorkerOnly.length > 0 ? ` (${onWorkerOnly.length} on worker but not in config — informational only)` : "";
|
|
8152
|
+
console.log(`All declared secrets in sync.${suffix}\n`);
|
|
8153
|
+
return 0;
|
|
8066
8154
|
}
|
|
8067
|
-
console.log(
|
|
8068
|
-
return
|
|
8155
|
+
console.log(`${declaredIssues} declared secret(s) need attention.\n`);
|
|
8156
|
+
return 1;
|
|
8069
8157
|
}
|
|
8070
8158
|
|
|
8071
8159
|
//#endregion
|
|
@@ -8156,7 +8244,8 @@ async function runSecretsPush(options) {
|
|
|
8156
8244
|
const SECRETS_USAGE = `usage:
|
|
8157
8245
|
tamer secrets init --env <env> [--config <path>]
|
|
8158
8246
|
tamer secrets set <NAME> --env <env> [--config <path>] # value on stdin (pipe only)
|
|
8159
|
-
tamer secrets load --env <env> [--file <path>] [--config <path>]
|
|
8247
|
+
tamer secrets load --env <env> [--worker <name>] [--file <path>] [--config <path>]
|
|
8248
|
+
# each worker: {workerDir}/.dev.vars.{env}; all declared workers when --worker omitted
|
|
8160
8249
|
tamer secrets get <NAME> --env <env> [--config <path>] # confirmation + audit log
|
|
8161
8250
|
tamer secrets list --env <env> [--config <path>]
|
|
8162
8251
|
tamer secrets rm <NAME> --env <env> [--config <path>]
|
|
@@ -8207,7 +8296,8 @@ async function runSecrets(argv) {
|
|
|
8207
8296
|
await runSecretsLoad({
|
|
8208
8297
|
file: parsed.file,
|
|
8209
8298
|
env: parsed.env,
|
|
8210
|
-
configPath: parsed.configPath
|
|
8299
|
+
configPath: parsed.configPath,
|
|
8300
|
+
worker: parsed.worker
|
|
8211
8301
|
});
|
|
8212
8302
|
return 0;
|
|
8213
8303
|
case "get":
|
|
@@ -8548,14 +8638,14 @@ async function main() {
|
|
|
8548
8638
|
try {
|
|
8549
8639
|
switch (command) {
|
|
8550
8640
|
case "bootstrap":
|
|
8551
|
-
await import("./bootstrap-
|
|
8641
|
+
await import("./bootstrap-CQS5s33A.mjs").then((m) => m.runBootstrap(parseBootstrapArgs(rest)));
|
|
8552
8642
|
break;
|
|
8553
8643
|
case "sync":
|
|
8554
|
-
await import("./sync-
|
|
8644
|
+
await import("./sync-KTzMVc_o.mjs").then((m) => m.runSync(parseSyncArgs(rest)));
|
|
8555
8645
|
break;
|
|
8556
8646
|
case "apply": {
|
|
8557
8647
|
const a = parseApplyArgs(rest);
|
|
8558
|
-
await import("./apply-
|
|
8648
|
+
await import("./apply-C_70Hgcf.mjs").then((m) => m.runApply({
|
|
8559
8649
|
env: a.env,
|
|
8560
8650
|
addShard: a.addShard,
|
|
8561
8651
|
configPath: a.configPath,
|
|
@@ -8567,11 +8657,11 @@ async function main() {
|
|
|
8567
8657
|
break;
|
|
8568
8658
|
}
|
|
8569
8659
|
case "dev":
|
|
8570
|
-
await import("./dev-
|
|
8660
|
+
await import("./dev-caJxohHI.mjs").then((m) => m.runDev(parseDevArgs(rest)));
|
|
8571
8661
|
break;
|
|
8572
8662
|
case "deploy": {
|
|
8573
8663
|
const d = parseDeployArgs(rest);
|
|
8574
|
-
await import("./deploy-
|
|
8664
|
+
await import("./deploy-D-GXzsWR.mjs").then((m) => m.runDeploy({
|
|
8575
8665
|
worker: d.worker,
|
|
8576
8666
|
env: d.env,
|
|
8577
8667
|
configPath: d.configPath,
|
|
@@ -8580,23 +8670,23 @@ async function main() {
|
|
|
8580
8670
|
break;
|
|
8581
8671
|
}
|
|
8582
8672
|
case "migrate":
|
|
8583
|
-
await import("./migrate-
|
|
8673
|
+
await import("./migrate-skvsDG6d.mjs").then((m) => m.runMigrate(parseMigrateArgs(rest)));
|
|
8584
8674
|
break;
|
|
8585
8675
|
case "types":
|
|
8586
|
-
await import("./types-
|
|
8676
|
+
await import("./types-D7qKnGsm.mjs").then((m) => m.runTypes(parseTypesArgs(rest)));
|
|
8587
8677
|
break;
|
|
8588
8678
|
case "status":
|
|
8589
|
-
await import("./status-
|
|
8679
|
+
await import("./status-BxStsax8.mjs").then((m) => m.runStatus(parseStatusArgs(rest)));
|
|
8590
8680
|
break;
|
|
8591
8681
|
case "events":
|
|
8592
|
-
await import("./events-
|
|
8682
|
+
await import("./events-Bor7XgLC.mjs").then((m) => m.runEvents(parseEventsArgs(rest)));
|
|
8593
8683
|
break;
|
|
8594
8684
|
case "drift":
|
|
8595
|
-
exitStatus = await import("./drift-
|
|
8685
|
+
exitStatus = await import("./drift-5_LwAdZo.mjs").then((m) => m.runDrift(parseDriftArgs(rest)));
|
|
8596
8686
|
break;
|
|
8597
8687
|
case "plan": {
|
|
8598
8688
|
const p = parsePlanArgs(rest);
|
|
8599
|
-
exitStatus = await import("./plan-
|
|
8689
|
+
exitStatus = await import("./plan-BLy8FaE2.mjs").then((m) => m.runPlan({
|
|
8600
8690
|
env: p.env,
|
|
8601
8691
|
configPath: p.configPath,
|
|
8602
8692
|
json: p.json,
|
|
@@ -8608,14 +8698,14 @@ async function main() {
|
|
|
8608
8698
|
break;
|
|
8609
8699
|
}
|
|
8610
8700
|
case "import":
|
|
8611
|
-
await import("./import-
|
|
8701
|
+
await import("./import-Vn9lhWic.mjs").then((m) => m.runImport(parseImportArgs(rest)));
|
|
8612
8702
|
break;
|
|
8613
8703
|
case "doctor":
|
|
8614
8704
|
exitStatus = await import("./doctor-32YLAXXl.mjs").then((m) => m.runDoctor(parseDoctorArgs(rest)));
|
|
8615
8705
|
break;
|
|
8616
8706
|
case "provision-tenant": {
|
|
8617
8707
|
const p = parseProvisionTenantArgs(rest);
|
|
8618
|
-
await import("./provision-tenant-
|
|
8708
|
+
await import("./provision-tenant-CleOYFwr.mjs").then((m) => m.runProvisionTenant({
|
|
8619
8709
|
env: p.env,
|
|
8620
8710
|
product: p.product,
|
|
8621
8711
|
workspace: p.workspace,
|
|
@@ -8632,7 +8722,7 @@ async function main() {
|
|
|
8632
8722
|
}
|
|
8633
8723
|
case "destroy-tenant": {
|
|
8634
8724
|
const t = parseDestroyTenantArgs(rest);
|
|
8635
|
-
await import("./destroy-tenant-
|
|
8725
|
+
await import("./destroy-tenant-DFHfNImL.mjs").then((m) => m.runDestroyTenant({
|
|
8636
8726
|
env: t.env,
|
|
8637
8727
|
product: t.product,
|
|
8638
8728
|
workspace: t.workspace,
|
|
@@ -8645,7 +8735,7 @@ async function main() {
|
|
|
8645
8735
|
}
|
|
8646
8736
|
case "destroy": {
|
|
8647
8737
|
const d = parseDestroyArgs(rest);
|
|
8648
|
-
await import("./destroy-
|
|
8738
|
+
await import("./destroy-DJRw_qLX.mjs").then((m) => m.runDestroy({
|
|
8649
8739
|
env: d.env,
|
|
8650
8740
|
force: d.force,
|
|
8651
8741
|
skipWorkers: d.skipWorkers,
|
|
@@ -8731,7 +8821,7 @@ Options:
|
|
|
8731
8821
|
Secrets (requires TAMER_SECRETS_KEY_{env} master key env var):
|
|
8732
8822
|
tamer secrets init --env <env> Generate master key (print once) + provision vault
|
|
8733
8823
|
tamer secrets set <NAME> --env <env> Encrypt value from stdin into vault (pipe only)
|
|
8734
|
-
tamer secrets load --env <env> [--file .dev.vars.<env>] Bulk import
|
|
8824
|
+
tamer secrets load --env <env> [--worker <name>] [--file .dev.vars.<env>] Bulk import; all workers when --worker omitted
|
|
8735
8825
|
tamer secrets get <NAME> --env <env> Decrypt + print (confirmation + audit log)
|
|
8736
8826
|
tamer secrets list --env <env> Names + fingerprints + last-set (never values)
|
|
8737
8827
|
tamer secrets rm <NAME> --env <env> Remove from vault
|
|
@@ -8765,5 +8855,5 @@ Environment variables (same as Wrangler):
|
|
|
8765
8855
|
main();
|
|
8766
8856
|
|
|
8767
8857
|
//#endregion
|
|
8768
|
-
export {
|
|
8858
|
+
export { rewriteIntraStackServiceTargets as A, getWorkers as B, tamerStateDatabaseName as C, mergedWorkerConfigForEnv as D, mergeWorkerConfigForResourcePick as E, ensureTamerSecretsDatabase as F, tamerSecretsDatabaseName as I, CFApiClient as L, wranglerConfigCliArgs as M, effectiveDispatchNamespaceName as N, resolveDeployedWorkerName as O, isEphemeralEnv as P, cloudflareAccountIdFromEnv as R, ensureTamerStateDatabase as S, buildIntraStackScriptNameMap as T, loadConfig as V, tenantDispatchScriptName as _, reconcileSecrets as a, createEmptyCfiState as b, vaultReaderFromMap as c, requiredSecretsForWorker as d, fetchStackImports as f, parseTenantShardRoles as g, StateManager as h, pushSecretsForDeploy as i, resolveReferencesInString as j, resolveWorkerConfig as k, createDeploySecretsResources as l, scanConfigForImports as m, parseSecretsArgs as n, secretsDrift as o, importedStackNames as p, runSecrets as r, secretsPlanItems as s, SECRETS_USAGE as t, namingFromConfig as u, tenantShardDatabaseName as v, stackNameForConfig as w, destroyTamerStateDatabase as x, tenantStateKey as y, cloudflareApiTokenFromEnv as z };
|
|
8769
8859
|
//# sourceMappingURL=tamer.mjs.map
|