@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
@@ -1 +1 @@
1
- {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/capability/capability.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/capability/capability.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { BindingSpec } from "./bindings.js";
4
+ import { declareRetained } from "../migrations/retainedDeclaration.js";
4
5
  //#region src/capability/capability.ts
5
6
  /**
6
7
  * Author a capability. Parses each binding through `BindingSpec` — normalizing `optional`
@@ -9,6 +10,7 @@ import { BindingSpec } from "./bindings.js";
9
10
  * `databases`/`kvNamespaces` literals so `createBackend` can infer the merged registries.
10
11
  */
11
12
  function defineCapability(input) {
13
+ for (const spec of Object.values(input.databases ?? {})) if (spec.migrations && spec.retained) declareRetained(spec.migrations, spec.retained);
12
14
  return {
13
15
  ...input,
14
16
  requiredBindings: input.requiredBindings.map((binding) => BindingSpec.parse(binding))
@@ -84,11 +84,24 @@ export interface SettingsAccountReader {
84
84
  d1Databases(): Promise<readonly string[]>;
85
85
  /** Whether this account holds a Cloudflare zone covering the hostname — the prerequisite for onboarding it. */
86
86
  zone(hostname: string): Promise<boolean>;
87
- /** Whether a declared secret has a value in that environment. The name is the registry's, not a binding's. */
88
- secret(request: {
87
+ /**
88
+ * Whether that environment's **D1 vault** holds a value under this registry name — asked of its manager
89
+ * Worker, the only thing that can open it.
90
+ *
91
+ * Named for the store it asks, because it used to be `secret()` — "does this secret have a value" — and
92
+ * that question has two stores behind it (#596). A check asking it about a `cf-secrets-store` secret got a
93
+ * confident `false` from a vault the secret never lives in. Ask {@link storeEntry} about one of those.
94
+ */
95
+ vaultSecret(request: {
89
96
  name: string;
90
97
  environment: string;
91
98
  }): Promise<boolean>;
99
+ /**
100
+ * Whether the account's **Secrets Store** holds an entry of exactly this name. The name is the entry's, not
101
+ * the registry's: compose it with `environmentScope(project, env).secretEntry(...)`, the namer provisioning
102
+ * created it with, so the check looks where the value went.
103
+ */
104
+ storeEntry(name: string): Promise<boolean>;
92
105
  }
93
106
  /** What the account tier is told: everything the local tier gets, plus the account it may ask. */
94
107
  export interface SettingsAccountContext extends SettingsCheckContext {
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/capability/settings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,mFAAmF;AACnF,eAAO,MAAM,eAAe;;;;;iBA0B+D,CAAC;AAC5F,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,4GAA4G;AAC5G,MAAM,WAAW,oBAAoB;IACnC,gGAAgG;IAChG,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,WAAW,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC1C,+GAA+G;IAC/G,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,8GAA8G;IAC9G,MAAM,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAED,kGAAkG;AAClG,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,yDAAyD;IACzD,OAAO,EAAE,qBAAqB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,CAAC,OAAO,EAAE,oBAAoB,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACrF,wGAAwG;IACxG,OAAO,CAAC,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,EAAE,CAO7G"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/capability/settings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,mFAAmF;AACnF,eAAO,MAAM,eAAe;;;;;iBA0B+D,CAAC;AAC5F,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,4GAA4G;AAC5G,MAAM,WAAW,oBAAoB;IACnC,gGAAgG;IAChG,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,WAAW,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC1C,+GAA+G;IAC/G,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC;;;;;;;OAOG;IACH,WAAW,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9E;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED,kGAAkG;AAClG,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,yDAAyD;IACzD,OAAO,EAAE,qBAAqB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,CAAC,OAAO,EAAE,oBAAoB,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACrF,wGAAwG;IACxG,OAAO,CAAC,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,EAAE,CAO7G"}
@@ -26,6 +26,17 @@ export interface DatabaseSpec<Tables extends SchemaMap = SchemaMap> {
26
26
  migrations?: Record<string, Migration>;
27
27
  /** Sort order within this database relative to other capabilities (core low, app high). Required with `migrations`. */
28
28
  migrationOrder?: number;
29
+ /**
30
+ * The tables in this slice whose rows **exist nowhere else** — a vault's sealed credentials, a
31
+ * suppression list of people who asked not to be mailed. Keys of `tables`, declared beside the
32
+ * `migrations` that create them (required with them).
33
+ *
34
+ * A schema `down` is right to drop a table; for these it destroys the only copy. So while one of them
35
+ * holds rows, no `down` runs against this database — a rollback, a `seed --redo` reset, a
36
+ * `remove --drop` — unless the operator passes the exact row count (`--destroy-retained <n>`). The
37
+ * refusal lives in the migration runner, so a new command that reverses migrations inherits it (#588).
38
+ */
39
+ retained?: readonly (keyof Tables & string)[];
29
40
  }
30
41
  /** A capability's databases: database name → {@link DatabaseSpec}. */
31
42
  export type DatabaseSpecMap = Record<string, DatabaseSpec>;
@@ -1 +1 @@
1
- {"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../src/data/databases.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAA2C,MAAM,uBAAuB,CAAC;AACnG,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS;IAChE,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,uHAAuH;IACvH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,GAAG,SAAS,eAAe,IAAI;KACnD,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,YAAY,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK;CAC3G,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,eAAe,CAO5E;AAED,uGAAuG;AACvG,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,eAAe,GAAG,cAAc,CAaxG"}
1
+ {"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../src/data/databases.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAA2C,MAAM,uBAAuB,CAAC;AACnG,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS;IAChE,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,uHAAuH;IACvH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC/C;AAED,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,GAAG,SAAS,eAAe,IAAI;KACnD,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,YAAY,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK;CAC3G,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,eAAe,CAO5E;AAED,uGAAuG;AACvG,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,eAAe,GAAG,cAAc,CAaxG"}
@@ -18,6 +18,12 @@ export interface NamespacedMigrations {
18
18
  order: number;
19
19
  /** Stable, per-namespace keys, each `^\d{4}_[a-z0-9_]+$` (e.g. "0001_init"). */
20
20
  migrations: Record<string, Migration>;
21
+ /**
22
+ * The table keys (camelCase, as the capability's `tables` declares them) this set's capability retains
23
+ * in this database — rows that exist nowhere else. Recorded on this set's `down`s, and the runner refuses
24
+ * any `down` against the database while one of them holds rows. See `./retained`.
25
+ */
26
+ retained?: readonly string[];
21
27
  }
22
28
  /**
23
29
  * Merge namespaced migration sets into one ordered `MigrationProvider` **per database** — matching
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/migrations/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrE,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,QAAyB,CAAC;AAE1D,mGAAmG;AACnG,eAAO,MAAM,iBAAiB,QAAqB,CAAC;AAKpD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACvC;AA6DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAavG"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/migrations/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAOrE,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,QAAyB,CAAC;AAE1D,mGAAmG;AACnG,eAAO,MAAM,iBAAiB,QAAqB,CAAC;AAKpD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAgED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAavG"}
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { InternalError } from "../error/pithyError.js";
4
+ import { declareRetained } from "./retainedDeclaration.js";
4
5
  //#region src/migrations/registry.ts
5
6
  /** Width of the zero-padded `order` prefix in a composed key — the stable anchor. */
6
7
  const ORDER_DIGITS = 4;
@@ -40,6 +41,7 @@ function composeDatabase(database, sets) {
40
41
  if (migration) composed[`${prefix}_${set.namespace}_${localKey}`] = migration;
41
42
  }
42
43
  }
44
+ for (const set of sets) declareRetained(set.migrations, set.retained ?? []);
43
45
  return { getMigrations: async () => composed };
44
46
  }
45
47
  /**
@@ -0,0 +1,101 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import type { D1Database } from "@cloudflare/workers-types";
4
+ import type { Migration, MigrationProvider } from "kysely/migration";
5
+ import { ValidationError } from "../error/pithyError";
6
+ /** The SQL name of a declared table key — `pithySecretsSystemSecrets` → `pithy_secrets_system_secrets`. */
7
+ export declare function retainedTableName(key: string): string;
8
+ /** One retained table that holds rows, on the binding it was counted through. */
9
+ export interface RetainedRows {
10
+ /** The D1 binding the table lives behind — the name an adopter recognizes. */
11
+ binding: string;
12
+ /** The SQL table name. */
13
+ table: string;
14
+ /** How many rows it holds. Always positive: an empty or absent table is not at risk. */
15
+ rows: number;
16
+ }
17
+ /** The SQL names of the retained tables a provider's migrations declare. Reads no database. */
18
+ export declare function retainedTableNames(provider: MigrationProvider): Promise<string[]>;
19
+ /**
20
+ * Count the rows in every retained table these migrations declare that is present in the database.
21
+ * Read-only. Returns only the tables holding rows, so an empty result means nothing retained is at risk.
22
+ */
23
+ export declare function countRetainedRows(database: D1Database, migrations: Readonly<Record<string, Migration>>, binding: string): Promise<RetainedRows[]>;
24
+ /**
25
+ * Mark an error as a refusal to run a `down`, so it reaches the operator as itself rather than as a failed
26
+ * migration. For a guard written outside this module — the CLI's shared-database floor is one.
27
+ */
28
+ export declare function downRefusal<E extends ValidationError>(error: E): E;
29
+ /** Whether `error` refused a `down` before it ran — as opposed to a migration that failed. */
30
+ export declare function isDownRefusal(error: unknown): error is ValidationError;
31
+ /**
32
+ * What a refusal was raised ahead of, as the sentence ends: `Refused before <this>.` A `down` for the
33
+ * runner and the migration fan-out; a database deletion for a teardown that removes the database whole
34
+ * (#591), where "any down ran" would name an operation that was never going to happen.
35
+ */
36
+ export type RefusedBefore = "any down against them ran" | "anything was deleted";
37
+ /**
38
+ * The refusal, in one wording for every place that raises it — the fan-out's preflight, which names every
39
+ * database before any of them moves, {@link guardRetained}, which is the floor under it, and a teardown
40
+ * that deletes a database holding retained tables (`pithy secrets deprovision`, #591).
41
+ *
42
+ * `consent` is what the caller passed. The action always prints the number that would work, because that
43
+ * number is the one fact the operator has to read before typing it.
44
+ */
45
+ export declare function retainedRefusal(atRisk: readonly RetainedRows[], consent: number | undefined, before?: RefusedBefore): ValidationError;
46
+ /**
47
+ * **The preflight: refuse unless the operator counted exactly the retained rows in scope.**
48
+ *
49
+ * Absent a count, only an empty scope passes; given one, only the same number does — a count that is too
50
+ * high is a count of something else, and agreeing to it would let a stale number from shell history through
51
+ * the day the rows it described are joined by more. Call it with every database the operation will touch,
52
+ * counted before the first of them moves, so the refusal names them all with nothing changed.
53
+ *
54
+ * The floor under it is {@link RetainedBudget}, fed the operator's number and never this function's
55
+ * count.
56
+ */
57
+ export declare function assertRetainedAgreed(atRisk: readonly RetainedRows[], consent: number | undefined, before?: RefusedBefore): void;
58
+ /**
59
+ * **How many retained rows a run has agreed to destroy, spent as each database is reached.**
60
+ *
61
+ * One per run, shared by every database in it. Absent an agreement it holds nothing, so any retained row
62
+ * refuses. A database whose rows exceed what is left is refused whole — nothing is spent on a refusal.
63
+ */
64
+ export declare class RetainedBudget {
65
+ #private;
66
+ /** What the caller agreed to, as they typed it — the number a refusal quotes back. */
67
+ readonly agreed: number | undefined;
68
+ constructor(agreed: number | undefined);
69
+ /** Spend `rows` if the budget covers them. False, and nothing spent, when it does not. */
70
+ spend(rows: number): boolean;
71
+ }
72
+ /**
73
+ * Wrap a provider so no `down` it yields runs while the database holds retained rows the budget does not
74
+ * cover. The check runs once, at the first `down`, and its answer stands for the rest of the run: a reset
75
+ * whose first `down` dropped the vault must not refuse its second for finding it empty.
76
+ *
77
+ * Counted at the `down`, not before: a row written after somebody else counted is a row this refuses.
78
+ */
79
+ export declare function guardRetained(provider: MigrationProvider, database: D1Database, options: {
80
+ binding: string;
81
+ budget: RetainedBudget;
82
+ }): MigrationProvider;
83
+ /** Which way one migration is about to move — Kysely's own spelling, as a `MigrationResult` carries it. */
84
+ export type MigrationDirection = "Up" | "Down";
85
+ /** Called ahead of one migration's body, with its composed name and the direction it is about to move. */
86
+ export type BeforeMigration = (name: string, direction: MigrationDirection) => Promise<void>;
87
+ /**
88
+ * Wrap a provider so `before` runs ahead of every `down` it yields — and a throw from `before` means the
89
+ * `down` never runs. Ups pass through untouched. A declared `down` stays declared: see {@link wrapEach}.
90
+ */
91
+ export declare function beforeEachDown(provider: MigrationProvider, before: () => Promise<void>): MigrationProvider;
92
+ /**
93
+ * Wrap a provider so `before` hears each migration's name and direction ahead of its body, up or down (#583).
94
+ *
95
+ * The seam a caller uses to say which migration it is on while it is on it: the CLI raises a `▸` step here,
96
+ * because a remote migration is a D1 round trip per statement and an operator watching nothing happen
97
+ * cannot tell a slow schema change from a hung one. Core carries no terminal concern — it hands over the
98
+ * name and the direction, and what is done with them is the caller's. A declared `down` stays declared.
99
+ */
100
+ export declare function beforeEachMigration(provider: MigrationProvider, before: BeforeMigration): MigrationProvider;
101
+ //# sourceMappingURL=retained.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retained.d.ts","sourceRoot":"","sources":["../../src/migrations/retained.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AA6DtD,2GAA2G;AAC3G,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+FAA+F;AAC/F,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEvF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,UAAU,EACpB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAC/C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAUD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAGlE;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAEtE;AAOD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,2BAA2B,GAAG,sBAAsB,CAAC;AAEjF;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,GAAE,aAA2C,GAClD,eAAe,CAEjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,GAAE,aAA2C,GAClD,IAAI,CAIN;AAyBD;;;;;GAKG;AACH,qBAAa,cAAc;;IACzB,sFAAsF;IACtF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAGpC,YAAY,MAAM,EAAE,MAAM,GAAG,SAAS,EAGrC;IAED,0FAA0F;IAC1F,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI3B;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACnD,iBAAiB,CAWnB;AAED,2GAA2G;AAC3G,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/C,0GAA0G;AAC1G,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAyC7F;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAE1G;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAE3G"}
@@ -0,0 +1,243 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { ValidationError } from "../error/pithyError.js";
4
+ import { declareRetainedDown, retainedTablesOf, retainedTablesOfDown } from "./retainedDeclaration.js";
5
+ import { CamelCasePlugin } from "kysely";
6
+ //#region src/migrations/retained.ts
7
+ /**
8
+ * **A retained table holds rows that exist nowhere else (#588).**
9
+ *
10
+ * A migration's `down` is the tested inverse of its `up`, and for schema that is exactly right. For a
11
+ * vault it is a `drop table` on the only copy of a credential Google issued. `0100_secrets_0001_init` is
12
+ * the whole history of the secrets database, so one `pithy migrate --rollback` — which steps back one
13
+ * migration in every composed database — emptied it in place, on staging, with nothing said first.
14
+ *
15
+ * So a capability **declares** a table retained, beside the migrations that create it
16
+ * (`DatabaseSpec.retained`), and the declaration is recorded on those migrations' own `down` functions
17
+ * (`./retainedDeclaration`) — by `defineCapability`, and again by `createMigrationRegistry` for a set that
18
+ * carries it. The refusal is on the operation that runs a `down`, not on a list of commands:
19
+ * {@link guardRetained} wraps every `down` a provider yields, and the runner applies it to every provider
20
+ * it is handed.
21
+ *
22
+ * ## What is TRUE
23
+ *
24
+ * **No `down` runs against a database while a table declared retained in that database holds rows**,
25
+ * beyond what the caller's {@link RetainedBudget} agreed to destroy. A count, not a boolean, so a flag
26
+ * somebody has in their shell history for another database does not also authorize this one — and one
27
+ * budget spent across a whole run, so an agreement to five rows cannot destroy five in every database.
28
+ *
29
+ * The budget is the operator's number and nothing else. The CLI's preflight also demands it *equal* the
30
+ * rows in scope; this floor demands only that no more are spent, and it is deliberately not handed the
31
+ * preflight's count — a guard fed the answer by the check above it is not a second guard.
32
+ *
33
+ * ## Its reach, stated so it can be checked
34
+ *
35
+ * - **Database-wide, deliberately.** A `down` cannot be inspected for which tables it drops without running
36
+ * it, so any `down` against a database holding retained rows is refused — including a migration of a
37
+ * different capability that never touches them. Over-refusing costs an override; under-refusing costs a
38
+ * vault.
39
+ * - **Every `down` through `runner.ts`** — `rollbackMigration`, `resetMigrations`, `dropMigrations` — whose
40
+ * function was declared: the registry's providers, the fan-out's merged ones, and a provider written by
41
+ * hand, so long as it yields the capability's own migration objects (or spreads of them).
42
+ * - **Counted over the set the runner is handed as the database.** Rollback and reset are handed one
43
+ * provider, and Kysely refuses one that does not span the ledger, so it is the database's. A drop reverses a
44
+ * part, and is handed the part and the database separately (`DropSelection`): it counts the database's,
45
+ * and refuses to reverse a migration the database's set does not carry. The CLI's `remove --drop` builds
46
+ * that set from the Worker's whole composition and every Worker discovered beside it — a capability sharing
47
+ * `SECRETS` and declaring nothing is refused while the vault holds rows.
48
+ * - **Not seen:** a drop whose caller hands the part as the database too (`{ database: part, reverse: part }`
49
+ * counts only the part); for `remove --drop`, a table declared only by a Worker whose config does not load;
50
+ * a Kysely `Migrator` constructed outside `runner.ts`; a `down` whose capability was never constructed in
51
+ * this process and whose set never passed through the registry; a `down` re-wrapped in a new function by
52
+ * anything but {@link beforeEachDown} or {@link beforeEachMigration}; and a table no capability declares — a
53
+ * capability removed from the config takes its declaration with it.
54
+ */
55
+ /** The snake_case the `CamelCasePlugin` writes, read from the plugin itself so there is one definition. */
56
+ var TableNames = class extends CamelCasePlugin {
57
+ sqlName(key) {
58
+ return this.snakeCase(key);
59
+ }
60
+ };
61
+ const NAMES = new TableNames();
62
+ /** The SQL name of a declared table key — `pithySecretsSystemSecrets` → `pithy_secrets_system_secrets`. */
63
+ function retainedTableName(key) {
64
+ return NAMES.sqlName(key);
65
+ }
66
+ /** The SQL names of the retained tables a provider's migrations declare. Reads no database. */
67
+ async function retainedTableNames(provider) {
68
+ return retainedTablesOf(await provider.getMigrations()).map(retainedTableName);
69
+ }
70
+ /**
71
+ * Count the rows in every retained table these migrations declare that is present in the database.
72
+ * Read-only. Returns only the tables holding rows, so an empty result means nothing retained is at risk.
73
+ */
74
+ async function countRetainedRows(database, migrations, binding) {
75
+ const counted = [];
76
+ for (const key of retainedTablesOf(migrations)) {
77
+ const table = retainedTableName(key);
78
+ if (!await database.prepare("select name from sqlite_master where type = 'table' and name = ?").bind(table).first()) continue;
79
+ const rows = (await database.prepare(`select count(*) as n from "${table}"`).first())?.n ?? 0;
80
+ if (rows > 0) counted.push({
81
+ binding,
82
+ table,
83
+ rows
84
+ });
85
+ }
86
+ return counted;
87
+ }
88
+ /**
89
+ * The refusals raised ahead of a `down`. A `Migrator` catches whatever a `down` throws and hands it back as
90
+ * a result, and the runner turns that into "Couldn't roll back" with a remedy to fix the migration — which
91
+ * is wrong for a refusal, where no migration is broken. So the runner asks {@link isDownRefusal} and
92
+ * rethrows one unchanged.
93
+ */
94
+ const REFUSALS = /* @__PURE__ */ new WeakSet();
95
+ /**
96
+ * Mark an error as a refusal to run a `down`, so it reaches the operator as itself rather than as a failed
97
+ * migration. For a guard written outside this module — the CLI's shared-database floor is one.
98
+ */
99
+ function downRefusal(error) {
100
+ REFUSALS.add(error);
101
+ return error;
102
+ }
103
+ /** Whether `error` refused a `down` before it ran — as opposed to a migration that failed. */
104
+ function isDownRefusal(error) {
105
+ return typeof error === "object" && error !== null && REFUSALS.has(error);
106
+ }
107
+ /** `5 rows`, `1 row`. */
108
+ function rowsLabel(count) {
109
+ return `${count} row${count === 1 ? "" : "s"}`;
110
+ }
111
+ /**
112
+ * The refusal, in one wording for every place that raises it — the fan-out's preflight, which names every
113
+ * database before any of them moves, {@link guardRetained}, which is the floor under it, and a teardown
114
+ * that deletes a database holding retained tables (`pithy secrets deprovision`, #591).
115
+ *
116
+ * `consent` is what the caller passed. The action always prints the number that would work, because that
117
+ * number is the one fact the operator has to read before typing it.
118
+ */
119
+ function retainedRefusal(atRisk, consent, before = "any down against them ran") {
120
+ return downRefusal(refusalFor(atRisk, consent, before));
121
+ }
122
+ /**
123
+ * **The preflight: refuse unless the operator counted exactly the retained rows in scope.**
124
+ *
125
+ * Absent a count, only an empty scope passes; given one, only the same number does — a count that is too
126
+ * high is a count of something else, and agreeing to it would let a stale number from shell history through
127
+ * the day the rows it described are joined by more. Call it with every database the operation will touch,
128
+ * counted before the first of them moves, so the refusal names them all with nothing changed.
129
+ *
130
+ * The floor under it is {@link RetainedBudget}, fed the operator's number and never this function's
131
+ * count.
132
+ */
133
+ function assertRetainedAgreed(atRisk, consent, before = "any down against them ran") {
134
+ const total = atRisk.reduce((sum, entry) => sum + entry.rows, 0);
135
+ if (!(consent === void 0 ? total === 0 : consent === total)) throw retainedRefusal(atRisk, consent, before);
136
+ }
137
+ function refusalFor(atRisk, consent, before) {
138
+ const total = atRisk.reduce((sum, entry) => sum + entry.rows, 0);
139
+ const named = atRisk.map((entry) => `${entry.table} on ${entry.binding} (${rowsLabel(entry.rows)})`).join(", ");
140
+ const mismatch = consent === void 0 ? "" : `--destroy-retained ${consent} does not match the ${rowsLabel(total)} at risk. `;
141
+ if (total === 0) return new ValidationError({
142
+ message: `${mismatch}Nothing retained is at risk. Refused before ${before === "anything was deleted" ? before : "any down ran"}.`,
143
+ action: "Run it again without --destroy-retained."
144
+ });
145
+ return new ValidationError({
146
+ message: `${mismatch}Retained ${rowsLabel(total)} would be dropped: ${named}. Refused before ${before}.`,
147
+ action: `They exist nowhere else. Back them up, or pass --destroy-retained ${total} to drop them.`,
148
+ detail: "A retained table is declared by its capability. Any down against its database, and any deletion of the database, is refused while it holds rows."
149
+ });
150
+ }
151
+ /**
152
+ * **How many retained rows a run has agreed to destroy, spent as each database is reached.**
153
+ *
154
+ * One per run, shared by every database in it. Absent an agreement it holds nothing, so any retained row
155
+ * refuses. A database whose rows exceed what is left is refused whole — nothing is spent on a refusal.
156
+ */
157
+ var RetainedBudget = class {
158
+ /** What the caller agreed to, as they typed it — the number a refusal quotes back. */
159
+ agreed;
160
+ #remaining;
161
+ constructor(agreed) {
162
+ this.agreed = agreed;
163
+ this.#remaining = agreed ?? 0;
164
+ }
165
+ /** Spend `rows` if the budget covers them. False, and nothing spent, when it does not. */
166
+ spend(rows) {
167
+ if (rows > this.#remaining) return false;
168
+ this.#remaining -= rows;
169
+ return true;
170
+ }
171
+ };
172
+ /**
173
+ * Wrap a provider so no `down` it yields runs while the database holds retained rows the budget does not
174
+ * cover. The check runs once, at the first `down`, and its answer stands for the rest of the run: a reset
175
+ * whose first `down` dropped the vault must not refuse its second for finding it empty.
176
+ *
177
+ * Counted at the `down`, not before: a row written after somebody else counted is a row this refuses.
178
+ */
179
+ function guardRetained(provider, database, options) {
180
+ let cleared;
181
+ const check = async () => {
182
+ const atRisk = await countRetainedRows(database, await provider.getMigrations(), options.binding);
183
+ const total = atRisk.reduce((sum, entry) => sum + entry.rows, 0);
184
+ if (!options.budget.spend(total)) throw retainedRefusal(atRisk, options.budget.agreed);
185
+ };
186
+ return beforeEachDown(provider, async () => {
187
+ cleared ??= check();
188
+ await cleared;
189
+ });
190
+ }
191
+ /**
192
+ * Wrap a provider so `before` runs ahead of every migration body it yields, in each of `directions` — and a
193
+ * throw from `before` means that body never runs. A direction not listed passes through untouched.
194
+ *
195
+ * **Each new `down` keeps the declaration of the one it wraps.** That is the reason this is the one way to
196
+ * wrap a provider's migrations: a hand-rolled wrapper is a new function the declaration has never heard of,
197
+ * and {@link guardRetained} handed it would find nothing declared and let every `down` through.
198
+ */
199
+ function wrapEach(provider, before, directions) {
200
+ return { getMigrations: async () => {
201
+ const migrations = await provider.getMigrations();
202
+ return Object.fromEntries(Object.entries(migrations).map(([name, migration]) => {
203
+ const { up, down } = migration;
204
+ const wrappedUp = directions.includes("Up") ? async (db) => {
205
+ await before(name, "Up");
206
+ await up(db);
207
+ } : up;
208
+ if (!down || !directions.includes("Down")) return [name, {
209
+ ...migration,
210
+ up: wrappedUp
211
+ }];
212
+ const wrappedDown = async (db) => {
213
+ await before(name, "Down");
214
+ await down(db);
215
+ };
216
+ declareRetainedDown(wrappedDown, retainedTablesOfDown(down));
217
+ return [name, {
218
+ up: wrappedUp,
219
+ down: wrappedDown
220
+ }];
221
+ }));
222
+ } };
223
+ }
224
+ /**
225
+ * Wrap a provider so `before` runs ahead of every `down` it yields — and a throw from `before` means the
226
+ * `down` never runs. Ups pass through untouched. A declared `down` stays declared: see {@link wrapEach}.
227
+ */
228
+ function beforeEachDown(provider, before) {
229
+ return wrapEach(provider, () => before(), ["Down"]);
230
+ }
231
+ /**
232
+ * Wrap a provider so `before` hears each migration's name and direction ahead of its body, up or down (#583).
233
+ *
234
+ * The seam a caller uses to say which migration it is on while it is on it: the CLI raises a `▸` step here,
235
+ * because a remote migration is a D1 round trip per statement and an operator watching nothing happen
236
+ * cannot tell a slow schema change from a hung one. Core carries no terminal concern — it hands over the
237
+ * name and the direction, and what is done with them is the caller's. A declared `down` stays declared.
238
+ */
239
+ function beforeEachMigration(provider, before) {
240
+ return wrapEach(provider, before, ["Up", "Down"]);
241
+ }
242
+ //#endregion
243
+ export { RetainedBudget, assertRetainedAgreed, beforeEachDown, beforeEachMigration, countRetainedRows, downRefusal, guardRetained, isDownRefusal, retainedRefusal, retainedTableName, retainedTableNames };
@@ -0,0 +1,15 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import type { Migration } from "kysely/migration";
4
+ /** Record that every `down` in `migrations` runs against a database holding these retained tables. */
5
+ export declare function declareRetained(migrations: Readonly<Record<string, Migration>>, tables: readonly string[]): void;
6
+ /** Record one `down` — for a wrapper that replaces a declared `down` with its own function. */
7
+ export declare function declareRetainedDown(down: object, tables: readonly string[]): void;
8
+ /** The retained table keys declared on one `down`. */
9
+ export declare function retainedTablesOfDown(down: object): readonly string[];
10
+ /**
11
+ * The retained table keys any migration in a set declares — the database-wide answer, since a `down` is
12
+ * refused for rows in *any* retained table of the database it runs against.
13
+ */
14
+ export declare function retainedTablesOf(migrations: Readonly<Record<string, Migration>>): string[];
15
+ //# sourceMappingURL=retainedDeclaration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retainedDeclaration.d.ts","sourceRoot":"","sources":["../../src/migrations/retainedDeclaration.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAsBlD,sGAAsG;AACtG,wBAAgB,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAKhH;AAED,+FAA+F;AAC/F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAGjF;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,MAAM,EAAE,CAO1F"}
@@ -0,0 +1,49 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ //#region src/migrations/retainedDeclaration.ts
4
+ /**
5
+ * **Where a retained declaration is kept: on the `down` that would destroy the table (#588).**
6
+ *
7
+ * A capability says which of its tables are retained (`DatabaseSpec.retained`). The runner has to know it
8
+ * at the moment a `down` is about to run, and by then all it holds is a `MigrationProvider` — Kysely's
9
+ * interface, rebuilt by the registry, merged by the fan-out, wrapped by `batchedProvider`, and written by
10
+ * hand in every capability's own migration tests. A declaration kept on any of those objects is lost the
11
+ * first time somebody builds a new one.
12
+ *
13
+ * The `down` function survives all of that. A registry keeps the capability's migration object; a spread
14
+ * that rebuilds the record keeps the same `down`; a hand-built provider in a test names the very
15
+ * `secrets_0001_init` the capability ships. So the declaration is keyed on the function itself, and any
16
+ * provider that yields it carries it.
17
+ *
18
+ * Kept apart from `./retained` so `defineCapability` can declare without importing Kysely's runtime.
19
+ */
20
+ /** The destructive function → the retained table keys (camelCase, as `tables` declares them) it can drop. */
21
+ const DECLARED = /* @__PURE__ */ new WeakMap();
22
+ /** Record that every `down` in `migrations` runs against a database holding these retained tables. */
23
+ function declareRetained(migrations, tables) {
24
+ if (tables.length === 0) return;
25
+ for (const migration of Object.values(migrations)) if (migration.down) declareRetainedDown(migration.down, tables);
26
+ }
27
+ /** Record one `down` — for a wrapper that replaces a declared `down` with its own function. */
28
+ function declareRetainedDown(down, tables) {
29
+ if (tables.length === 0) return;
30
+ DECLARED.set(down, [.../* @__PURE__ */ new Set([...DECLARED.get(down) ?? [], ...tables])]);
31
+ }
32
+ /** The retained table keys declared on one `down`. */
33
+ function retainedTablesOfDown(down) {
34
+ return DECLARED.get(down) ?? [];
35
+ }
36
+ /**
37
+ * The retained table keys any migration in a set declares — the database-wide answer, since a `down` is
38
+ * refused for rows in *any* retained table of the database it runs against.
39
+ */
40
+ function retainedTablesOf(migrations) {
41
+ const tables = /* @__PURE__ */ new Set();
42
+ for (const migration of Object.values(migrations)) {
43
+ if (!migration.down) continue;
44
+ for (const table of retainedTablesOfDown(migration.down)) tables.add(table);
45
+ }
46
+ return [...tables].sort();
47
+ }
48
+ //#endregion
49
+ export { declareRetained, declareRetainedDown, retainedTablesOf, retainedTablesOfDown };