@beechcms/core 0.9.0 → 0.9.1

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 (203) hide show
  1. package/dist/dashboard-layout/content-view.d.ts +4 -4
  2. package/package.json +2 -2
  3. package/dist/automations-grammar-words.d.ts +0 -2
  4. package/dist/automations-grammar-words.d.ts.map +0 -1
  5. package/dist/automations-grammar-words.js +0 -8
  6. package/dist/automations.repository.interface.d.ts +0 -19
  7. package/dist/automations.repository.interface.d.ts.map +0 -1
  8. package/dist/automations.repository.interface.js +0 -3
  9. package/dist/automations.runner.interface.d.ts +0 -10
  10. package/dist/automations.runner.interface.d.ts.map +0 -1
  11. package/dist/automations.runner.interface.js +0 -3
  12. package/dist/automations.runner.stub.d.ts +0 -5
  13. package/dist/automations.runner.stub.d.ts.map +0 -1
  14. package/dist/automations.runner.stub.js +0 -7
  15. package/dist/automations.types.d.ts +0 -75
  16. package/dist/automations.types.d.ts.map +0 -1
  17. package/dist/automations.types.js +0 -3
  18. package/dist/clock.d.ts +0 -25
  19. package/dist/clock.d.ts.map +0 -1
  20. package/dist/clock.js +0 -11
  21. package/dist/content-scan.repository.d.ts +0 -9
  22. package/dist/content-scan.repository.d.ts.map +0 -1
  23. package/dist/content-scan.repository.js +0 -3
  24. package/dist/content.repository.d.ts +0 -247
  25. package/dist/content.repository.d.ts.map +0 -1
  26. package/dist/content.repository.js +0 -59
  27. package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts +0 -19
  28. package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts.map +0 -1
  29. package/dist/dashboard-layout/kanban/kanban-position.repository.js +0 -3
  30. package/dist/dashboard-layout.d.ts +0 -154
  31. package/dist/dashboard-layout.d.ts.map +0 -1
  32. package/dist/dashboard-layout.js +0 -186
  33. package/dist/dashboard-layout.repository.d.ts +0 -18
  34. package/dist/dashboard-layout.repository.d.ts.map +0 -1
  35. package/dist/dashboard-layout.repository.js +0 -3
  36. package/dist/dashboard-permissions.d.ts +0 -3
  37. package/dist/dashboard-permissions.d.ts.map +0 -1
  38. package/dist/dashboard-permissions.js +0 -11
  39. package/dist/dashboard-scopes.d.ts +0 -12
  40. package/dist/dashboard-scopes.d.ts.map +0 -1
  41. package/dist/dashboard-scopes.js +0 -30
  42. package/dist/define-seed.d.ts +0 -3
  43. package/dist/define-seed.d.ts.map +0 -1
  44. package/dist/define-seed.js +0 -5
  45. package/dist/demo-data.repository.d.ts +0 -5
  46. package/dist/demo-data.repository.d.ts.map +0 -1
  47. package/dist/demo-data.repository.js +0 -3
  48. package/dist/email.provider.d.ts +0 -32
  49. package/dist/email.provider.d.ts.map +0 -1
  50. package/dist/email.provider.js +0 -4
  51. package/dist/engine/ddl/seed-ddl-destructive.d.ts +0 -40
  52. package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +0 -1
  53. package/dist/engine/ddl/seed-ddl-destructive.js +0 -149
  54. package/dist/engine/ddl.d.ts +0 -193
  55. package/dist/engine/ddl.d.ts.map +0 -1
  56. package/dist/engine/ddl.js +0 -518
  57. package/dist/engine/define-seed.d.ts +0 -3
  58. package/dist/engine/define-seed.d.ts.map +0 -1
  59. package/dist/engine/define-seed.js +0 -5
  60. package/dist/engine/introspection.d.ts +0 -101
  61. package/dist/engine/introspection.d.ts.map +0 -1
  62. package/dist/engine/introspection.js +0 -127
  63. package/dist/engine/localization.d.ts +0 -127
  64. package/dist/engine/localization.d.ts.map +0 -1
  65. package/dist/engine/localization.js +0 -212
  66. package/dist/engine/policies.d.ts +0 -58
  67. package/dist/engine/policies.d.ts.map +0 -1
  68. package/dist/engine/policies.js +0 -168
  69. package/dist/engine/privacy.service.d.ts +0 -65
  70. package/dist/engine/privacy.service.d.ts.map +0 -1
  71. package/dist/engine/privacy.service.js +0 -114
  72. package/dist/engine/query.d.ts +0 -23
  73. package/dist/engine/query.d.ts.map +0 -1
  74. package/dist/engine/query.js +0 -236
  75. package/dist/engine/relations.d.ts +0 -28
  76. package/dist/engine/relations.d.ts.map +0 -1
  77. package/dist/engine/relations.js +0 -25
  78. package/dist/engine/schema-fingerprint.d.ts +0 -73
  79. package/dist/engine/schema-fingerprint.d.ts.map +0 -1
  80. package/dist/engine/schema-fingerprint.js +0 -97
  81. package/dist/engine/schema-mutator.d.ts +0 -26
  82. package/dist/engine/schema-mutator.d.ts.map +0 -1
  83. package/dist/engine/schema-mutator.js +0 -3
  84. package/dist/engine/seed-ddl-destructive.d.ts +0 -40
  85. package/dist/engine/seed-ddl-destructive.d.ts.map +0 -1
  86. package/dist/engine/seed-ddl-destructive.js +0 -149
  87. package/dist/engine/seed-ddl.d.ts +0 -40
  88. package/dist/engine/seed-ddl.d.ts.map +0 -1
  89. package/dist/engine/seed-ddl.js +0 -100
  90. package/dist/engine/seed-registry.d.ts +0 -71
  91. package/dist/engine/seed-registry.d.ts.map +0 -1
  92. package/dist/engine/seed-registry.js +0 -167
  93. package/dist/engine/seed-types-generator.d.ts +0 -10
  94. package/dist/engine/seed-types-generator.d.ts.map +0 -1
  95. package/dist/engine/seed-types-generator.js +0 -89
  96. package/dist/engine/seed-validation.d.ts +0 -30
  97. package/dist/engine/seed-validation.d.ts.map +0 -1
  98. package/dist/engine/seed-validation.js +0 -319
  99. package/dist/engine/seeds.d.ts +0 -20
  100. package/dist/engine/seeds.d.ts.map +0 -1
  101. package/dist/engine/seeds.js +0 -21
  102. package/dist/engine/serialize.d.ts +0 -20
  103. package/dist/engine/serialize.d.ts.map +0 -1
  104. package/dist/engine/serialize.js +0 -160
  105. package/dist/engine.d.ts +0 -144
  106. package/dist/engine.d.ts.map +0 -1
  107. package/dist/engine.js +0 -741
  108. package/dist/file-types.d.ts +0 -13
  109. package/dist/file-types.d.ts.map +0 -1
  110. package/dist/file-types.js +0 -85
  111. package/dist/hooks.d.ts +0 -29
  112. package/dist/hooks.d.ts.map +0 -1
  113. package/dist/hooks.js +0 -3
  114. package/dist/id-generator.d.ts +0 -26
  115. package/dist/id-generator.d.ts.map +0 -1
  116. package/dist/id-generator.js +0 -12
  117. package/dist/idempotency.repository.d.ts +0 -13
  118. package/dist/idempotency.repository.d.ts.map +0 -1
  119. package/dist/idempotency.repository.js +0 -3
  120. package/dist/kanban-position.repository.d.ts +0 -19
  121. package/dist/kanban-position.repository.d.ts.map +0 -1
  122. package/dist/kanban-position.repository.js +0 -3
  123. package/dist/kanban.d.ts +0 -75
  124. package/dist/kanban.d.ts.map +0 -1
  125. package/dist/kanban.js +0 -82
  126. package/dist/layout-permissions.d.ts +0 -3
  127. package/dist/layout-permissions.d.ts.map +0 -1
  128. package/dist/layout-permissions.js +0 -11
  129. package/dist/media.repository.d.ts +0 -61
  130. package/dist/media.repository.d.ts.map +0 -1
  131. package/dist/media.repository.js +0 -3
  132. package/dist/policies.d.ts +0 -10
  133. package/dist/policies.d.ts.map +0 -1
  134. package/dist/policies.js +0 -33
  135. package/dist/queue.interface.d.ts +0 -39
  136. package/dist/queue.interface.d.ts.map +0 -1
  137. package/dist/queue.interface.js +0 -3
  138. package/dist/queue.stub.d.ts +0 -6
  139. package/dist/queue.stub.d.ts.map +0 -1
  140. package/dist/queue.stub.js +0 -8
  141. package/dist/relations.d.ts +0 -28
  142. package/dist/relations.d.ts.map +0 -1
  143. package/dist/relations.js +0 -25
  144. package/dist/richtext-render.d.ts +0 -11
  145. package/dist/richtext-render.d.ts.map +0 -1
  146. package/dist/richtext-render.js +0 -87
  147. package/dist/richtext.d.ts +0 -11
  148. package/dist/richtext.d.ts.map +0 -1
  149. package/dist/richtext.js +0 -13
  150. package/dist/scheduler.interface.d.ts +0 -4
  151. package/dist/scheduler.interface.d.ts.map +0 -1
  152. package/dist/scheduler.interface.js +0 -3
  153. package/dist/scheduler.stub.d.ts +0 -5
  154. package/dist/scheduler.stub.d.ts.map +0 -1
  155. package/dist/scheduler.stub.js +0 -7
  156. package/dist/schema-mutator.d.ts +0 -26
  157. package/dist/schema-mutator.d.ts.map +0 -1
  158. package/dist/schema-mutator.js +0 -3
  159. package/dist/seed-ddl-destructive.d.ts +0 -40
  160. package/dist/seed-ddl-destructive.d.ts.map +0 -1
  161. package/dist/seed-ddl-destructive.js +0 -149
  162. package/dist/seed-ddl.d.ts +0 -40
  163. package/dist/seed-ddl.d.ts.map +0 -1
  164. package/dist/seed-ddl.js +0 -100
  165. package/dist/seed-layout.d.ts +0 -145
  166. package/dist/seed-layout.d.ts.map +0 -1
  167. package/dist/seed-layout.js +0 -192
  168. package/dist/seed-layout.repository.d.ts +0 -22
  169. package/dist/seed-layout.repository.d.ts.map +0 -1
  170. package/dist/seed-layout.repository.js +0 -3
  171. package/dist/seed-registry.d.ts +0 -71
  172. package/dist/seed-registry.d.ts.map +0 -1
  173. package/dist/seed-registry.js +0 -143
  174. package/dist/seed-types-generator.d.ts +0 -10
  175. package/dist/seed-types-generator.d.ts.map +0 -1
  176. package/dist/seed-types-generator.js +0 -86
  177. package/dist/seed-validation.d.ts +0 -23
  178. package/dist/seed-validation.d.ts.map +0 -1
  179. package/dist/seed-validation.js +0 -224
  180. package/dist/seed.repository.d.ts +0 -37
  181. package/dist/seed.repository.d.ts.map +0 -1
  182. package/dist/seed.repository.js +0 -3
  183. package/dist/seeds.d.ts +0 -20
  184. package/dist/seeds.d.ts.map +0 -1
  185. package/dist/seeds.js +0 -21
  186. package/dist/site-settings.repository.d.ts +0 -16
  187. package/dist/site-settings.repository.d.ts.map +0 -1
  188. package/dist/site-settings.repository.js +0 -3
  189. package/dist/slug-utils.d.ts +0 -18
  190. package/dist/slug-utils.d.ts.map +0 -1
  191. package/dist/slug-utils.js +0 -32
  192. package/dist/storage.d.ts +0 -46
  193. package/dist/storage.d.ts.map +0 -1
  194. package/dist/storage.js +0 -3
  195. package/dist/types.d.ts +0 -243
  196. package/dist/types.d.ts.map +0 -1
  197. package/dist/types.js +0 -3
  198. package/dist/validation.d.ts +0 -50
  199. package/dist/validation.d.ts.map +0 -1
  200. package/dist/validation.js +0 -660
  201. package/dist/webhook-validation.d.ts +0 -3
  202. package/dist/webhook-validation.d.ts.map +0 -1
  203. package/dist/webhook-validation.js +0 -6
@@ -1,73 +0,0 @@
1
- import type { Branch, Seed } from './types.js';
2
- /**
3
- * Bumped ONLY when the projection below or the canonical byte format changes — i.e. when
4
- * fingerprints computed by two builds are no longer comparable. It is carried in the fingerprint
5
- * string itself so a version skew reads as a mismatch instead of as an accidental match.
6
- */
7
- export declare const SCHEMA_FINGERPRINT_VERSION = 1;
8
- /** The response-shape-bearing subset of a `Branch`. */
9
- export interface ContractBranch {
10
- alias: string;
11
- type: Branch['type'];
12
- format?: Branch['format'];
13
- multiple?: boolean;
14
- options?: string[];
15
- requiredOnCreate: boolean;
16
- requiredOnUpdate: boolean;
17
- targetSeed?: string;
18
- /** From `resolvePolicies`, so an explicitly-written default hashes like an omitted one. */
19
- visibility: 'full' | 'masked' | 'hidden';
20
- publicRead: boolean;
21
- publicEdit: boolean;
22
- minItems?: number;
23
- maxItems?: number;
24
- /** Present only when true: the dictionary shape is part of the public contract (`?lang=all`, writes). */
25
- localized?: boolean;
26
- /** Repeater sub-fields, same projection, recursively. */
27
- fields?: ContractBranch[];
28
- }
29
- /** The response-shape-bearing subset of a `Seed`. */
30
- export interface ContractSeed {
31
- slug: string;
32
- displayNameAlias: string;
33
- allowDrafts: boolean;
34
- allowPublicRead: boolean;
35
- allowPublicPost: boolean;
36
- allowPublicEdit: boolean;
37
- branches: ContractBranch[];
38
- }
39
- /** The exact value that gets canonicalized and hashed. */
40
- export interface SchemaContract {
41
- fingerprintVersion: number;
42
- seeds: ContractSeed[];
43
- }
44
- /**
45
- * Reduces seeds to what a response shape depends on.
46
- *
47
- * Deliberately EXCLUDED, and each for a reason a future reader must not "fix":
48
- * - `id` (`br_XX`) — a stable internal handle; it never appears in a payload, and minting order
49
- * differs between an environment built by migration and one grown through the dashboard.
50
- * - `label`, `labelPlural`, `hint`, `dashboard`, `layout` — presentation, never response shape.
51
- * - `retentionDays`, `onDelete`, `policies.search|filter|sort`, `numberOptions`, `fileOptions`,
52
- * `policies.classification|privacy` — behaviour and storage concerns that leave the response
53
- * shape identical. (`privacy` DOES change a stored value's encoding, but the API type stays
54
- * `string`; drift there is a data concern, not a type concern.)
55
- * - anything physical (column order, index names) — see the VETO Audit.
56
- *
57
- * Seeds are sorted by slug; BRANCH ORDER IS PRESERVED, because it is the declared field order the
58
- * generated types and the dashboard form both follow.
59
- */
60
- export declare function projectSchemaContract(seeds: Seed[]): SchemaContract;
61
- /**
62
- * `v{VERSION}:{32 lowercase hex}` — SHA-256 over the canonical JSON of the contract projection,
63
- * truncated to 128 bits.
64
- *
65
- * Truncation is deliberate: this value travels on EVERY public response as `X-Schema-Revision`,
66
- * and 128 bits of a SHA-256 digest carries no realistic collision risk for a value space of a few
67
- * hundred schema revisions. It is a revision marker, never a security token.
68
- *
69
- * Web Crypto only — the same API the Worker and Node ≥ 18 both expose, as `webhook-crypto.ts`
70
- * already relies on. `@beechcms/core` gains no dependency.
71
- */
72
- export declare function computeSchemaFingerprint(seeds: Seed[]): Promise<string>;
73
- //# sourceMappingURL=schema-fingerprint.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-fingerprint.d.ts","sourceRoot":"","sources":["../../src/engine/schema-fingerprint.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2FAA2F;IAC3F,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACxC,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yGAAyG;IACzG,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yDAAyD;IACzD,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;CAC1B;AAED,qDAAqD;AACrD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,eAAe,EAAE,OAAO,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,cAAc,EAAE,CAAA;CAC3B;AAED,0DAA0D;AAC1D,MAAM,WAAW,cAAc;IAC7B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc,CAenE;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7E"}
@@ -1,97 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- /**
4
- * @module engine/schema-fingerprint
5
- * A deterministic name for "the shape this API answers in".
6
- *
7
- * Computed from live seed definitions (`introspectSeedDefinitions`), embedded in generated client
8
- * types at build time (sprint 3), returned on every public response as `X-Schema-Revision`
9
- * (sprint 4), and compared by the client at request time (sprint 5). Both ends MUST compute it
10
- * with this function — two implementations would be free to disagree, and a drift detector whose
11
- * ends disagree is worse than none.
12
- *
13
- * What is hashed is a CONTRACT PROJECTION, not the whole seed definition: labels, hints, dashboard
14
- * icons and layout cannot change a single response byte, and hashing them would fire a hard
15
- * `BeechProblem` in someone else's production client over a typo fix.
16
- */
17
- import { canonicalStringify } from '../common/canonical-json.js';
18
- import { resolvePolicies } from './policies.js';
19
- /**
20
- * Bumped ONLY when the projection below or the canonical byte format changes — i.e. when
21
- * fingerprints computed by two builds are no longer comparable. It is carried in the fingerprint
22
- * string itself so a version skew reads as a mismatch instead of as an accidental match.
23
- */
24
- export const SCHEMA_FINGERPRINT_VERSION = 1;
25
- function projectBranch(branch) {
26
- const policies = resolvePolicies(branch);
27
- return {
28
- alias: branch.alias,
29
- type: branch.type,
30
- ...(branch.format !== undefined ? { format: branch.format } : {}),
31
- ...(branch.multiple !== undefined ? { multiple: branch.multiple } : {}),
32
- // Option order is the contract: it is the order a select renders and a union type lists.
33
- ...(branch.options !== undefined ? { options: [...branch.options] } : {}),
34
- requiredOnCreate: branch.requiredOnCreate ?? false,
35
- requiredOnUpdate: branch.requiredOnUpdate ?? false,
36
- ...(branch.targetSeed !== undefined ? { targetSeed: branch.targetSeed } : {}),
37
- visibility: policies.visibility,
38
- publicRead: policies.public,
39
- publicEdit: policies.publicEdit,
40
- ...(branch.minItems !== undefined ? { minItems: branch.minItems } : {}),
41
- ...(branch.maxItems !== undefined ? { maxItems: branch.maxItems } : {}),
42
- // Spread only when true so every schema without localized branches keeps its fingerprint.
43
- ...(branch.localized === true ? { localized: true } : {}),
44
- ...(branch.fields ? { fields: branch.fields.map(projectBranch) } : {}),
45
- };
46
- }
47
- /**
48
- * Reduces seeds to what a response shape depends on.
49
- *
50
- * Deliberately EXCLUDED, and each for a reason a future reader must not "fix":
51
- * - `id` (`br_XX`) — a stable internal handle; it never appears in a payload, and minting order
52
- * differs between an environment built by migration and one grown through the dashboard.
53
- * - `label`, `labelPlural`, `hint`, `dashboard`, `layout` — presentation, never response shape.
54
- * - `retentionDays`, `onDelete`, `policies.search|filter|sort`, `numberOptions`, `fileOptions`,
55
- * `policies.classification|privacy` — behaviour and storage concerns that leave the response
56
- * shape identical. (`privacy` DOES change a stored value's encoding, but the API type stays
57
- * `string`; drift there is a data concern, not a type concern.)
58
- * - anything physical (column order, index names) — see the VETO Audit.
59
- *
60
- * Seeds are sorted by slug; BRANCH ORDER IS PRESERVED, because it is the declared field order the
61
- * generated types and the dashboard form both follow.
62
- */
63
- export function projectSchemaContract(seeds) {
64
- return {
65
- fingerprintVersion: SCHEMA_FINGERPRINT_VERSION,
66
- seeds: [...seeds]
67
- .sort((a, b) => a.slug.localeCompare(b.slug))
68
- .map(seed => ({
69
- slug: seed.slug,
70
- displayNameAlias: seed.displayNameAlias,
71
- allowDrafts: seed.allowDrafts ?? false,
72
- allowPublicRead: seed.allowPublicRead ?? false,
73
- allowPublicPost: seed.allowPublicPost ?? false,
74
- allowPublicEdit: seed.allowPublicEdit ?? false,
75
- branches: seed.branches.map(projectBranch),
76
- })),
77
- };
78
- }
79
- function toHex(buffer) {
80
- return Array.from(new Uint8Array(buffer), byte => byte.toString(16).padStart(2, '0')).join('');
81
- }
82
- /**
83
- * `v{VERSION}:{32 lowercase hex}` — SHA-256 over the canonical JSON of the contract projection,
84
- * truncated to 128 bits.
85
- *
86
- * Truncation is deliberate: this value travels on EVERY public response as `X-Schema-Revision`,
87
- * and 128 bits of a SHA-256 digest carries no realistic collision risk for a value space of a few
88
- * hundred schema revisions. It is a revision marker, never a security token.
89
- *
90
- * Web Crypto only — the same API the Worker and Node ≥ 18 both expose, as `webhook-crypto.ts`
91
- * already relies on. `@beechcms/core` gains no dependency.
92
- */
93
- export async function computeSchemaFingerprint(seeds) {
94
- const bytes = new TextEncoder().encode(canonicalStringify(projectSchemaContract(seeds)));
95
- const digest = await crypto.subtle.digest('SHA-256', bytes);
96
- return `v${SCHEMA_FINGERPRINT_VERSION}:${toHex(digest).slice(0, 32)}`;
97
- }
@@ -1,26 +0,0 @@
1
- /** Executes additive schema DDL against the live database and introspects columns.
2
- * Implemented by D1SchemaMutator in apps/api/src/shared/schema-mutator.d1.ts.
3
- * This is the ONLY sanctioned channel for runtime DDL — handlers never touch env.DB. */
4
- export interface ISchemaMutator {
5
- /** Column names currently on a table, or null if the table does not exist. */
6
- getColumns(table: string): Promise<Set<string> | null>;
7
- /** Runs the given DDL statements in order as a single D1 batch.
8
- * All statements must be additive (CREATE … IF NOT EXISTS / ALTER … ADD COLUMN /
9
- * CREATE INDEX IF NOT EXISTS). Throws on the first failing statement. */
10
- execDdl(statements: string[]): Promise<void>;
11
- /** `DROP TABLE IF EXISTS {table}`. */
12
- dropTable(table: string): Promise<void>;
13
- /** `ALTER TABLE {table} DROP COLUMN {column}`. */
14
- dropColumn(table: string, column: string): Promise<void>;
15
- /** `ALTER TABLE {table} RENAME COLUMN {from} TO {to}`. */
16
- renameColumn(table: string, from: string, to: string): Promise<void>;
17
- /** Runs a multi-statement destructive batch atomically (FTS rebuild,
18
- * type-change column rebuild, full type drop). The caller assembles the
19
- * statements; the impl validates identifiers and runs them as one D1 batch. */
20
- execDestructive(statements: string[]): Promise<void>;
21
- /** Reads all rows from a table for the specified columns only.
22
- * Used before DROP TABLE to collect R2 keys for media cleanup.
23
- * All identifiers are validated against `^[A-Za-z0-9_]+$`. */
24
- fetchRows(table: string, columns: string[]): Promise<Record<string, unknown>[]>;
25
- }
26
- //# sourceMappingURL=schema-mutator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-mutator.d.ts","sourceRoot":"","sources":["../../src/engine/schema-mutator.ts"],"names":[],"mappings":"AAGA;;yFAEyF;AACzF,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAA;IACtD;;8EAE0E;IAC1E,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAS5C,sCAAsC;IACtC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,kDAAkD;IAClD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,0DAA0D;IAC1D,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpE;;oFAEgF;IAChF,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpD;;mEAE+D;IAC/D,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;CAChF"}
@@ -1,3 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- export {};
@@ -1,40 +0,0 @@
1
- import type { Seed, BranchType } from './types.js';
2
- /**
3
- * Ordered DROP TABLE statements for a full hard-delete of a seed's tables.
4
- * Order: junction drafts → junctions → FTS triggers → FTS table → drafts → main table.
5
- * All statements use IF EXISTS (idempotent).
6
- */
7
- export declare function generateDropTable(seed: Seed): string[];
8
- /**
9
- * DROP COLUMN statements for a single branch (by alias).
10
- * For multi-relation branches: drops the junction tables (no column on parent).
11
- * For regular branches: drops from main table + drafts table (if allowDrafts).
12
- * Does NOT include FTS handling — callers must prepend ftsTriggerDrops() and
13
- * append planFtsRebuild() when the branch is searchable.
14
- */
15
- export declare function generateDropColumn(seed: Seed, alias: string): string[];
16
- /**
17
- * RENAME COLUMN statements for a branch alias change.
18
- * Updates main table + drafts (if allowDrafts).
19
- * Does NOT handle FTS — callers must rebuild FTS separately (SQLite auto-updates
20
- * trigger bodies on RENAME but the FTS virtual-table columns keep the old name).
21
- */
22
- export declare function generateRenameColumn(seed: Seed, fromAlias: string, toAlias: string): string[];
23
- /**
24
- * Full FTS rebuild: drop triggers + FTS table, then recreate them, then backfill.
25
- * Returns an empty array if the seed has no searchable branches.
26
- * The drop steps use IF EXISTS so this is safe to call even if FTS was already dropped.
27
- */
28
- export declare function planFtsRebuild(seed: Seed): string[];
29
- export interface RetypeColumnPlan {
30
- statements: string[];
31
- ftsRebuildNeeded: boolean;
32
- }
33
- /**
34
- * Generates statements to change a branch's SQL storage type using the
35
- * add-new-column / copy / drop-old / rename approach.
36
- * Includes FTS rebuild statements when the branch is (or becomes) searchable.
37
- * `updatedSeed` must already reflect the new type on the renamed branch.
38
- */
39
- export declare function planRetypeColumn(seed: Seed, alias: string, newType: BranchType, updatedSeed: Seed): RetypeColumnPlan;
40
- //# sourceMappingURL=seed-ddl-destructive.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seed-ddl-destructive.d.ts","sourceRoot":"","sources":["../../src/engine/seed-ddl-destructive.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAU,UAAU,EAAE,MAAM,YAAY,CAAA;AAkC1D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAgBtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBtE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ7F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAiBnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,EACnB,WAAW,EAAE,IAAI,GAChB,gBAAgB,CAyClB"}
@@ -1,149 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- import { junctionTableName, generateFtsTable, generateFtsTriggers } from './engine.js';
4
- const BRANCH_SQL_TYPE = {
5
- text: 'TEXT',
6
- number: 'REAL',
7
- boolean: 'INTEGER',
8
- date: 'INTEGER',
9
- json: 'TEXT',
10
- richtext: 'TEXT',
11
- file: 'TEXT',
12
- tags: 'TEXT',
13
- relation: 'TEXT',
14
- repeater: 'TEXT',
15
- };
16
- /** Branch types that receive a B-tree index in generateIndexes (used by retype to drop/recreate). */
17
- const INDEXABLE_TYPES = new Set(['text', 'number', 'date', 'boolean', 'relation']);
18
- function searchBranches(seed) {
19
- return seed.branches.filter(b => (b.type === 'text' || b.type === 'richtext') && b.policies?.search !== false);
20
- }
21
- function ftsTriggerDrops(slug) {
22
- return [
23
- `DROP TRIGGER IF EXISTS fts_${slug}_insert;`,
24
- `DROP TRIGGER IF EXISTS fts_${slug}_update;`,
25
- `DROP TRIGGER IF EXISTS fts_${slug}_delete;`,
26
- `DROP TABLE IF EXISTS fts_${slug};`,
27
- ];
28
- }
29
- /**
30
- * Ordered DROP TABLE statements for a full hard-delete of a seed's tables.
31
- * Order: junction drafts → junctions → FTS triggers → FTS table → drafts → main table.
32
- * All statements use IF EXISTS (idempotent).
33
- */
34
- export function generateDropTable(seed) {
35
- const stmts = [];
36
- const { slug } = seed;
37
- for (const branch of seed.branches) {
38
- if (branch.type !== 'relation' || branch.multiple !== true)
39
- continue;
40
- const jt = junctionTableName(slug, branch.alias);
41
- stmts.push(`DROP TABLE IF EXISTS ${jt}_drafts;`);
42
- stmts.push(`DROP TABLE IF EXISTS ${jt};`);
43
- }
44
- stmts.push(...ftsTriggerDrops(slug));
45
- stmts.push(`DROP TABLE IF EXISTS content_${slug}_drafts;`);
46
- stmts.push(`DROP TABLE IF EXISTS content_${slug};`);
47
- return stmts;
48
- }
49
- /**
50
- * DROP COLUMN statements for a single branch (by alias).
51
- * For multi-relation branches: drops the junction tables (no column on parent).
52
- * For regular branches: drops from main table + drafts table (if allowDrafts).
53
- * Does NOT include FTS handling — callers must prepend ftsTriggerDrops() and
54
- * append planFtsRebuild() when the branch is searchable.
55
- */
56
- export function generateDropColumn(seed, alias) {
57
- const stmts = [];
58
- const { slug } = seed;
59
- const branch = seed.branches.find(b => b.alias === alias);
60
- if (!branch)
61
- throw new Error(`Branch '${alias}' not found in seed '${slug}'`);
62
- if (branch.type === 'relation' && branch.multiple === true) {
63
- const jt = junctionTableName(slug, alias);
64
- if (seed.allowDrafts)
65
- stmts.push(`DROP TABLE IF EXISTS ${jt}_drafts;`);
66
- stmts.push(`DROP TABLE IF EXISTS ${jt};`);
67
- }
68
- else {
69
- stmts.push(`ALTER TABLE content_${slug} DROP COLUMN ${alias};`);
70
- if (seed.allowDrafts)
71
- stmts.push(`ALTER TABLE content_${slug}_drafts DROP COLUMN ${alias};`);
72
- }
73
- return stmts;
74
- }
75
- /**
76
- * RENAME COLUMN statements for a branch alias change.
77
- * Updates main table + drafts (if allowDrafts).
78
- * Does NOT handle FTS — callers must rebuild FTS separately (SQLite auto-updates
79
- * trigger bodies on RENAME but the FTS virtual-table columns keep the old name).
80
- */
81
- export function generateRenameColumn(seed, fromAlias, toAlias) {
82
- const stmts = [];
83
- const { slug } = seed;
84
- stmts.push(`ALTER TABLE content_${slug} RENAME COLUMN ${fromAlias} TO ${toAlias};`);
85
- if (seed.allowDrafts) {
86
- stmts.push(`ALTER TABLE content_${slug}_drafts RENAME COLUMN ${fromAlias} TO ${toAlias};`);
87
- }
88
- return stmts;
89
- }
90
- /**
91
- * Full FTS rebuild: drop triggers + FTS table, then recreate them, then backfill.
92
- * Returns an empty array if the seed has no searchable branches.
93
- * The drop steps use IF EXISTS so this is safe to call even if FTS was already dropped.
94
- */
95
- export function planFtsRebuild(seed) {
96
- const rtBranches = searchBranches(seed);
97
- if (rtBranches.length === 0)
98
- return [];
99
- const { slug } = seed;
100
- const stmts = [...ftsTriggerDrops(slug)];
101
- const ftsTable = generateFtsTable(seed);
102
- if (ftsTable)
103
- stmts.push(ftsTable);
104
- stmts.push(...generateFtsTriggers(seed));
105
- const cols = rtBranches.map(b => b.alias);
106
- stmts.push(`INSERT INTO fts_${slug}(entry_id, ${cols.join(', ')}) SELECT id, ${cols.join(', ')} FROM content_${slug};`);
107
- return stmts;
108
- }
109
- /**
110
- * Generates statements to change a branch's SQL storage type using the
111
- * add-new-column / copy / drop-old / rename approach.
112
- * Includes FTS rebuild statements when the branch is (or becomes) searchable.
113
- * `updatedSeed` must already reflect the new type on the renamed branch.
114
- */
115
- export function planRetypeColumn(seed, alias, newType, updatedSeed) {
116
- const branch = seed.branches.find(b => b.alias === alias);
117
- if (!branch)
118
- throw new Error(`Branch '${alias}' not found in seed '${seed.slug}'`);
119
- const { slug } = seed;
120
- const newSqlType = BRANCH_SQL_TYPE[newType];
121
- const tmpAlias = `${alias}_migrate`;
122
- const stmts = [];
123
- // Always drop FTS first to avoid "column referenced in trigger" errors on DROP COLUMN.
124
- stmts.push(...ftsTriggerDrops(slug));
125
- // Drop the branch index if it exists on the old column (required before DROP COLUMN).
126
- if (INDEXABLE_TYPES.has(branch.type) && branch.policies?.filter !== false) {
127
- stmts.push(`DROP INDEX IF EXISTS idx_${slug}_${alias};`);
128
- }
129
- // Main table: add migration column, copy data, drop old, rename.
130
- stmts.push(`ALTER TABLE content_${slug} ADD COLUMN ${tmpAlias} ${newSqlType};`);
131
- stmts.push(`UPDATE content_${slug} SET ${tmpAlias} = CAST(${alias} AS ${newSqlType});`);
132
- stmts.push(`ALTER TABLE content_${slug} DROP COLUMN ${alias};`);
133
- stmts.push(`ALTER TABLE content_${slug} RENAME COLUMN ${tmpAlias} TO ${alias};`);
134
- // Recreate index for the renamed column if the new type warrants it.
135
- if (INDEXABLE_TYPES.has(newType) && branch.policies?.filter !== false) {
136
- stmts.push(`CREATE INDEX IF NOT EXISTS idx_${slug}_${alias} ON content_${slug}(${alias});`);
137
- }
138
- // Drafts table (no indexes to worry about).
139
- if (seed.allowDrafts) {
140
- stmts.push(`ALTER TABLE content_${slug}_drafts ADD COLUMN ${tmpAlias} ${newSqlType};`);
141
- stmts.push(`UPDATE content_${slug}_drafts SET ${tmpAlias} = CAST(${alias} AS ${newSqlType});`);
142
- stmts.push(`ALTER TABLE content_${slug}_drafts DROP COLUMN ${alias};`);
143
- stmts.push(`ALTER TABLE content_${slug}_drafts RENAME COLUMN ${tmpAlias} TO ${alias};`);
144
- }
145
- // Rebuild FTS if the seed has searchable branches in the updated definition.
146
- const rebuild = planFtsRebuild(updatedSeed);
147
- stmts.push(...rebuild);
148
- return { statements: stmts, ftsRebuildNeeded: rebuild.length > 0 };
149
- }
@@ -1,40 +0,0 @@
1
- import type { Seed } from './types.js';
2
- /**
3
- * Full create-from-scratch statement set for a seed. Mirrors the CLI's buildStatements.
4
- * Order: parent table → indexes → draft table → FTS table → FTS triggers →
5
- * per multi-relation: junction table → junction indexes → junction draft table.
6
- * Callers that create several seeds must order seeds with sortSeedsByDependencies
7
- * first so relation FK targets exist.
8
- */
9
- export declare function planCreateSeed(seed: Seed): string[];
10
- export interface ExtendPlan {
11
- statements: string[];
12
- ftsRebuildNeeded: boolean;
13
- }
14
- /**
15
- * Additive extension: given the columns that already exist on content_{slug}
16
- * (from PRAGMA table_info, passed in by the caller), return ONLY the statements
17
- * needed to add new branches — ADD COLUMN + indexes, plus junction tables for
18
- * new multi-relation branches. Never drops or renames.
19
- *
20
- * FTS: SQLite cannot ALTER an fts5 table's columns. If a new text/richtext
21
- * searchable branch was added, ftsRebuildNeeded=true signals the caller
22
- * (sprint 03) to handle it — no DROP is emitted.
23
- */
24
- export declare function planExtendSeed(seed: Seed, existingColumns: Set<string>): ExtendPlan;
25
- /**
26
- * Destructive FTS rebuild (sprint 06). SQLite cannot ALTER an fts5 table's
27
- * columns, so when a searchable branch is added, renamed, retyped, or dropped
28
- * the only correct fix is to drop and recreate the `fts_{slug}` virtual table
29
- * (and its insert/update/delete triggers), then backfill from `content_{slug}`.
30
- *
31
- * Returns an empty array when the seed has no searchable branches — in that
32
- * case the caller should instead drop any leftover FTS table via
33
- * generateDropTable's FTS statements. The returned statements are destructive
34
- * and must run through ISchemaMutator.execDestructive, never execDdl.
35
- *
36
- * Order: drop triggers → drop fts table → recreate table → recreate triggers →
37
- * backfill existing rows.
38
- */
39
- export declare function planFtsRebuild(seed: Seed): string[];
40
- //# sourceMappingURL=seed-ddl.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seed-ddl.d.ts","sourceRoot":"","sources":["../../src/engine/seed-ddl.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AActC;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAanD;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,UAAU,CAqBnF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CA0BnD"}
@@ -1,100 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- import { generateCreateTable, generateDraftTable, generateIndexes, generateFtsTable, generateFtsTriggers, generateAddColumn, generateJunctionTable, generateJunctionIndexes, generateJunctionDraftTable, indexableSearchBranches, } from './engine.js';
4
- /**
5
- * Full create-from-scratch statement set for a seed. Mirrors the CLI's buildStatements.
6
- * Order: parent table → indexes → draft table → FTS table → FTS triggers →
7
- * per multi-relation: junction table → junction indexes → junction draft table.
8
- * Callers that create several seeds must order seeds with sortSeedsByDependencies
9
- * first so relation FK targets exist.
10
- */
11
- export function planCreateSeed(seed) {
12
- const stmts = [generateCreateTable(seed), ...generateIndexes(seed)];
13
- const draft = generateDraftTable(seed);
14
- if (draft)
15
- stmts.push(draft);
16
- const fts = generateFtsTable(seed);
17
- if (fts)
18
- stmts.push(fts, ...generateFtsTriggers(seed));
19
- for (const branch of seed.branches) {
20
- if (branch.type !== 'relation' || branch.multiple !== true)
21
- continue;
22
- stmts.push(generateJunctionTable(seed, branch), ...generateJunctionIndexes(seed, branch));
23
- const dj = generateJunctionDraftTable(seed, branch);
24
- if (dj)
25
- stmts.push(dj);
26
- }
27
- return stmts;
28
- }
29
- /**
30
- * Additive extension: given the columns that already exist on content_{slug}
31
- * (from PRAGMA table_info, passed in by the caller), return ONLY the statements
32
- * needed to add new branches — ADD COLUMN + indexes, plus junction tables for
33
- * new multi-relation branches. Never drops or renames.
34
- *
35
- * FTS: SQLite cannot ALTER an fts5 table's columns. If a new text/richtext
36
- * searchable branch was added, ftsRebuildNeeded=true signals the caller
37
- * (sprint 03) to handle it — no DROP is emitted.
38
- */
39
- export function planExtendSeed(seed, existingColumns) {
40
- const statements = [];
41
- let ftsRebuildNeeded = false;
42
- for (const branch of seed.branches) {
43
- if (branch.type === 'relation' && branch.multiple === true) {
44
- // junction table is CREATE IF NOT EXISTS — safe to re-emit
45
- statements.push(generateJunctionTable(seed, branch), ...generateJunctionIndexes(seed, branch));
46
- const dj = generateJunctionDraftTable(seed, branch);
47
- if (dj)
48
- statements.push(dj);
49
- continue;
50
- }
51
- if (existingColumns.has(branch.alias))
52
- continue;
53
- statements.push(generateAddColumn(seed, branch));
54
- if ((branch.type === 'text' || branch.type === 'richtext') && branch.policies?.search !== false) {
55
- ftsRebuildNeeded = true;
56
- }
57
- }
58
- // CREATE INDEX IF NOT EXISTS — idempotent, safe to re-run
59
- statements.push(...generateIndexes(seed));
60
- return { statements, ftsRebuildNeeded };
61
- }
62
- /**
63
- * Destructive FTS rebuild (sprint 06). SQLite cannot ALTER an fts5 table's
64
- * columns, so when a searchable branch is added, renamed, retyped, or dropped
65
- * the only correct fix is to drop and recreate the `fts_{slug}` virtual table
66
- * (and its insert/update/delete triggers), then backfill from `content_{slug}`.
67
- *
68
- * Returns an empty array when the seed has no searchable branches — in that
69
- * case the caller should instead drop any leftover FTS table via
70
- * generateDropTable's FTS statements. The returned statements are destructive
71
- * and must run through ISchemaMutator.execDestructive, never execDdl.
72
- *
73
- * Order: drop triggers → drop fts table → recreate table → recreate triggers →
74
- * backfill existing rows.
75
- */
76
- export function planFtsRebuild(seed) {
77
- const branches = indexableSearchBranches(seed);
78
- if (branches.length === 0)
79
- return [];
80
- const slug = seed.slug;
81
- const ftsTable = `fts_${slug}`;
82
- const contentTable = `content_${slug}`;
83
- const cols = branches.map(b => b.alias);
84
- const ftsTableDdl = generateFtsTable(seed);
85
- const triggers = generateFtsTriggers(seed);
86
- // generateFtsTable/Triggers return non-null here (branches.length > 0 checked).
87
- if (!ftsTableDdl)
88
- return [];
89
- const ftsColList = ['entry_id', ...cols].join(', ');
90
- const selectList = ['id', ...cols].join(', ');
91
- return [
92
- `DROP TRIGGER IF EXISTS fts_${slug}_insert;`,
93
- `DROP TRIGGER IF EXISTS fts_${slug}_update;`,
94
- `DROP TRIGGER IF EXISTS fts_${slug}_delete;`,
95
- `DROP TABLE IF EXISTS ${ftsTable};`,
96
- ftsTableDdl,
97
- ...triggers,
98
- `INSERT INTO ${ftsTable}(${ftsColList}) SELECT ${selectList} FROM ${contentTable};`,
99
- ];
100
- }
@@ -1,71 +0,0 @@
1
- import type { Seed, Branch } from './types.js';
2
- export interface ISeedRegistry {
3
- /**
4
- * Returns all seeds as a flat array, preserving insertion order.
5
- * Decouples callers from the internal storage shape so the registry
6
- * implementation can change without touching every route handler.
7
- */
8
- all(): Seed[];
9
- /**
10
- * Returns the seed with the given slug, or null if not found.
11
- * Provides a single lookup point that can be overridden in tests
12
- * without rebuilding the full registry object.
13
- */
14
- get(slug: string): Seed | null;
15
- /**
16
- * Returns seeds that are visible in the dashboard sidebar.
17
- * A seed is visible when dashboard.hidden is not explicitly true.
18
- * Eliminates the seeds.filter(s => !s.dashboard?.hidden) pattern
19
- * that would otherwise be duplicated across route handlers.
20
- */
21
- visibleInDashboard(): Seed[];
22
- /**
23
- * Returns seeds that have allowPublicRead enabled.
24
- * Eliminates the seeds.filter(s => s.allowPublicRead) pattern.
25
- */
26
- publicReadable(): Seed[];
27
- /**
28
- * Returns seeds that have the draft workflow enabled.
29
- * Eliminates the seeds.filter(s => s.allowDrafts) pattern.
30
- */
31
- draftEnabled(): Seed[];
32
- }
33
- export declare class SeedRegistry implements ISeedRegistry {
34
- private readonly seedMap;
35
- private readonly orderedSeeds;
36
- constructor(seeds: Seed[]);
37
- all(): Seed[];
38
- get(slug: string): Seed | null;
39
- visibleInDashboard(): Seed[];
40
- publicReadable(): Seed[];
41
- draftEnabled(): Seed[];
42
- }
43
- /**
44
- * Named subclass of SeedRegistry for use in test suites.
45
- * Gives tests a semantic name without requiring any dependency on factory.ts.
46
- */
47
- export declare class InMemorySeedRegistry extends SeedRegistry {
48
- }
49
- /** Finds a branch by its stable id within a Seed. Returns null if not found. */
50
- export declare function findBranchById(seed: Seed, id: string): Branch | null;
51
- /**
52
- * Returns the next free branch id for a seed in the form `br_NN` (zero-padded to 2,
53
- * growing as needed). Scans existing ids, never reuses a number already present —
54
- * even if a branch was removed, its id is not recycled (ids must be globally stable
55
- * for the life of the seed so layouts/automations/FTS triggers never collide).
56
- */
57
- export declare function nextBranchId(seed: Pick<Seed, 'branches'>): string;
58
- /**
59
- * Returns the input seeds reordered so that every seed appears AFTER all the
60
- * seeds it depends on (its `relation` branch targets). Pure function — does
61
- * not read from any global registry.
62
- *
63
- * Uses Kahn's algorithm (BFS on in-degree) for cycle detection and topological
64
- * ordering. Sprint 3 (CLI / migration runner) consumes this to create tables in
65
- * the correct order without disabling SQLite FK constraints.
66
- *
67
- * @throws {Error} When a relation targets an unknown slug not in `seeds`.
68
- * @throws {Error} When a cyclic dependency is detected, listing involved slugs.
69
- */
70
- export declare function sortSeedsByDependencies(seeds: ReadonlyArray<Seed>): Seed[];
71
- //# sourceMappingURL=seed-registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seed-registry.d.ts","sourceRoot":"","sources":["../../src/engine/seed-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAI9C,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,IAAI,IAAI,EAAE,CAAA;IAEb;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAE9B;;;;;OAKG;IACH,kBAAkB,IAAI,IAAI,EAAE,CAAA;IAE5B;;;OAGG;IACH,cAAc,IAAI,IAAI,EAAE,CAAA;IAExB;;;OAGG;IACH,YAAY,IAAI,IAAI,EAAE,CAAA;CACvB;AAID,qBAAa,YAAa,YAAW,aAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IAErC,YAAY,KAAK,EAAE,IAAI,EAAE,EAgCxB;IAED,GAAG,IAAI,IAAI,EAAE,CAEZ;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE7B;IAED,kBAAkB,IAAI,IAAI,EAAE,CAE3B;IAED,cAAc,IAAI,IAAI,EAAE,CAEvB;IAED,YAAY,IAAI,IAAI,EAAE,CAErB;CACF;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;CAAG;AAEzD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,MAAM,CAQjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CA0F1E"}