@pithy-sh/core 0.6.1 → 0.7.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.
Files changed (56) hide show
  1. package/dist/capability/capability.d.ts.map +1 -1
  2. package/dist/capability/capability.js +2 -0
  3. package/dist/capability/settings.d.ts +15 -2
  4. package/dist/capability/settings.d.ts.map +1 -1
  5. package/dist/data/databases.d.ts +11 -0
  6. package/dist/data/databases.d.ts.map +1 -1
  7. package/dist/migrations/registry.d.ts +6 -0
  8. package/dist/migrations/registry.d.ts.map +1 -1
  9. package/dist/migrations/registry.js +2 -0
  10. package/dist/migrations/retained.d.ts +101 -0
  11. package/dist/migrations/retained.d.ts.map +1 -0
  12. package/dist/migrations/retained.js +243 -0
  13. package/dist/migrations/retainedDeclaration.d.ts +15 -0
  14. package/dist/migrations/retainedDeclaration.d.ts.map +1 -0
  15. package/dist/migrations/retainedDeclaration.js +49 -0
  16. package/dist/migrations/runner.d.ts +44 -7
  17. package/dist/migrations/runner.d.ts.map +1 -1
  18. package/dist/migrations/runner.js +41 -15
  19. package/dist/naming/environment.d.ts +12 -0
  20. package/dist/naming/environment.d.ts.map +1 -1
  21. package/dist/naming/environment.js +38 -1
  22. package/dist/naming/feature.d.ts +7 -1
  23. package/dist/naming/feature.d.ts.map +1 -1
  24. package/dist/naming/feature.js +10 -3
  25. package/dist/naming/provisionScope.d.ts +97 -9
  26. package/dist/naming/provisionScope.d.ts.map +1 -1
  27. package/dist/naming/provisionScope.js +87 -12
  28. package/dist/naming/resourceNames.d.ts +5 -2
  29. package/dist/naming/resourceNames.d.ts.map +1 -1
  30. package/dist/naming/resourceNames.js +1 -1
  31. package/dist/text/comments.d.ts +14 -0
  32. package/dist/text/comments.d.ts.map +1 -1
  33. package/dist/text/comments.js +28 -2
  34. package/dist/version.generated.d.ts +1 -1
  35. package/dist/version.generated.js +1 -1
  36. package/dist/workflow/host.d.ts +8 -0
  37. package/dist/workflow/host.d.ts.map +1 -1
  38. package/dist/workflow/host.js +5 -2
  39. package/dist/workflow/hostEnv.d.ts +1 -1
  40. package/dist/workflow/hostEnv.js +1 -1
  41. package/package.json +1 -1
  42. package/src/capability/capability.ts +6 -0
  43. package/src/capability/settings.ts +15 -2
  44. package/src/data/databases.ts +11 -0
  45. package/src/migrations/registry.ts +10 -0
  46. package/src/migrations/retained.ts +319 -0
  47. package/src/migrations/retainedDeclaration.ts +56 -0
  48. package/src/migrations/runner.ts +89 -15
  49. package/src/naming/environment.ts +43 -0
  50. package/src/naming/feature.ts +10 -3
  51. package/src/naming/provisionScope.ts +130 -13
  52. package/src/naming/resourceNames.ts +6 -3
  53. package/src/text/comments.ts +31 -1
  54. package/src/version.generated.ts +1 -1
  55. package/src/workflow/host.ts +14 -4
  56. package/src/workflow/hostEnv.ts +1 -1
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  import type { D1Database } from "@cloudflare/workers-types";
4
4
  import { type MigrationProvider, type MigrationResult } from "kysely/migration";
5
+ import { RetainedBudget } from "./retained";
5
6
  /**
6
7
  * Which database a run is reporting on — what a failure names.
7
8
  *
@@ -16,6 +17,19 @@ export interface MigrationTarget {
16
17
  /** The database name: a capability's `databases` key. Throw-site context, not the adopter's handle. */
17
18
  database: string;
18
19
  }
20
+ /**
21
+ * What a caller that reverses migrations says about retained rows (#588) — see `./retained`.
22
+ *
23
+ * Optional, and absent is the safe answer: a caller that says nothing has counted nothing, so any `down`
24
+ * against a database holding retained rows is refused.
25
+ */
26
+ export interface RetainedConsent {
27
+ /**
28
+ * The retained rows the caller agreed to destroy. Pass one budget to every database in a run, so one
29
+ * agreement is spent once; a caller reversing a single database builds its own. Absent means none.
30
+ */
31
+ budget?: RetainedBudget;
32
+ }
19
33
  /** Run every pending migration to latest. An empty provider resolves to `[]`. */
20
34
  export declare function runMigrations(database: D1Database, provider: MigrationProvider, target?: MigrationTarget): Promise<MigrationResult[]>;
21
35
  /** One database's ledger beside the declaration it is supposed to match — see {@link readMigrationLedger}. */
@@ -46,24 +60,47 @@ export interface MigrationLedger {
46
60
  * warn-only "schema is behind" check, and the refusal `pithy migrate` raises before it writes.
47
61
  */
48
62
  export declare function readMigrationLedger(database: D1Database, provider: MigrationProvider): Promise<MigrationLedger>;
49
- /** Step the latest applied migration back — one step, the `pithy migrate --rollback` seam. */
50
- export declare function rollbackMigration(database: D1Database, provider: MigrationProvider, target?: MigrationTarget): Promise<MigrationResult[]>;
63
+ /**
64
+ * Step this database's latest applied migration back — one step, per database. `pithy migrate --rollback`
65
+ * calls it once for **every** database in its fan-out. Refused while a retained table here holds rows the
66
+ * caller has not counted in `consent` (#588).
67
+ */
68
+ export declare function rollbackMigration(database: D1Database, provider: MigrationProvider, target?: MigrationTarget, consent?: RetainedConsent): Promise<MigrationResult[]>;
51
69
  /**
52
70
  * Fully reset one database's schema: every applied migration's `down` runs, in one pass, in reverse
53
71
  * chronological order — Kysely's `NO_MIGRATIONS` target, not just the latest — then every migration's
54
72
  * `up` reapplies from empty. The seam behind `pithy seed --redo`'s destructive rebuild: because the
55
73
  * schema comes back empty, the ordinary non-destructive seed writes (`INSERT OR IGNORE`, KV
56
74
  * skip-if-exists) simply work afterward — there is no per-row identity problem to solve. An empty
57
- * ledger rolls back nothing; an empty provider reapplies nothing.
75
+ * ledger rolls back nothing; an empty provider reapplies nothing. Refused, before the first `down`, while a
76
+ * retained table here holds rows the caller has not counted in `consent` (#588).
77
+ */
78
+ export declare function resetMigrations(database: D1Database, provider: MigrationProvider, target?: MigrationTarget, consent?: RetainedConsent): Promise<MigrationResult[]>;
79
+ /**
80
+ * What a drop reverses, and the database it reverses it in.
81
+ *
82
+ * Two providers because they answer two questions. `reverse` is the part being removed — one capability's
83
+ * migrations. `database` is every migration composed into that D1, and it is what the retained guard counts:
84
+ * a table is retained in a *database*, and the capability being dropped is the one least likely to declare
85
+ * the vault it shares a database with (#588). Handed only the part, the guard counted what the part declared
86
+ * — nothing — while the vault beside it held rows.
58
87
  */
59
- export declare function resetMigrations(database: D1Database, provider: MigrationProvider, target?: MigrationTarget): Promise<MigrationResult[]>;
88
+ export interface DropSelection {
89
+ /** Every migration composed into this database — the set whose retained declarations are counted. */
90
+ database: MigrationProvider;
91
+ /** The migrations to reverse: a part of `database`, by composed name. */
92
+ reverse: MigrationProvider;
93
+ }
60
94
  /**
61
- * Surgically drop **one capability's** migrations: run each of the provider's `down` functions in
95
+ * Surgically drop **one capability's** migrations: run each of `drop.reverse`'s `down` functions in
62
96
  * reverse order and delete only those ledger rows, leaving every other capability's tables and
63
97
  * bookkeeping untouched. The seam behind `pithy remove --drop`. Kysely's stepwise `Migrator` refuses a
64
98
  * provider that doesn't span the whole ledger (it reads a foreign row as corrupt state), so a
65
99
  * per-capability drop can't go through it — this reverses the capability's own migrations directly.
66
- * Only migrations recorded in the ledger are reversed; an absent ledger drops nothing.
100
+ * Only migrations recorded in the ledger are reversed; an absent ledger drops nothing. Refused, before the
101
+ * first `down`, while a retained table **anywhere in `drop.database`** holds rows the caller has not counted
102
+ * in `consent` (#588). A name `drop.reverse` carries that `drop.database` does not is an internal fault: the
103
+ * guard would not have counted the database the `down` runs in.
67
104
  */
68
- export declare function dropMigrations(database: D1Database, provider: MigrationProvider, target?: MigrationTarget): Promise<MigrationResult[]>;
105
+ export declare function dropMigrations(database: D1Database, drop: DropSelection, target?: MigrationTarget, consent?: RetainedConsent): Promise<MigrationResult[]>;
69
106
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAA2B,MAAM,kBAAkB,CAAC;AA0DzG;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,OAAO,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iFAAiF;AACjF,wBAAsB,aAAa,CACjC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED,8GAA8G;AAC9G,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAOrH;AAED,8FAA8F;AAC9F,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAO5B;AAgBD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CA+B5B"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/migrations/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAA2B,MAAM,kBAAkB,CAAC;AAKzG,OAAO,EAAgC,cAAc,EAAE,MAAM,YAAY,CAAC;AA4D1E;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,OAAO,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAUD,iFAAiF;AACjF,wBAAsB,aAAa,CACjC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED,8GAA8G;AAC9G,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAOrH;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CAO5B;AAgBD;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,qGAAqG;IACrG,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,yEAAyE;IACzE,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,eAAe,EAAE,CAAC,CA4C5B"}
@@ -4,6 +4,7 @@ import { InternalError } from "../error/pithyError.js";
4
4
  import { causeMessage } from "../error/cause.js";
5
5
  import { MIGRATION_LOCK_TABLE, MIGRATION_TABLE, migrationKysely } from "./bookkeeping.js";
6
6
  import { batchedProvider } from "./batch.js";
7
+ import { RetainedBudget, guardRetained, isDownRefusal } from "./retained.js";
7
8
  import { sql } from "kysely";
8
9
  import { Migrator, NO_MIGRATIONS } from "kysely/migration";
9
10
  //#region src/migrations/runner.ts
@@ -46,18 +47,25 @@ import { Migrator, NO_MIGRATIONS } from "kysely/migration";
46
47
  * capability arrives with its whole set. Refusing the add with an actionable error was the
47
48
  * alternative; it explains the corner instead of removing it.
48
49
  */
49
- function migrator(database, provider) {
50
+ function migrator(database, provider, target, consent) {
50
51
  return new Migrator({
51
52
  db: migrationKysely(database),
52
- provider: batchedProvider(provider, database),
53
+ provider: batchedProvider(guardRetained(provider, database, guardOptions(target, consent)), database),
53
54
  migrationTableName: MIGRATION_TABLE,
54
55
  migrationLockTableName: MIGRATION_LOCK_TABLE,
55
56
  allowUnorderedMigrations: true
56
57
  });
57
58
  }
59
+ /** The guard's options: the binding its refusal names, and the budget the caller agreed to. */
60
+ function guardOptions(target, consent) {
61
+ return {
62
+ binding: target?.binding ?? "this database",
63
+ budget: consent?.budget ?? new RetainedBudget(void 0)
64
+ };
65
+ }
58
66
  /** Run every pending migration to latest. An empty provider resolves to `[]`. */
59
67
  async function runMigrations(database, provider, target) {
60
- const { error, results } = await migrator(database, provider).migrateToLatest();
68
+ const { error, results } = await migrator(database, provider, target, void 0).migrateToLatest();
61
69
  return settle("run", error, results, target);
62
70
  }
63
71
  /**
@@ -85,9 +93,13 @@ async function readMigrationLedger(database, provider) {
85
93
  undeclared: [...applied].filter((name) => !declared.includes(name)).sort()
86
94
  };
87
95
  }
88
- /** Step the latest applied migration back — one step, the `pithy migrate --rollback` seam. */
89
- async function rollbackMigration(database, provider, target) {
90
- const { error, results } = await migrator(database, provider).migrateDown();
96
+ /**
97
+ * Step this database's latest applied migration back — one step, per database. `pithy migrate --rollback`
98
+ * calls it once for **every** database in its fan-out. Refused while a retained table here holds rows the
99
+ * caller has not counted in `consent` (#588).
100
+ */
101
+ async function rollbackMigration(database, provider, target, consent) {
102
+ const { error, results } = await migrator(database, provider, target, consent).migrateDown();
91
103
  return settle("rollback", error, results, target);
92
104
  }
93
105
  /**
@@ -96,10 +108,11 @@ async function rollbackMigration(database, provider, target) {
96
108
  * `up` reapplies from empty. The seam behind `pithy seed --redo`'s destructive rebuild: because the
97
109
  * schema comes back empty, the ordinary non-destructive seed writes (`INSERT OR IGNORE`, KV
98
110
  * skip-if-exists) simply work afterward — there is no per-row identity problem to solve. An empty
99
- * ledger rolls back nothing; an empty provider reapplies nothing.
111
+ * ledger rolls back nothing; an empty provider reapplies nothing. Refused, before the first `down`, while a
112
+ * retained table here holds rows the caller has not counted in `consent` (#588).
100
113
  */
101
- async function resetMigrations(database, provider, target) {
102
- const runner = migrator(database, provider);
114
+ async function resetMigrations(database, provider, target, consent) {
115
+ const runner = migrator(database, provider, target, consent);
103
116
  const down = await runner.migrateTo(NO_MIGRATIONS);
104
117
  const downResults = settle("resetDown", down.error, down.results, target);
105
118
  const up = await runner.migrateToLatest();
@@ -117,19 +130,30 @@ async function appliedMigrationNames(db) {
117
130
  return new Set(rows.map((row) => row.name));
118
131
  }
119
132
  /**
120
- * Surgically drop **one capability's** migrations: run each of the provider's `down` functions in
133
+ * Surgically drop **one capability's** migrations: run each of `drop.reverse`'s `down` functions in
121
134
  * reverse order and delete only those ledger rows, leaving every other capability's tables and
122
135
  * bookkeeping untouched. The seam behind `pithy remove --drop`. Kysely's stepwise `Migrator` refuses a
123
136
  * provider that doesn't span the whole ledger (it reads a foreign row as corrupt state), so a
124
137
  * per-capability drop can't go through it — this reverses the capability's own migrations directly.
125
- * Only migrations recorded in the ledger are reversed; an absent ledger drops nothing.
138
+ * Only migrations recorded in the ledger are reversed; an absent ledger drops nothing. Refused, before the
139
+ * first `down`, while a retained table **anywhere in `drop.database`** holds rows the caller has not counted
140
+ * in `consent` (#588). A name `drop.reverse` carries that `drop.database` does not is an internal fault: the
141
+ * guard would not have counted the database the `down` runs in.
126
142
  */
127
- async function dropMigrations(database, provider, target) {
143
+ async function dropMigrations(database, drop, target, consent) {
128
144
  const db = migrationKysely(database);
129
- const migrations = await batchedProvider(provider, database).getMigrations();
145
+ const guarded = guardRetained(drop.database, database, guardOptions(target, consent));
146
+ const migrations = await batchedProvider(guarded, database).getMigrations();
147
+ const reversing = Object.keys(await drop.reverse.getMigrations());
148
+ const stray = reversing.filter((name) => !(name in migrations));
149
+ if (stray.length > 0) throw new InternalError({
150
+ message: `Couldn't drop ${stray.map((name) => `"${name}"`).join(", ")}${on(target)}. The database's migrations do not carry it.`,
151
+ detail: `${where(target)} A drop counts retained rows over the database's whole set, so every migration it reverses must be in it.`,
152
+ action: "Build the drop from the database's composed migrations. Nothing was dropped."
153
+ });
130
154
  const applied = await appliedMigrationNames(db);
131
155
  const results = [];
132
- for (const name of Object.keys(migrations).sort().reverse()) {
156
+ for (const name of reversing.sort().reverse()) {
133
157
  if (!applied.has(name)) continue;
134
158
  const down = migrations[name]?.down;
135
159
  if (!down) continue;
@@ -142,6 +166,7 @@ async function dropMigrations(database, provider, target) {
142
166
  status: "Success"
143
167
  });
144
168
  } catch (error) {
169
+ if (isDownRefusal(error)) throw error;
145
170
  const dropped = results.map((result) => `"${result.migrationName}"`);
146
171
  throw new InternalError({
147
172
  message: `Couldn't drop "${name}"${on(target)}. ${reasonOf(error)}`,
@@ -162,7 +187,7 @@ const VOICE = {
162
187
  rollback: {
163
188
  failed: (key) => `Couldn't roll back "${key}"`,
164
189
  fallback: "The rollback failed",
165
- action: "Fix the migration. Run pithy migrate --rollback again."
190
+ action: "Fix the migration's down. Run pithy doctor to see where each database stands."
166
191
  },
167
192
  resetDown: {
168
193
  failed: (key) => `Couldn't roll back "${key}" during reset`,
@@ -203,6 +228,7 @@ function reasonOf(error) {
203
228
  }
204
229
  function settle(verb, error, results, target) {
205
230
  if (error !== void 0) {
231
+ if (isDownRefusal(error)) throw error;
206
232
  const voice = VOICE[verb];
207
233
  const failed = results?.find((result) => result.status === "Error");
208
234
  const applied = results?.filter((result) => result.status === "Success").map((result) => result.migrationName);
@@ -43,6 +43,18 @@ export declare const GLOBAL_SCOPE = "global";
43
43
  * that rejects it would be a cycle.
44
44
  */
45
45
  export declare const FEATURE_ENVIRONMENT = "feature";
46
+ /**
47
+ * **The segment a feature takes where an environment sits** — `f<issue>`, as in `<project>-f69-demo-db-d1`.
48
+ *
49
+ * Defined here, beside the environment rule, because the two share a slot in every composed name and the
50
+ * environment rule has to refuse this shape: `feature.ts` composes a feature's head with it, and
51
+ * {@link isValidEnvironment} refuses an environment that starts with one. A marker composed in one module and
52
+ * recognized in another would be two statements of one shape, and the next person to change one would not
53
+ * find the other.
54
+ */
55
+ export declare function featureMarker(issue: string): string;
56
+ /** Is this whole hyphen-delimited segment a feature's marker? `f1` and `f01` are; `f1a` and `feature` are not. */
57
+ export declare function isFeatureMarker(segment: string): boolean;
46
58
  /**
47
59
  * The longest an environment name may be — **the longest canonical one, `staging`**.
48
60
  *
@@ -1 +1 @@
1
- {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/naming/environment.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,YAAI,KAAK,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAEhE,wGAAwG;AACxG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,QAAqE,CAAC;AAEvG;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA4BzD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,YAAI,SAAS,EAAE,MAAM,CAAU,CAAC;AAEjE;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oBAAoB,yBA2D9B,CAAC;AAEJ,sGAAsG;AACtG,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/naming/environment.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,YAAI,KAAK,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAEhE,wGAAwG;AACxG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAKD,kHAAkH;AAClH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAgBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,QAAqE,CAAC;AAEvG;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxD;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmCzD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,YAAI,SAAS,EAAE,MAAM,CAAU,CAAC;AAEjE;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oBAAoB,yBA2D9B,CAAC;AAEJ,sGAAsG;AACtG,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -49,6 +49,37 @@ const GLOBAL_SCOPE = "global";
49
49
  */
50
50
  const FEATURE_ENVIRONMENT = "feature";
51
51
  /**
52
+ * **The segment a feature takes where an environment sits** — `f<issue>`, as in `<project>-f69-demo-db-d1`.
53
+ *
54
+ * Defined here, beside the environment rule, because the two share a slot in every composed name and the
55
+ * environment rule has to refuse this shape: `feature.ts` composes a feature's head with it, and
56
+ * {@link isValidEnvironment} refuses an environment that starts with one. A marker composed in one module and
57
+ * recognized in another would be two statements of one shape, and the next person to change one would not
58
+ * find the other.
59
+ */
60
+ function featureMarker(issue) {
61
+ return `f${issue}`;
62
+ }
63
+ /** Every string {@link featureMarker} can compose: an `f` and one or more digits, as a whole segment. */
64
+ const FEATURE_MARKER = /^f[0-9]+$/;
65
+ /** Is this whole hyphen-delimited segment a feature's marker? `f1` and `f01` are; `f1a` and `feature` are not. */
66
+ function isFeatureMarker(segment) {
67
+ return FEATURE_MARKER.test(segment);
68
+ }
69
+ /**
70
+ * Does this environment start where a feature's name does?
71
+ *
72
+ * **Exactly the environments that can collide with a feature (#587).** A declared environment composes
73
+ * `<project>-<env>-<thing>`, a feature `<project>-f<issue>-<slug>-<thing>`, and a feature Worker's name has no
74
+ * kind suffix to tell the two apart. After the shared `<project>-`, the two strings can only be equal when the
75
+ * environment's first segment is the feature's marker — `f1-demo` meets feature 1-demo's Worker `api`, and `f1`
76
+ * meets it too, through a Worker called `demo-api`. Any other first segment differs from every marker, so no
77
+ * name composed under it can be a feature's. So this is the whole rule, not one case of it.
78
+ */
79
+ function startsWithFeatureMarker(name) {
80
+ return isFeatureMarker(name.split("-")[0] ?? "");
81
+ }
82
+ /**
52
83
  * The longest an environment name may be — **the longest canonical one, `staging`**.
53
84
  *
54
85
  * This is a derivation input, not a preference: `WORKFLOW_DERIVED_PROJECT_NAME` and
@@ -72,6 +103,7 @@ const MAX_ENVIRONMENT_NAME = Math.max(...ENVIRONMENTS.map((environment) => envir
72
103
  */
73
104
  function isValidEnvironment(name) {
74
105
  if (name === "global") return false;
106
+ if (startsWithFeatureMarker(name)) return false;
75
107
  return name.length <= MAX_ENVIRONMENT_NAME && NAME_SEGMENT.test(name);
76
108
  }
77
109
  /**
@@ -94,6 +126,11 @@ function assertValidEnvironment(name) {
94
126
  action: `Name the environment one of ${ENVIRONMENTS.join(", ")}.`,
95
127
  detail: `${GLOBAL_SCOPE} occupies the environment slot of a composed name for values shared across every environment.`
96
128
  });
129
+ if (startsWithFeatureMarker(name)) throw new ValidationError({
130
+ message: `"${name}" starts the way a feature's name does.`,
131
+ action: "Start the environment with something other than f and a number.",
132
+ detail: `A feature takes the environment's slot with f<issue>, so <project>-${name}-<worker> can be a feature's Worker name exactly, and \`pithy feature destroy\` deletes that Worker.`
133
+ });
97
134
  if (name.length > MAX_ENVIRONMENT_NAME && NAME_SEGMENT.test(name)) throw new ValidationError({
98
135
  message: `"${name}" is ${name.length} characters. An environment stops at ${MAX_ENVIRONMENT_NAME}.`,
99
136
  action: `Use one of ${ENVIRONMENTS.join(", ")}, or a shorter name.`,
@@ -189,4 +226,4 @@ const DeclaredEnvironments = z.array(z.string().describe("One deployed environme
189
226
  }
190
227
  }).describe("Every deployed environment this project has, in the order provisioning walks them — least-production first. Declared once in the root pithy.config.ts, because the set cannot be per-Worker. `dev` is never listed: it is local and always present.");
191
228
  //#endregion
192
- export { DEFAULT_ENVIRONMENTS, DeclaredEnvironments, ENVIRONMENTS, FEATURE_ENVIRONMENT, GLOBAL_SCOPE, LOCAL_ENVIRONMENT, MAX_ENVIRONMENT_NAME, assertValidEnvironment, isValidEnvironment };
229
+ export { DEFAULT_ENVIRONMENTS, DeclaredEnvironments, ENVIRONMENTS, FEATURE_ENVIRONMENT, GLOBAL_SCOPE, LOCAL_ENVIRONMENT, MAX_ENVIRONMENT_NAME, assertValidEnvironment, featureMarker, isFeatureMarker, isValidEnvironment };
@@ -65,6 +65,12 @@ export declare function featureSecretEntryName(identity: FeatureIdentity, secret
65
65
  * floored the slug at one character and never touched the worker segment, so it ran unbounded — 69
66
66
  * characters for a worker called `collaboration-realtime-gateway`, 109 for a 70-character one. `apps/<name>`
67
67
  * has a charset rule and no length rule, so nothing upstream was going to stop it either.
68
+ *
69
+ * **`app` is the `apps/<app>` directory, never the deploy name.** A scaffolded Worker deploys as
70
+ * `<project>-<app>`, and handing that here composed `<project>-f<issue>-<slug>-<project>-<app>` — the
71
+ * project twice, spent out of the budget above (#587). This function takes a string and cannot tell the
72
+ * two apart, so the provisioning path reaches it only through `featureScope`, which is handed both names
73
+ * and picks.
68
74
  */
69
- export declare function featureWorkerName(identity: FeatureIdentity, worker: string): string;
75
+ export declare function featureWorkerName(identity: FeatureIdentity, app: string): string;
70
76
  //# sourceMappingURL=feature.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../../src/naming/feature.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;GAgBG;AAEH,iHAAiH;AACjH,MAAM,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD,6EAA6E;AAC7E,eAAO,MAAM,sBAAsB,EAAE,SAAS,mBAAmB,EAAuB,CAAC;AAEzF,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;CACd;AAkED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAQjH;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQxF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF"}
1
+ {"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../../src/naming/feature.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AAEH,iHAAiH;AACjH,MAAM,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD,6EAA6E;AAC7E,eAAO,MAAM,sBAAsB,EAAE,SAAS,mBAAmB,EAAuB,CAAC;AAEzF,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;CACd;AAkED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAQjH;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQxF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhF"}
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { ValidationError } from "../error/pithyError.js";
4
+ import { featureMarker } from "./environment.js";
4
5
  import { NAMESPACE_LIMITS } from "./limits.js";
5
6
  import { assertValidProjectName, fitSegment, kebab } from "./resource.js";
6
7
  //#region src/naming/feature.ts
@@ -32,7 +33,7 @@ function assertIssue(issue) {
32
33
  function head(identity) {
33
34
  assertValidProjectName(identity.project);
34
35
  assertIssue(identity.issue);
35
- return `${kebab(identity.project)}-f${identity.issue}`;
36
+ return `${kebab(identity.project)}-${featureMarker(identity.issue)}`;
36
37
  }
37
38
  /**
38
39
  * Fit `<head>-<slug>-<tail><fixed>` into `budget`, truncating the slug first and the tail only if the
@@ -100,9 +101,15 @@ function featureSecretEntryName(identity, secret) {
100
101
  * floored the slug at one character and never touched the worker segment, so it ran unbounded — 69
101
102
  * characters for a worker called `collaboration-realtime-gateway`, 109 for a 70-character one. `apps/<name>`
102
103
  * has a charset rule and no length rule, so nothing upstream was going to stop it either.
104
+ *
105
+ * **`app` is the `apps/<app>` directory, never the deploy name.** A scaffolded Worker deploys as
106
+ * `<project>-<app>`, and handing that here composed `<project>-f<issue>-<slug>-<project>-<app>` — the
107
+ * project twice, spent out of the budget above (#587). This function takes a string and cannot tell the
108
+ * two apart, so the provisioning path reaches it only through `featureScope`, which is handed both names
109
+ * and picks.
103
110
  */
104
- function featureWorkerName(identity, worker) {
105
- return composeFeatureName(head(identity), kebab(identity.slug), kebab(worker), "", NAMESPACE_LIMITS.worker.maxLength);
111
+ function featureWorkerName(identity, app) {
112
+ return composeFeatureName(head(identity), kebab(identity.slug), kebab(app), "", NAMESPACE_LIMITS.worker.maxLength);
106
113
  }
107
114
  //#endregion
108
115
  export { FEATURE_RESOURCE_KINDS, featureResourceName, featureSecretEntryName, featureWorkerName };
@@ -74,6 +74,27 @@ export interface BindingNaming {
74
74
  export interface ProjectGlobalNaming extends BindingNaming {
75
75
  readonly scope: "global";
76
76
  }
77
+ /**
78
+ * The two names one Worker answers to before a scope has named it — **and why a scope is handed both.**
79
+ *
80
+ * `pithy init replay --worker board` writes `apps/board/wrangler.jsonc` with `"name": "replay-board"`.
81
+ * So the Worker's directory says `board` and its deploy name says `replay-board`, and the two scopes need
82
+ * different ones. A declared environment's fallback is wrangler's own `<script>-<env>`, which is built on
83
+ * the deploy name. A feature's name is `<project>-f<issue>-<slug>-<app>`, which already leads with the
84
+ * project, so it is built on the directory.
85
+ *
86
+ * This was one string until #587, and the string was the deploy name, so every feature Worker carried the
87
+ * project twice: `replay-f69-demo-replay-board`. That was not only untidy. The name is held to the Worker
88
+ * cap of 63, and the doubled segment spent that budget where the truncation lands on the part that says
89
+ * *which* Worker. Carrying both names is what lets each scope take the one its shape is built from, and
90
+ * lets neither caller choose on the scope's behalf.
91
+ */
92
+ export interface ProvisionWorkerNames {
93
+ /** The Worker's `apps/<app>` directory basename — the name a sibling's `service` binding targets it by. */
94
+ readonly app: string;
95
+ /** The Worker's deploy name — the top-level `name` of its `wrangler.jsonc`, e.g. `replay-board`. */
96
+ readonly script: string;
97
+ }
77
98
  /** Where a provisioning run's resources are named, and where their ids are written. */
78
99
  export interface ProvisionScope {
79
100
  /** The `env.<stanza>` key in each Worker's config that this scope's ids are written into. */
@@ -118,8 +139,18 @@ export interface ProvisionScope {
118
139
  * is created, judged to be the project's, kept out of the teardown record, and orphaned.
119
140
  */
120
141
  readonly honorsGlobal: boolean;
121
- /** The script name a Worker deploys under in this scope. */
122
- worker(worker: string): string;
142
+ /**
143
+ * The script name a Worker deploys under in this scope.
144
+ *
145
+ * `worker` carries **both** of the Worker's names, because the two scopes compose from different ones:
146
+ * a declared environment falls back to wrangler's `<script>-<env>`, and a feature composes
147
+ * `<project>-f<issue>-<slug>-<app>`. See {@link ProvisionWorkerNames}.
148
+ *
149
+ * `declared` is the name that scope's stanza already carries, when it carries one. A scope may honor it
150
+ * or compose its own; see {@link environmentScope} and {@link featureScope}, which answer differently
151
+ * and say why. Passing it is how a caller asks the scope rather than deciding for itself.
152
+ */
153
+ worker(worker: ProvisionWorkerNames, declared?: string): string;
123
154
  /**
124
155
  * This scope's CF Secrets Store entry name for a declared secret.
125
156
  *
@@ -158,6 +189,22 @@ export interface ProvisionScope {
158
189
  */
159
190
  export declare function bindingResourceName(project: string, binding: string, kind: FeatureResourceKind, naming: ProjectGlobalNaming): string;
160
191
  export declare function bindingResourceName(project: string, binding: string, kind: FeatureResourceKind, naming: BindingNaming, scoped: (thing: string) => string): string;
192
+ /**
193
+ * **Is this name inside a feature's namespace** — `<project>-f<issue>-…`, the project and then a feature's
194
+ * marker, with something after it?
195
+ *
196
+ * The namespace, not one feature's names, because that is what has to stay disjoint: `pithy feature destroy`
197
+ * deletes by exact name, and a feature Worker's name has no kind suffix, so a declared environment's name
198
+ * that lands anywhere in here is one some branch's teardown can delete (#587). Every name {@link featureScope}
199
+ * composes is inside; {@link environmentScope} refuses to name a Worker inside, and `isValidEnvironment`
200
+ * refuses every environment whose composed names could be.
201
+ *
202
+ * **What it does not see.** It is stated for one project. A second project on the same account whose name is
203
+ * this one's plus `-f<issue>` — `acme-f1` beside `acme` — composes names inside `acme`'s namespace from an
204
+ * ordinary environment, and nothing here can tell, because a project name carries no boundary a later hyphen
205
+ * cannot fake. That is the hyphen ambiguity every composed name carries, one segment further left.
206
+ */
207
+ export declare function isFeatureName(project: string, name: string): boolean;
161
208
  /**
162
209
  * A declared environment's scope — `staging`, `prod`, or whatever the root `pithy.config.ts` lists.
163
210
  *
@@ -165,13 +212,25 @@ export declare function bindingResourceName(project: string, binding: string, ki
165
212
  * every name below, so an illegal one must fail before anything is created rather than at the fourth
166
213
  * getter that happened to use it.
167
214
  *
168
- * **A Worker's script name is wrangler's own, `<script>-<env>`, deliberately.** It is the one name here
169
- * that is not `<project>-<env>-<thing>`, because `wrangler deploy --env staging` has always appended the
170
- * environment to the top-level `name` — so every project that ever deployed is already at that address.
171
- * A Worker script is a `refuse`-policy namespace precisely because renaming one orphans the deployment
172
- * and every `service` binding pointing at it; composing a "more correct" name here would do exactly
173
- * that, silently, on the next deploy. The name is written out rather than left implicit so a service
174
- * binding and a deploy agree on one string that is in the file.
215
+ * **A declared name wins; the fallback is wrangler's own, `<script>-<env>`.**
216
+ *
217
+ * This reverses the rule that stood here until #580, and the reversal is worth reading rather than
218
+ * assuming. The old rule *recomputed* `<script>-<env>` on every provision and wrote it over whatever the
219
+ * stanza said, on the argument that wrangler has always appended the environment to the top-level `name`,
220
+ * so every project that ever deployed is already at that address.
221
+ *
222
+ * That argument is still true about the **fallback**, and the fallback is unchanged: a stanza that names
223
+ * nothing gets `<script>-<env>` and every existing adopter deploys exactly where they always did. What was
224
+ * wrong was recomputing over a name somebody wrote down. Since #580 the starter template writes one —
225
+ * `<project>-<env>-<worker>`, the shape every other resource here takes — so recompute would have made the
226
+ * template's stamp pointless, and worse: it would have silently renamed the Worker of every project that
227
+ * had taken the new shape, on their next `pithy provision`. A Worker script is a `refuse`-policy namespace
228
+ * precisely because renaming one orphans the deployment, its routes, and every `service` binding pointing
229
+ * at it. Doing that as a side effect of provisioning is the failure the old rule was written to prevent,
230
+ * arriving from the other direction.
231
+ *
232
+ * So the name is read, not composed, when the file already holds one — and written out when it does not,
233
+ * so a service binding and a deploy still agree on one string that is in the file.
175
234
  */
176
235
  export declare function environmentScope(project: string, environment: string): ProvisionScope;
177
236
  /**
@@ -193,6 +252,35 @@ export declare function environmentScope(project: string, environment: string):
193
252
  * `resource` is ignored for the same reason it is moot: a feature's `<thing>` segment is the binding plus
194
253
  * the kind, and the whole name is recomputed on teardown rather than looked up, so nothing outside the
195
254
  * feature reads the string.
255
+ *
256
+ * **And a declared Worker name is ignored here too — the other half of the #580 asymmetry.** A declared
257
+ * environment's script name is the adopter's, written in a tracked file, and provisioning reads it. A
258
+ * feature's is the kit's: it is composed from the branch, written into a generated config nobody commits,
259
+ * and **recomputed on teardown**. Honoring a declared one would leave `pithy feature destroy` computing a
260
+ * name the deployment does not answer to, which is a Worker nothing deletes.
196
261
  */
197
262
  export declare function featureScope(identity: FeatureIdentity): ProvisionScope;
263
+ /**
264
+ * **Every script name one Worker can be deployed under in a feature — what teardown looks for (#592).**
265
+ *
266
+ * The first is the name {@link featureScope} composes today, taken from the scope rather than composed a
267
+ * second time, so provisioning and teardown cannot disagree about it. The second is the one it composed
268
+ * until #587, from the deploy name: `<project>-f<issue>-<slug>-<project>-<app>`. A feature provisioned and
269
+ * deployed before that upgrade is still running under it, and after its next deploy it runs under both —
270
+ * so teardown looks for both. One entry when the two coincide, as they do for a Worker whose deploy name
271
+ * is its directory.
272
+ *
273
+ * **Exact names, never a prefix.** A prefix scan of `<project>-f<issue>-<slug>-` reaches a sibling whose
274
+ * slug extends this one's. The exact names can still meet a sibling in one shape: the doubled name for
275
+ * slug `demo` and deploy name `acme-api` is the current name for slug `demo-acme` and directory `api`, on
276
+ * the same issue number. That is the same hyphen ambiguity every feature name here carries.
277
+ *
278
+ * **They cannot meet a declared environment's Worker**, which has no suffix either and is `<project>-<env>-<app>`
279
+ * since #580: every name either shape yields is inside {@link isFeatureName}'s namespace, no environment may
280
+ * start with a feature's marker, and {@link environmentScope} refuses a declared or fallback Worker name inside
281
+ * it. What that does not reach is a name nothing in the kit chose — a stanza written by hand and deployed
282
+ * without `pithy provision --env` ever reading it, or another project on the account, as {@link isFeatureName}
283
+ * says.
284
+ */
285
+ export declare function featureWorkerScriptNames(identity: FeatureIdentity, worker: ProvisionWorkerNames): string[];
198
286
  //# sourceMappingURL=provisionScope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provisionScope.d.ts","sourceRoot":"","sources":["../../src/naming/provisionScope.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAIzB,MAAM,WAAW,CAAC;AAGnB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IACpF;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,MAAM,CAAC;CACnE;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,mBAAmB,GAC1B,MAAM,CAAC;AACV,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAAC;AAsBV;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CAerF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,cAAc,CAatE"}
1
+ {"version":3,"file":"provisionScope.d.ts","sourceRoot":"","sources":["../../src/naming/provisionScope.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAIzB,MAAM,WAAW,CAAC;AAInB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAoB;IACnC,2GAA2G;IAC3G,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oGAAoG;IACpG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IACpF;;;;;;;;;OASG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE;;;;;;OAMG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,MAAM,CAAC;CACnE;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,mBAAmB,GAC1B,MAAM,CAAC;AACV,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAAC;AAsBV;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CA6BrF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,cAAc,CAetE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAI1G"}