@prisma/orm-target-sqlite 8.0.0-rc.14-dev.11 → 8.0.0-rc.14-dev.13

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 (42) hide show
  1. package/dist/{migration-Y6M_R3GK.mjs → migration-BQaFOngL.mjs} +2 -2
  2. package/dist/{migration-Y6M_R3GK.mjs.map → migration-BQaFOngL.mjs.map} +1 -1
  3. package/dist/{migration-dc58fySD.d.mts → migration-LE8F9qcM.d.mts} +2 -2
  4. package/dist/{migration-dc58fySD.d.mts.map → migration-LE8F9qcM.d.mts.map} +1 -1
  5. package/dist/{op-factory-call-4FJxPMyx.d.mts → op-factory-call-B_WuATMN.d.mts} +15 -3
  6. package/dist/op-factory-call-B_WuATMN.d.mts.map +1 -0
  7. package/dist/{op-factory-call-Dv_ma_mw-BtLqNmZI.mjs → op-factory-call-DFDt6p_b-CN07t9pu.mjs} +114 -15
  8. package/dist/op-factory-call-DFDt6p_b-CN07t9pu.mjs.map +1 -0
  9. package/dist/{planner-Bsjn1MTX.d.mts → planner-B37W4Kaw.d.mts} +2 -2
  10. package/dist/{planner-Bsjn1MTX.d.mts.map → planner-B37W4Kaw.d.mts.map} +1 -1
  11. package/dist/{planner-produced-sqlite-migration-BQ8vBitH-DlquRDZ4.d.mts → planner-produced-sqlite-migration-C6t5lWDq-DXm-Vkhf.d.mts} +4 -4
  12. package/dist/planner-produced-sqlite-migration-C6t5lWDq-DXm-Vkhf.d.mts.map +1 -0
  13. package/dist/planner-produced-sqlite-migration-D7O3_r38.d.mts +1 -0
  14. package/dist/{planner-produced-sqlite-migration-D1iuFT1l-BSFCXgJD.mjs → planner-produced-sqlite-migration-v5i-Qz6p-D2ezVWv0.mjs} +3 -3
  15. package/dist/{planner-produced-sqlite-migration-D1iuFT1l-BSFCXgJD.mjs.map → planner-produced-sqlite-migration-v5i-Qz6p-D2ezVWv0.mjs.map} +1 -1
  16. package/dist/planner-rTeVmEl6-EkIM6GZa.mjs +191 -0
  17. package/dist/planner-rTeVmEl6-EkIM6GZa.mjs.map +1 -0
  18. package/dist/{sqlite-migration-Du67NG7r-CqcA5XBz.d.mts → sqlite-migration-2IEGvjRm-BQfd6NLr.d.mts} +11 -3
  19. package/dist/sqlite-migration-2IEGvjRm-BQfd6NLr.d.mts.map +1 -0
  20. package/dist/{planner-CWfPzOwZ-DVj6Tm5a.mjs → sqlite-migration-D1Zk_YEy-BRKDlY8h.mjs} +173 -165
  21. package/dist/sqlite-migration-D1Zk_YEy-BRKDlY8h.mjs.map +1 -0
  22. package/dist/target.d.mts +7 -7
  23. package/dist/target.mjs +7 -7
  24. package/dist/target__control.mjs +2 -1
  25. package/dist/target__control.mjs.map +1 -1
  26. package/dist/target__migration.d.mts +2 -2
  27. package/dist/target__migration.mjs +2 -2
  28. package/dist/target__op-factory-call.d.mts +2 -2
  29. package/dist/target__op-factory-call.mjs +2 -2
  30. package/dist/target__planner-produced-sqlite-migration.d.mts +2 -2
  31. package/dist/target__planner-produced-sqlite-migration.mjs +1 -1
  32. package/dist/target__planner.d.mts +1 -1
  33. package/dist/target__planner.mjs +1 -1
  34. package/package.json +9 -9
  35. package/dist/op-factory-call-4FJxPMyx.d.mts.map +0 -1
  36. package/dist/op-factory-call-Dv_ma_mw-BtLqNmZI.mjs.map +0 -1
  37. package/dist/planner-CWfPzOwZ-DVj6Tm5a.mjs.map +0 -1
  38. package/dist/planner-produced-sqlite-migration-BQ8vBitH-DlquRDZ4.d.mts.map +0 -1
  39. package/dist/planner-produced-sqlite-migration-BfFAqrKj.d.mts +0 -1
  40. package/dist/sqlite-migration-Du67NG7r-CqcA5XBz.d.mts.map +0 -1
  41. package/dist/sqlite-migration-DuQG9WLW-BqHx4fMJ.mjs +0 -94
  42. package/dist/sqlite-migration-DuQG9WLW-BqHx4fMJ.mjs.map +0 -1
@@ -0,0 +1,191 @@
1
+ import { m as renameTableSteps, u as RenameTableCall } from "./op-factory-call-DFDt6p_b-CN07t9pu.mjs";
2
+ import { c as pairIndexReplacements, d as sqlitePlannerStrategies, i as conflictForDisallowedCall, l as planIssues, n as buildSqlitePlanDiff, o as indexNameCaseChange, r as coalesceSubtreeIssues, s as issueNode } from "./sqlite-migration-D1Zk_YEy-BRKDlY8h.mjs";
3
+ import { t as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-v5i-Qz6p-D2ezVWv0.mjs";
4
+ import { issueOutcome } from "@prisma/orm-framework/components/control";
5
+ import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
6
+ import { RelationalSchemaNodeKind, SqlTableIR } from "@prisma/orm-family-sql/schema-ir/types";
7
+ import { detectTableNameCaseChanges, extractCodecControlHooks, planFieldEventOperations, plannerFailure } from "@prisma/orm-family-sql/family/control";
8
+ //#region ../../../3-targets/3-targets/sqlite/dist/planner-rTeVmEl6.mjs
9
+ function createSqliteMigrationPlanner(lowerer) {
10
+ return new SqliteMigrationPlanner(lowerer);
11
+ }
12
+ /**
13
+ * SQLite migration planner — a thin wrapper over `planIssues`.
14
+ *
15
+ * `plan()` diffs the live schema against the target contract via the one
16
+ * differ (`buildSqlitePlanDiff`, producing node-typed `SchemaDiffIssue[]`)
17
+ * and delegates to `planIssues` with the registered strategies. Strategies
18
+ * absorb groups of related issues into composite recipes (e.g. recreating a
19
+ * table to apply type/nullability/default/constraint changes at once);
20
+ * anything not absorbed by a strategy flows through `mapNodeIssueToCall` in
21
+ * the issue planner as a one-off call.
22
+ *
23
+ * FK-backing indexes are already merged into the expected table node's
24
+ * `indexes` at derivation (`contractToSchemaIR`'s `convertTable`), so
25
+ * `mapNodeIssueToCall` handles them uniformly alongside user-declared
26
+ * indexes — no separate expansion step in the planner.
27
+ */
28
+ var SqliteMigrationPlanner = class {
29
+ #lowerer;
30
+ constructor(lowerer) {
31
+ this.#lowerer = lowerer;
32
+ }
33
+ plan(options) {
34
+ return this.planSql(options);
35
+ }
36
+ emptyMigration(context, spaceId) {
37
+ return new TypeScriptRenderableSqliteMigration([], {
38
+ from: context.fromHash,
39
+ to: context.toHash
40
+ }, spaceId, context.snapshotsImportPath, void 0, this.#lowerer);
41
+ }
42
+ planSql(options) {
43
+ const policyResult = this.ensureAdditivePolicy(options.policy);
44
+ if (policyResult) return policyResult;
45
+ const { expected, actual, issues: diffIssues } = this.collectSchemaIssues(options);
46
+ const replacedIndexes = pairIndexReplacements(diffIssues, indexNameCaseChange);
47
+ const disallowedIndexCalls = replacedIndexes.calls.filter((call) => !options.policy.allowedOperationClasses.includes(call.operationClass));
48
+ if (disallowedIndexCalls.length > 0) return plannerFailure(disallowedIndexCalls.map((call) => conflictForDisallowedCall(call, options.policy.allowedOperationClasses)));
49
+ const issues = diffIssues.filter((issue) => !replacedIndexes.consumed.has(issue));
50
+ const caseChangeConflicts = detectTableNameCaseChanges({
51
+ issues,
52
+ tableOf: (issue) => {
53
+ const node = issueNode(issue);
54
+ return node instanceof SqlTableIR ? node : void 0;
55
+ },
56
+ namespaceIdOf: () => UNBOUND_NAMESPACE_ID,
57
+ renameByHandStatements: (rename) => renameTableSteps(rename.from, rename.to).map((renameStep) => renameStep.sql),
58
+ renameTableCall: (rename) => new RenameTableCall(rename.from, rename.to).renderTypeScript(),
59
+ contract: options.contract,
60
+ defaultNamespaceId: UNBOUND_NAMESPACE_ID
61
+ });
62
+ if (caseChangeConflicts.length > 0) return plannerFailure(caseChangeConflicts);
63
+ const codecHooks = extractCodecControlHooks(options.frameworkComponents);
64
+ const result = planIssues({
65
+ issues,
66
+ expected,
67
+ actual,
68
+ policy: options.policy,
69
+ frameworkComponents: options.frameworkComponents,
70
+ strategies: sqlitePlannerStrategies
71
+ });
72
+ if (!result.ok) return plannerFailure(result.failure);
73
+ const fieldEventOps = planFieldEventOperations({
74
+ priorContract: options.fromContract,
75
+ newContract: options.contract,
76
+ codecHooks
77
+ });
78
+ const calls = [
79
+ ...replacedIndexes.calls,
80
+ ...result.value.calls,
81
+ ...fieldEventOps
82
+ ];
83
+ const destination = {
84
+ storageHash: options.contract.storage.storageHash,
85
+ ...options.contract.profileHash !== void 0 ? { profileHash: options.contract.profileHash } : {}
86
+ };
87
+ return {
88
+ kind: "success",
89
+ plan: new TypeScriptRenderableSqliteMigration(calls, {
90
+ from: options.fromContract?.storage.storageHash ?? null,
91
+ to: options.contract.storage.storageHash
92
+ }, options.spaceId, options.snapshotsImportPath, destination, this.#lowerer)
93
+ };
94
+ }
95
+ ensureAdditivePolicy(policy) {
96
+ if (!policy.allowedOperationClasses.includes("additive")) return plannerFailure([{
97
+ kind: "unsupportedOperation",
98
+ summary: "Migration planner requires additive operations be allowed",
99
+ why: "The planner requires the \"additive\" operation class to be allowed in the policy."
100
+ }]);
101
+ return null;
102
+ }
103
+ /**
104
+ * Diffs the target contract against the live schema via the one differ
105
+ * (the same tree-building `diffSqliteSchema` uses, plus the
106
+ * op-render stamper) and prepares the issue list `planIssues` consumes.
107
+ *
108
+ * Three passes, in order:
109
+ * 1. Subtree coalescing — the differ is total (a missing/extra table also
110
+ * emits an issue for every column/constraint under it); those nested
111
+ * issues are redundant once the table-level `CreateTable`/`DropTable`
112
+ * call already accounts for the whole subtree. Runs FIRST, over the
113
+ * complete diff: a sibling-owned extra table's column issues must
114
+ * collapse into its one table-level issue before the ownership pass,
115
+ * because a bare column node carries no table reference — if coalescing
116
+ * ran after ownership dropped the table-level issue, the orphaned column
117
+ * issues would survive and the planner would emit drops against a
118
+ * sibling space's table.
119
+ * 2. Ownership — a live extra is only this plan's to drop when no contract
120
+ * space owns it. The differ ran against THIS space's contract, so a
121
+ * table a sibling owns surfaces here as `not-expected`; the planner asks
122
+ * the ownership oracle (the passive aggregate) whether any space declares
123
+ * it and, if so, leaves it alone. A table no space owns stays a genuine
124
+ * extra. Ownership lives in the aggregate; the planner only asks. No
125
+ * oracle (single-space) keeps every extra.
126
+ * 3. Strict-mode extras gating — `not-expected` (extra table/column/
127
+ * constraint) issues are dropped entirely outside strict mode, mirroring
128
+ * the retired coordinate walk's `if (strict) { ...extra_* } }` guards:
129
+ * an additive-only plan must never even consider dropping an unclaimed
130
+ * object, not just refuse to emit the drop.
131
+ */
132
+ collectSchemaIssues(options) {
133
+ const allowed = options.policy.allowedOperationClasses;
134
+ const strict = allowed.includes("widening") || allowed.includes("destructive");
135
+ const { expected, actual, issues: rawIssues } = buildSqlitePlanDiff({
136
+ contract: options.contract,
137
+ actualSchema: options.schema,
138
+ frameworkComponents: options.frameworkComponents
139
+ });
140
+ const owned = retainUnownedExtras(coalesceSubtreeIssues(rawIssues), options.ownership);
141
+ return {
142
+ expected,
143
+ actual,
144
+ issues: strict ? owned : owned.filter((issue) => issueOutcome(issue) !== "not-expected")
145
+ };
146
+ }
147
+ };
148
+ /**
149
+ * Drops a `not-expected` issue when it is a whole extra TABLE that some
150
+ * contract space owns, asking the ownership oracle per node.
151
+ *
152
+ * The consultation applies ONLY to table-level extras — a live table this
153
+ * space's contract lacks — identified by asking the issue's own node
154
+ * (`nodeKind === table`), never by counting path segments. SQLite is a
155
+ * single-namespace target, so every coordinate is qualified with the shared
156
+ * `UNBOUND_NAMESPACE_ID` sentinel (the same one the aggregate's declared
157
+ * entities carry for this target). `entityKind` is the literal `'table'`:
158
+ * this function only ever asks about a node already confirmed to be
159
+ * `RelationalSchemaNodeKind.table` (checked just above), and that's a
160
+ * diff-tree `nodeKind` spelling (`'sql-table'`) distinct from the storage
161
+ * `entries` vocabulary `elementCoordinates` walks (`'table'`) — the literal
162
+ * is that storage-entries spelling. `declaresEntity` answers over the whole
163
+ * composition (self included), so a positive answer on such a table means
164
+ * another space owns it (a table this space owned would be in its expected
165
+ * tree, never an extra): leave it. A negative answer means no space owns
166
+ * it — a genuine orphan to drop.
167
+ *
168
+ * A DEEPER extra (an extra column/constraint on a table this space DOES own —
169
+ * only the child drifted, so the table is in the expected tree) is this
170
+ * space's own drift and is always kept for dropping; asking the oracle there
171
+ * would wrongly suppress it, because the owned table answers `true`. No oracle
172
+ * ⇒ every extra is kept (single-space plan).
173
+ */
174
+ function retainUnownedExtras(issues, ownership) {
175
+ if (ownership === void 0) return issues;
176
+ return issues.filter((issue) => {
177
+ if (issueOutcome(issue) !== "not-expected") return true;
178
+ const node = issueNode(issue);
179
+ if (node === void 0 || node.nodeKind !== RelationalSchemaNodeKind.table) return true;
180
+ const tableName = issue.path[1];
181
+ return tableName === void 0 || !ownership.declaresEntity({
182
+ namespaceId: UNBOUND_NAMESPACE_ID,
183
+ entityKind: "table",
184
+ entityName: tableName
185
+ });
186
+ });
187
+ }
188
+ //#endregion
189
+ export { createSqliteMigrationPlanner as n, SqliteMigrationPlanner as t };
190
+
191
+ //# sourceMappingURL=planner-rTeVmEl6-EkIM6GZa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-rTeVmEl6-EkIM6GZa.mjs","names":["#lowerer"],"sources":["../../../../3-targets/3-targets/sqlite/dist/planner-rTeVmEl6.mjs"],"sourcesContent":["import { p as renameTableSteps, u as RenameTableCall } from \"./op-factory-call-DFDt6p_b.mjs\";\nimport { a as conflictForDisallowedCall, c as sqlitePlannerStrategies, i as coalesceSubtreeIssues, l as buildSqlitePlanDiff, n as indexNameCaseChange, o as issueNode, r as pairIndexReplacements, s as planIssues } from \"./sqlite-migration-D1Zk_YEy.mjs\";\nimport { t as TypeScriptRenderableSqliteMigration } from \"./planner-produced-sqlite-migration-v5i-Qz6p.mjs\";\nimport { issueOutcome } from \"@internal/framework-components/control\";\nimport { detectTableNameCaseChanges, extractCodecControlHooks, planFieldEventOperations, plannerFailure } from \"@internal/family-sql/control\";\nimport { RelationalSchemaNodeKind, SqlTableIR } from \"@internal/sql-schema-ir/types\";\nimport { UNBOUND_NAMESPACE_ID } from \"@internal/framework-components/ir\";\n//#region src/core/migrations/planner.ts\nfunction createSqliteMigrationPlanner(lowerer) {\n\treturn new SqliteMigrationPlanner(lowerer);\n}\n/**\n* SQLite migration planner — a thin wrapper over `planIssues`.\n*\n* `plan()` diffs the live schema against the target contract via the one\n* differ (`buildSqlitePlanDiff`, producing node-typed `SchemaDiffIssue[]`)\n* and delegates to `planIssues` with the registered strategies. Strategies\n* absorb groups of related issues into composite recipes (e.g. recreating a\n* table to apply type/nullability/default/constraint changes at once);\n* anything not absorbed by a strategy flows through `mapNodeIssueToCall` in\n* the issue planner as a one-off call.\n*\n* FK-backing indexes are already merged into the expected table node's\n* `indexes` at derivation (`contractToSchemaIR`'s `convertTable`), so\n* `mapNodeIssueToCall` handles them uniformly alongside user-declared\n* indexes — no separate expansion step in the planner.\n*/\nvar SqliteMigrationPlanner = class {\n\t#lowerer;\n\tconstructor(lowerer) {\n\t\tthis.#lowerer = lowerer;\n\t}\n\tplan(options) {\n\t\treturn this.planSql(options);\n\t}\n\temptyMigration(context, spaceId) {\n\t\treturn new TypeScriptRenderableSqliteMigration([], {\n\t\t\tfrom: context.fromHash,\n\t\t\tto: context.toHash\n\t\t}, spaceId, context.snapshotsImportPath, void 0, this.#lowerer);\n\t}\n\tplanSql(options) {\n\t\tconst policyResult = this.ensureAdditivePolicy(options.policy);\n\t\tif (policyResult) return policyResult;\n\t\tconst { expected, actual, issues: diffIssues } = this.collectSchemaIssues(options);\n\t\tconst replacedIndexes = pairIndexReplacements(diffIssues, indexNameCaseChange);\n\t\tconst disallowedIndexCalls = replacedIndexes.calls.filter((call) => !options.policy.allowedOperationClasses.includes(call.operationClass));\n\t\tif (disallowedIndexCalls.length > 0) return plannerFailure(disallowedIndexCalls.map((call) => conflictForDisallowedCall(call, options.policy.allowedOperationClasses)));\n\t\tconst issues = diffIssues.filter((issue) => !replacedIndexes.consumed.has(issue));\n\t\tconst caseChangeConflicts = detectTableNameCaseChanges({\n\t\t\tissues,\n\t\t\ttableOf: (issue) => {\n\t\t\t\tconst node = issueNode(issue);\n\t\t\t\treturn node instanceof SqlTableIR ? node : void 0;\n\t\t\t},\n\t\t\tnamespaceIdOf: () => UNBOUND_NAMESPACE_ID,\n\t\t\trenameByHandStatements: (rename) => renameTableSteps(rename.from, rename.to).map((renameStep) => renameStep.sql),\n\t\t\trenameTableCall: (rename) => new RenameTableCall(rename.from, rename.to).renderTypeScript(),\n\t\t\tcontract: options.contract,\n\t\t\tdefaultNamespaceId: UNBOUND_NAMESPACE_ID\n\t\t});\n\t\tif (caseChangeConflicts.length > 0) return plannerFailure(caseChangeConflicts);\n\t\tconst codecHooks = extractCodecControlHooks(options.frameworkComponents);\n\t\tconst result = planIssues({\n\t\t\tissues,\n\t\t\texpected,\n\t\t\tactual,\n\t\t\tpolicy: options.policy,\n\t\t\tframeworkComponents: options.frameworkComponents,\n\t\t\tstrategies: sqlitePlannerStrategies\n\t\t});\n\t\tif (!result.ok) return plannerFailure(result.failure);\n\t\tconst fieldEventOps = planFieldEventOperations({\n\t\t\tpriorContract: options.fromContract,\n\t\t\tnewContract: options.contract,\n\t\t\tcodecHooks\n\t\t});\n\t\tconst calls = [\n\t\t\t...replacedIndexes.calls,\n\t\t\t...result.value.calls,\n\t\t\t...fieldEventOps\n\t\t];\n\t\tconst destination = {\n\t\t\tstorageHash: options.contract.storage.storageHash,\n\t\t\t...options.contract.profileHash !== void 0 ? { profileHash: options.contract.profileHash } : {}\n\t\t};\n\t\treturn {\n\t\t\tkind: \"success\",\n\t\t\tplan: new TypeScriptRenderableSqliteMigration(calls, {\n\t\t\t\tfrom: options.fromContract?.storage.storageHash ?? null,\n\t\t\t\tto: options.contract.storage.storageHash\n\t\t\t}, options.spaceId, options.snapshotsImportPath, destination, this.#lowerer)\n\t\t};\n\t}\n\tensureAdditivePolicy(policy) {\n\t\tif (!policy.allowedOperationClasses.includes(\"additive\")) return plannerFailure([{\n\t\t\tkind: \"unsupportedOperation\",\n\t\t\tsummary: \"Migration planner requires additive operations be allowed\",\n\t\t\twhy: \"The planner requires the \\\"additive\\\" operation class to be allowed in the policy.\"\n\t\t}]);\n\t\treturn null;\n\t}\n\t/**\n\t* Diffs the target contract against the live schema via the one differ\n\t* (the same tree-building `diffSqliteSchema` uses, plus the\n\t* op-render stamper) and prepares the issue list `planIssues` consumes.\n\t*\n\t* Three passes, in order:\n\t* 1. Subtree coalescing — the differ is total (a missing/extra table also\n\t* emits an issue for every column/constraint under it); those nested\n\t* issues are redundant once the table-level `CreateTable`/`DropTable`\n\t* call already accounts for the whole subtree. Runs FIRST, over the\n\t* complete diff: a sibling-owned extra table's column issues must\n\t* collapse into its one table-level issue before the ownership pass,\n\t* because a bare column node carries no table reference — if coalescing\n\t* ran after ownership dropped the table-level issue, the orphaned column\n\t* issues would survive and the planner would emit drops against a\n\t* sibling space's table.\n\t* 2. Ownership — a live extra is only this plan's to drop when no contract\n\t* space owns it. The differ ran against THIS space's contract, so a\n\t* table a sibling owns surfaces here as `not-expected`; the planner asks\n\t* the ownership oracle (the passive aggregate) whether any space declares\n\t* it and, if so, leaves it alone. A table no space owns stays a genuine\n\t* extra. Ownership lives in the aggregate; the planner only asks. No\n\t* oracle (single-space) keeps every extra.\n\t* 3. Strict-mode extras gating — `not-expected` (extra table/column/\n\t* constraint) issues are dropped entirely outside strict mode, mirroring\n\t* the retired coordinate walk's `if (strict) { ...extra_* } }` guards:\n\t* an additive-only plan must never even consider dropping an unclaimed\n\t* object, not just refuse to emit the drop.\n\t*/\n\tcollectSchemaIssues(options) {\n\t\tconst allowed = options.policy.allowedOperationClasses;\n\t\tconst strict = allowed.includes(\"widening\") || allowed.includes(\"destructive\");\n\t\tconst { expected, actual, issues: rawIssues } = buildSqlitePlanDiff({\n\t\t\tcontract: options.contract,\n\t\t\tactualSchema: options.schema,\n\t\t\tframeworkComponents: options.frameworkComponents\n\t\t});\n\t\tconst owned = retainUnownedExtras(coalesceSubtreeIssues(rawIssues), options.ownership);\n\t\treturn {\n\t\t\texpected,\n\t\t\tactual,\n\t\t\tissues: strict ? owned : owned.filter((issue) => issueOutcome(issue) !== \"not-expected\")\n\t\t};\n\t}\n};\n/**\n* Drops a `not-expected` issue when it is a whole extra TABLE that some\n* contract space owns, asking the ownership oracle per node.\n*\n* The consultation applies ONLY to table-level extras — a live table this\n* space's contract lacks — identified by asking the issue's own node\n* (`nodeKind === table`), never by counting path segments. SQLite is a\n* single-namespace target, so every coordinate is qualified with the shared\n* `UNBOUND_NAMESPACE_ID` sentinel (the same one the aggregate's declared\n* entities carry for this target). `entityKind` is the literal `'table'`:\n* this function only ever asks about a node already confirmed to be\n* `RelationalSchemaNodeKind.table` (checked just above), and that's a\n* diff-tree `nodeKind` spelling (`'sql-table'`) distinct from the storage\n* `entries` vocabulary `elementCoordinates` walks (`'table'`) — the literal\n* is that storage-entries spelling. `declaresEntity` answers over the whole\n* composition (self included), so a positive answer on such a table means\n* another space owns it (a table this space owned would be in its expected\n* tree, never an extra): leave it. A negative answer means no space owns\n* it — a genuine orphan to drop.\n*\n* A DEEPER extra (an extra column/constraint on a table this space DOES own —\n* only the child drifted, so the table is in the expected tree) is this\n* space's own drift and is always kept for dropping; asking the oracle there\n* would wrongly suppress it, because the owned table answers `true`. No oracle\n* ⇒ every extra is kept (single-space plan).\n*/\nfunction retainUnownedExtras(issues, ownership) {\n\tif (ownership === void 0) return issues;\n\treturn issues.filter((issue) => {\n\t\tif (issueOutcome(issue) !== \"not-expected\") return true;\n\t\tconst node = issueNode(issue);\n\t\tif (node === void 0 || node.nodeKind !== RelationalSchemaNodeKind.table) return true;\n\t\tconst tableName = issue.path[1];\n\t\treturn tableName === void 0 || !ownership.declaresEntity({\n\t\t\tnamespaceId: UNBOUND_NAMESPACE_ID,\n\t\t\tentityKind: \"table\",\n\t\t\tentityName: tableName\n\t\t});\n\t});\n}\n//#endregion\nexport { createSqliteMigrationPlanner as n, SqliteMigrationPlanner as t };\n\n//# sourceMappingURL=planner-rTeVmEl6.mjs.map"],"mappings":"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"}
@@ -4,11 +4,11 @@ import { t as SqliteContractView } from "./sqlite-contract-view-BpNMaU2m-COMDaGa
4
4
  import { DdlColumn, DdlTableConstraint } from "@prisma/orm-family-sql/relational-core/ast";
5
5
  import { ControlStack } from "@prisma/orm-framework/components/control";
6
6
  import { SqlStorage } from "@prisma/orm-family-sql/contract/types";
7
- import { Migration } from "@prisma/orm-family-sql/family/migration";
8
7
  import { MigrationOperationClass, SqlMigrationPlanOperation } from "@prisma/orm-family-sql/family/control";
8
+ import { Migration } from "@prisma/orm-family-sql/family/migration";
9
9
  import { Contract } from "@prisma/orm-framework/contract/types";
10
10
  import { SqlControlAdapter } from "@prisma/orm-family-sql/family/control-adapter";
11
- //#region ../../../3-targets/3-targets/sqlite/dist/sqlite-migration-Du67NG7r.d.mts
11
+ //#region ../../../3-targets/3-targets/sqlite/dist/sqlite-migration-2IEGvjRm.d.mts
12
12
  //#region src/core/migrations/sqlite-migration.d.ts
13
13
  type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
14
14
  /**
@@ -44,6 +44,7 @@ declare abstract class SqliteMigration<Start extends Contract<SqlStorage> = Cont
44
44
  */
45
45
  protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;
46
46
  constructor(stack?: ControlStack<'sql', 'sqlite'>);
47
+ private frameworkComponents;
47
48
  /**
48
49
  * Returns the materialized control adapter, or throws a MIGRATION.SQLITE_CONTROL_STACK_MISSING naming
49
50
  * `operation` when the migration was constructed without a `ControlStack`.
@@ -70,6 +71,13 @@ declare abstract class SqliteMigration<Start extends Contract<SqlStorage> = Cont
70
71
  protected dropTable(options: {
71
72
  readonly table: string;
72
73
  }): Promise<Op>;
74
+ /**
75
+ * Emit the operations that rename a table: the table rename, then a drop and a create under the new name of each index whose name was derived from the old table name, read from this migration's start and end contracts. Spread the result into `operations`: `...this.renameTable({ table: 'userProfile', to: 'UserProfile' })`. Throws `MIGRATION.TABLE_RENAME_UNMATCHED` when the start contract lacks the table or the end contract lacks the new name.
76
+ */
77
+ protected renameTable(options: {
78
+ readonly table: string;
79
+ readonly to: string;
80
+ }): readonly Promise<Op>[];
73
81
  protected addColumn(options: {
74
82
  readonly table: string;
75
83
  readonly column: SqliteColumnSpec;
@@ -99,4 +107,4 @@ declare abstract class SqliteMigration<Start extends Contract<SqlStorage> = Cont
99
107
  }
100
108
  //#endregion
101
109
  export { SqliteMigration as t };
102
- //# sourceMappingURL=sqlite-migration-Du67NG7r-CqcA5XBz.d.mts.map
110
+ //# sourceMappingURL=sqlite-migration-2IEGvjRm-BQfd6NLr.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-migration-2IEGvjRm-BQfd6NLr.d.mts","names":[],"sources":["../../../../3-targets/3-targets/sqlite/dist/sqlite-migration-2IEGvjRm.d.mts"],"mappings":";;;;;;;;;;;;KAWK,KAAK,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;uBAuBb,gBAAgB,cAAc,SAAS,cAAc,SAAS,aAAa,YAAY,SAAS,cAAc,SAAS,qBAAqB,UAAU,mCAAmC,OAAO;;WAE5M;;;;;;;qBAOU,gBAAgB;EACnC,YAAY,QAAQ;UACZ;;;;;;UAMA;;;;;;MAMJ,eAAe,mBAAmB;;;;;MAKlC,iBAAiB,mBAAmB;YAC9B,YAAY;aACX;aACA;aACA,kBAAkB;aAClB,uBAAuB;MAC9B,QAAQ;YACF,UAAU;aACT;MACP,QAAQ;;;;YAIF,YAAY;aACX;aACA;eACE,QAAQ;YACX,UAAU;aACT;aACA,QAAQ;MACf,QAAQ;YACF,WAAW;aACV;aACA;MACP,QAAQ;YACF,YAAY;aACX;aACA;aACA;MACP,QAAQ;YACF,UAAU;aACT;aACA;MACP,QAAQ;YACF,cAAc;aACb;aACA,eAAe;aACf;aACA,kBAAkB;aAClB;aACA,qBAAqB;aACrB,gBAAgB;MACvB,QAAQ"}
@@ -1,19 +1,22 @@
1
- import { n as sqliteError } from "./errors-DnR-sMHS-KkMLIP2U.mjs";
1
+ import { n as sqliteError, t as errorSqliteMigrationStackMissing } from "./errors-DnR-sMHS-KkMLIP2U.mjs";
2
2
  import { n as sqliteResolveDefault } from "./default-normalizer-Bbo6WzxJ-MgaICRCQ.mjs";
3
- import { a as DropColumnCall, d as buildRecreatePostchecks, f as buildRecreateSummary, i as DataTransformCall, l as RecreateTableCall, m as sqliteDefaultToDdlColumnDefault, n as CreateIndexCall, o as DropIndexCall, p as renderDefaultLiteral, r as CreateTableCall, s as DropTableCall, t as AddColumnCall, u as buildColumnTypeSql } from "./op-factory-call-Dv_ma_mw-BtLqNmZI.mjs";
3
+ import { _ as sqliteIdentifiersCollide, a as DropColumnCall, d as buildColumnTypeSql, f as buildRecreatePostchecks, g as sqliteDefaultToDdlColumnDefault, h as renderDefaultLiteral, i as DataTransformCall, l as RecreateTableCall, n as CreateIndexCall, o as DropIndexCall, p as buildRecreateSummary, r as CreateTableCall, s as DropTableCall, t as AddColumnCall, u as RenameTableCall } from "./op-factory-call-DFDt6p_b-CN07t9pu.mjs";
4
4
  import { t as CONTROL_TABLE_NAMES } from "./control-tables-D_o8dKRB-BXi43noL.mjs";
5
- import { t as TypeScriptRenderableSqliteMigration } from "./planner-produced-sqlite-migration-D1iuFT1l-BSFCXgJD.mjs";
5
+ import { n as SqliteContractView } from "./sqlite-contract-view-BYR10usg-BteDAUZr.mjs";
6
6
  import { DdlColumn, ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint } from "@prisma/orm-family-sql/relational-core/ast";
7
7
  import { ifDefined } from "@prisma/orm-framework/utils/defined";
8
8
  import { blindCast } from "@prisma/orm-framework/utils/casts";
9
9
  import { diffSchemas, issueOutcome, orderIssuesByDependencies } from "@prisma/orm-framework/components/control";
10
- import { UNBOUND_NAMESPACE_ID, entityAt } from "@prisma/orm-framework/components/ir";
11
- import { RelationalSchemaNodeKind, SqlSchemaIR, SqlTableIR, contractDefaultRefusal, relationalNodeGranularity } from "@prisma/orm-family-sql/schema-ir/types";
10
+ import { entityAt } from "@prisma/orm-framework/components/ir";
11
+ import { RelationalSchemaNodeKind, SqlIndexIR, SqlSchemaIR, contractDefaultRefusal, relationalNodeGranularity } from "@prisma/orm-family-sql/schema-ir/types";
12
12
  import { InternalError } from "@prisma/orm-framework/utils/internal-error";
13
- import { buildDataTypeResolver, buildNativeTypeExpander, contractToSchemaIR, detectTableNameCaseChanges, extractCodecControlHooks, planFieldEventOperations, plannerFailure } from "@prisma/orm-family-sql/family/control";
13
+ import { applyTableRename, buildDataTypeResolver, buildNativeTypeExpander, contractToSchemaIR } from "@prisma/orm-family-sql/family/control";
14
14
  import { verifySqlSchemaByDiff } from "@prisma/orm-family-sql/family/diff";
15
+ import { parseWireName } from "@prisma/orm-family-sql/schema-ir/naming";
15
16
  import { notOk, ok } from "@prisma/orm-framework/utils/result";
16
- //#region ../../../3-targets/3-targets/sqlite/dist/planner-CWfPzOwZ.mjs
17
+ import { Migration } from "@prisma/orm-family-sql/family/migration";
18
+ import { MigrationContractViews } from "@prisma/orm-toolchain/migration-tools/migration";
19
+ //#region ../../../3-targets/3-targets/sqlite/dist/sqlite-migration-D1Zk_YEy.mjs
17
20
  /** Renders a column default for the SQLite dialect. */
18
21
  function sqliteRenderDefault(def, column) {
19
22
  if (def.kind === "function") {
@@ -672,174 +675,179 @@ function locationForCall(call) {
672
675
  if ("indexName" in call) location.index = call.indexName;
673
676
  return Object.keys(location).length > 0 ? location : void 0;
674
677
  }
675
- function createSqliteMigrationPlanner(lowerer) {
676
- return new SqliteMigrationPlanner(lowerer);
678
+ function indexFindings(issues, outcome) {
679
+ return issues.flatMap((issue) => {
680
+ const node = issueNode(issue);
681
+ const tableName = issue.path[1];
682
+ if (node === void 0 || !SqlIndexIR.is(node) || tableName === void 0) return [];
683
+ return issueOutcome(issue) === outcome ? [{
684
+ issue,
685
+ index: node,
686
+ tableName
687
+ }] : [];
688
+ });
689
+ }
690
+ /**
691
+ * An index on a renamed table whose wire name derives from the table name: the old and the new index share their content hash and differ in name.
692
+ */
693
+ function renamedTableIndex(renamedTables) {
694
+ return (old, replacement) => {
695
+ const oldWire = parseWireName(old.index.name);
696
+ const replacementWire = parseWireName(replacement.index.name);
697
+ return renamedTables.has(old.tableName) && old.tableName === replacement.tableName && oldWire !== void 0 && oldWire.hash === replacementWire?.hash && old.index.name !== replacement.index.name;
698
+ };
699
+ }
700
+ /**
701
+ * An index on the same table whose new name SQLite takes for the old one, as after a table renamed by hand. Its content is not compared: the old index must be dropped before the new one can be created whatever either defines, and the new one is created from its own definition.
702
+ */
703
+ const indexNameCaseChange = (old, replacement) => old.tableName === replacement.tableName && old.index.name !== replacement.index.name && sqliteIdentifiersCollide(old.index.name, replacement.index.name);
704
+ /**
705
+ * Pairs each index the plan drops with the index that replaces it, and plans every paired drop before every paired create. SQLite cannot rename an index, and it compares index names without regard to the case of ASCII letters, so a replacement whose name differs from the old one only in that case would otherwise collide with it. The paired issues are returned as consumed so the ordinary diff does not plan them again.
706
+ */
707
+ function pairIndexReplacements(issues, matches) {
708
+ const missing = indexFindings(issues, "not-found");
709
+ const pairs = indexFindings(issues, "not-expected").flatMap((old) => {
710
+ const replacement = missing.find((candidate) => matches(old, candidate));
711
+ if (replacement === void 0) return [];
712
+ missing.splice(missing.indexOf(replacement), 1);
713
+ return [{
714
+ old,
715
+ replacement
716
+ }];
717
+ });
718
+ return {
719
+ calls: [...pairs.map(({ old }) => new DropIndexCall(old.tableName, old.index.name)), ...pairs.map(({ replacement }) => new CreateIndexCall(replacement.tableName, replacement.index.name, replacement.index.columns ?? []))],
720
+ consumed: new Set(pairs.flatMap(({ old, replacement }) => [old.issue, replacement.issue]))
721
+ };
677
722
  }
678
723
  /**
679
- * SQLite migration planner — a thin wrapper over `planIssues`.
724
+ * The calls a migration's `renameTable` emits: the table rename, then a drop of each wire-named index whose prefix derives from the old table name and a create of it under the new name, since SQLite cannot rename an index. SQLite names no primary key, unique constraint or foreign key the contract leaves unnamed, so those need nothing. Throws `MIGRATION.TABLE_RENAME_UNMATCHED` when the start contract lacks the table or the end contract lacks the new name.
725
+ */
726
+ function sqliteTableRenameCalls(input) {
727
+ const applied = applyTableRename({
728
+ startContract: input.startContract,
729
+ endContract: input.endContract,
730
+ rename: input.rename,
731
+ renameTableReferences: void 0
732
+ });
733
+ if (!applied.ok) throw applied.failure;
734
+ const { rename } = applied.value;
735
+ const { issues } = buildSqlitePlanDiff({
736
+ contract: input.endContract,
737
+ actualSchema: sqliteContractToSchema(applied.value.contract),
738
+ frameworkComponents: input.frameworkComponents
739
+ });
740
+ return [new RenameTableCall(rename.from, rename.to), ...pairIndexReplacements(coalesceSubtreeIssues(issues), renamedTableIndex(/* @__PURE__ */ new Set([rename.to]))).calls];
741
+ }
742
+ /**
743
+ * Target-owned base class for SQLite migrations. Fixes the `SqlMigration`
744
+ * generic to `SqlitePlanTargetDetails` and the abstract `targetId` to the
745
+ * SQLite literal, so both user-authored migrations and renderer-generated
746
+ * scaffolds can extend `SqliteMigration` directly without redeclaring
747
+ * target-local identity.
680
748
  *
681
- * `plan()` diffs the live schema against the target contract via the one
682
- * differ (`buildSqlitePlanDiff`, producing node-typed `SchemaDiffIssue[]`)
683
- * and delegates to `planIssues` with the registered strategies. Strategies
684
- * absorb groups of related issues into composite recipes (e.g. recreating a
685
- * table to apply type/nullability/default/constraint changes at once);
686
- * anything not absorbed by a strategy flows through `mapNodeIssueToCall` in
687
- * the issue planner as a one-off call.
749
+ * The constructor materializes a single SQLite `SqlControlAdapter` from
750
+ * `stack.adapter.create(stack)` and stores it; the protected instance methods
751
+ * forward to the corresponding `*Call` with that stored adapter, so user
752
+ * migrations can write `this.createTable({...})` without threading the adapter
753
+ * through every call.
688
754
  *
689
- * FK-backing indexes are already merged into the expected table node's
690
- * `indexes` at derivation (`contractToSchemaIR`'s `convertTable`), so
691
- * `mapNodeIssueToCall` handles them uniformly alongside user-declared
692
- * indexes — no separate expansion step in the planner.
755
+ * Binds the framework base's `Start` / `End` contract generics so a subclass
756
+ * that assigns its snapshot-store `contract.json` imports to
757
+ * `startContractJson` / `endContractJson` gets fully-typed view accessors:
758
+ * `this.endContract` is a `SqliteContractView<End>`
759
+ * (sole namespace unwrapped to the root — `this.endContract.table.<name>`),
760
+ * built lazily from the JSON fields via the shared `MigrationContractViews`
761
+ * helper. Mirrors `MongoMigration`'s view getters; the framework base derives
762
+ * `describe()` from the same JSON.
693
763
  */
694
- var SqliteMigrationPlanner = class {
695
- #lowerer;
696
- constructor(lowerer) {
697
- this.#lowerer = lowerer;
698
- }
699
- plan(options) {
700
- return this.planSql(options);
701
- }
702
- emptyMigration(context, spaceId) {
703
- return new TypeScriptRenderableSqliteMigration([], {
704
- from: context.fromHash,
705
- to: context.toHash
706
- }, spaceId, context.snapshotsImportPath, void 0, this.#lowerer);
707
- }
708
- planSql(options) {
709
- const policyResult = this.ensureAdditivePolicy(options.policy);
710
- if (policyResult) return policyResult;
711
- const { expected, actual, issues } = this.collectSchemaIssues(options);
712
- const caseChangeConflicts = detectTableNameCaseChanges({
713
- issues,
714
- tableOf: (issue) => {
715
- const node = issueNode(issue);
716
- return node instanceof SqlTableIR ? node : void 0;
717
- },
718
- namespaceIdOf: () => UNBOUND_NAMESPACE_ID
719
- });
720
- if (caseChangeConflicts.length > 0) return plannerFailure(caseChangeConflicts);
721
- const codecHooks = extractCodecControlHooks(options.frameworkComponents);
722
- const result = planIssues({
723
- issues,
724
- expected,
725
- actual,
726
- policy: options.policy,
727
- frameworkComponents: options.frameworkComponents,
728
- strategies: sqlitePlannerStrategies
729
- });
730
- if (!result.ok) return plannerFailure(result.failure);
731
- const fieldEventOps = planFieldEventOperations({
732
- priorContract: options.fromContract,
733
- newContract: options.contract,
734
- codecHooks
735
- });
736
- const calls = [...result.value.calls, ...fieldEventOps];
737
- const destination = {
738
- storageHash: options.contract.storage.storageHash,
739
- ...options.contract.profileHash !== void 0 ? { profileHash: options.contract.profileHash } : {}
740
- };
741
- return {
742
- kind: "success",
743
- plan: new TypeScriptRenderableSqliteMigration(calls, {
744
- from: options.fromContract?.storage.storageHash ?? null,
745
- to: options.contract.storage.storageHash
746
- }, options.spaceId, options.snapshotsImportPath, destination, this.#lowerer)
747
- };
764
+ var SqliteMigration = class extends Migration {
765
+ targetId = "sqlite";
766
+ /**
767
+ * Materialized SQLite control adapter, created once per migration
768
+ * instance from the injected stack. `undefined` only when the migration
769
+ * was instantiated without a stack (test fixtures); `controlAdapterFor`
770
+ * throws a MIGRATION.SQLITE_CONTROL_STACK_MISSING in that case to surface the misuse.
771
+ */
772
+ controlAdapter;
773
+ #endView = new MigrationContractViews(this, "SqliteMigration", (json) => SqliteContractView.fromJson(json));
774
+ #startView = new MigrationContractViews(this, "SqliteMigration", (json) => SqliteContractView.fromJson(json));
775
+ constructor(stack) {
776
+ super(stack);
777
+ this.controlAdapter = stack?.adapter ? blindCast(stack.adapter.create(stack)) : void 0;
748
778
  }
749
- ensureAdditivePolicy(policy) {
750
- if (!policy.allowedOperationClasses.includes("additive")) return plannerFailure([{
751
- kind: "unsupportedOperation",
752
- summary: "Migration planner requires additive operations be allowed",
753
- why: "The planner requires the \"additive\" operation class to be allowed in the policy."
754
- }]);
755
- return null;
779
+ frameworkComponents() {
780
+ const stack = this.stack;
781
+ if (stack === void 0) return [];
782
+ return [
783
+ stack.target,
784
+ ...stack.adapter === void 0 ? [] : [stack.adapter],
785
+ ...stack.extensions
786
+ ];
756
787
  }
757
788
  /**
758
- * Diffs the target contract against the live schema via the one differ
759
- * (the same tree-building `diffSqliteSchema` uses, plus the
760
- * op-render stamper) and prepares the issue list `planIssues` consumes.
761
- *
762
- * Three passes, in order:
763
- * 1. Subtree coalescing — the differ is total (a missing/extra table also
764
- * emits an issue for every column/constraint under it); those nested
765
- * issues are redundant once the table-level `CreateTable`/`DropTable`
766
- * call already accounts for the whole subtree. Runs FIRST, over the
767
- * complete diff: a sibling-owned extra table's column issues must
768
- * collapse into its one table-level issue before the ownership pass,
769
- * because a bare column node carries no table reference — if coalescing
770
- * ran after ownership dropped the table-level issue, the orphaned column
771
- * issues would survive and the planner would emit drops against a
772
- * sibling space's table.
773
- * 2. Ownership — a live extra is only this plan's to drop when no contract
774
- * space owns it. The differ ran against THIS space's contract, so a
775
- * table a sibling owns surfaces here as `not-expected`; the planner asks
776
- * the ownership oracle (the passive aggregate) whether any space declares
777
- * it and, if so, leaves it alone. A table no space owns stays a genuine
778
- * extra. Ownership lives in the aggregate; the planner only asks. No
779
- * oracle (single-space) keeps every extra.
780
- * 3. Strict-mode extras gating — `not-expected` (extra table/column/
781
- * constraint) issues are dropped entirely outside strict mode, mirroring
782
- * the retired coordinate walk's `if (strict) { ...extra_* } }` guards:
783
- * an additive-only plan must never even consider dropping an unclaimed
784
- * object, not just refuse to emit the drop.
789
+ * Returns the materialized control adapter, or throws a MIGRATION.SQLITE_CONTROL_STACK_MISSING naming
790
+ * `operation` when the migration was constructed without a `ControlStack`.
791
+ * Single home for the null-check that every DDL/DML method shares.
785
792
  */
786
- collectSchemaIssues(options) {
787
- const allowed = options.policy.allowedOperationClasses;
788
- const strict = allowed.includes("widening") || allowed.includes("destructive");
789
- const { expected, actual, issues: rawIssues } = buildSqlitePlanDiff({
790
- contract: options.contract,
791
- actualSchema: options.schema,
792
- frameworkComponents: options.frameworkComponents
793
- });
794
- const owned = retainUnownedExtras(coalesceSubtreeIssues(rawIssues), options.ownership);
795
- return {
796
- expected,
797
- actual,
798
- issues: strict ? owned : owned.filter((issue) => issueOutcome(issue) !== "not-expected")
799
- };
793
+ controlAdapterFor(operation) {
794
+ if (!this.controlAdapter) throw errorSqliteMigrationStackMissing(operation);
795
+ return this.controlAdapter;
796
+ }
797
+ /**
798
+ * The typed SQLite view over this migration's end-state contract — sole
799
+ * namespace unwrapped to the root, so `this.endContract.table.<name>` etc.
800
+ * Throws if no `endContractJson` was provided.
801
+ */
802
+ get endContract() {
803
+ return this.#endView.endContract;
804
+ }
805
+ /**
806
+ * The typed SQLite view over this migration's start-state contract, or
807
+ * `null` for a baseline migration (no `startContractJson`).
808
+ */
809
+ get startContract() {
810
+ return this.#startView.startContract;
811
+ }
812
+ createTable(options) {
813
+ return new CreateTableCall(options.table, options.columns, options.constraints).toOp(this.controlAdapterFor("createTable"));
814
+ }
815
+ dropTable(options) {
816
+ return new DropTableCall(options.table).toOp(this.controlAdapterFor("dropTable"));
817
+ }
818
+ /**
819
+ * Emit the operations that rename a table: the table rename, then a drop and a create under the new name of each index whose name was derived from the old table name, read from this migration's start and end contracts. Spread the result into `operations`: `...this.renameTable({ table: 'userProfile', to: 'UserProfile' })`. Throws `MIGRATION.TABLE_RENAME_UNMATCHED` when the start contract lacks the table or the end contract lacks the new name.
820
+ */
821
+ renameTable(options) {
822
+ const adapter = this.controlAdapterFor("renameTable");
823
+ return sqliteTableRenameCalls({
824
+ startContract: this.startContract,
825
+ endContract: this.endContract,
826
+ rename: {
827
+ namespaceId: void 0,
828
+ from: options.table,
829
+ to: options.to
830
+ },
831
+ frameworkComponents: this.frameworkComponents()
832
+ }).map(async (call) => call.toOp(adapter));
833
+ }
834
+ addColumn(options) {
835
+ return new AddColumnCall(options.table, options.column).toOp(this.controlAdapterFor("addColumn"));
836
+ }
837
+ dropColumn(options) {
838
+ return new DropColumnCall(options.table, options.column).toOp(this.controlAdapterFor("dropColumn"));
839
+ }
840
+ createIndex(options) {
841
+ return new CreateIndexCall(options.table, options.index, options.columns).toOp(this.controlAdapterFor("createIndex"));
842
+ }
843
+ dropIndex(options) {
844
+ return new DropIndexCall(options.table, options.index).toOp(this.controlAdapterFor("dropIndex"));
845
+ }
846
+ recreateTable(options) {
847
+ return new RecreateTableCall(options).toOp(this.controlAdapterFor("recreateTable"));
800
848
  }
801
849
  };
802
- /**
803
- * Drops a `not-expected` issue when it is a whole extra TABLE that some
804
- * contract space owns, asking the ownership oracle per node.
805
- *
806
- * The consultation applies ONLY to table-level extras — a live table this
807
- * space's contract lacks — identified by asking the issue's own node
808
- * (`nodeKind === table`), never by counting path segments. SQLite is a
809
- * single-namespace target, so every coordinate is qualified with the shared
810
- * `UNBOUND_NAMESPACE_ID` sentinel (the same one the aggregate's declared
811
- * entities carry for this target). `entityKind` is the literal `'table'`:
812
- * this function only ever asks about a node already confirmed to be
813
- * `RelationalSchemaNodeKind.table` (checked just above), and that's a
814
- * diff-tree `nodeKind` spelling (`'sql-table'`) distinct from the storage
815
- * `entries` vocabulary `elementCoordinates` walks (`'table'`) — the literal
816
- * is that storage-entries spelling. `declaresEntity` answers over the whole
817
- * composition (self included), so a positive answer on such a table means
818
- * another space owns it (a table this space owned would be in its expected
819
- * tree, never an extra): leave it. A negative answer means no space owns
820
- * it — a genuine orphan to drop.
821
- *
822
- * A DEEPER extra (an extra column/constraint on a table this space DOES own —
823
- * only the child drifted, so the table is in the expected tree) is this
824
- * space's own drift and is always kept for dropping; asking the oracle there
825
- * would wrongly suppress it, because the owned table answers `true`. No oracle
826
- * ⇒ every extra is kept (single-space plan).
827
- */
828
- function retainUnownedExtras(issues, ownership) {
829
- if (ownership === void 0) return issues;
830
- return issues.filter((issue) => {
831
- if (issueOutcome(issue) !== "not-expected") return true;
832
- const node = issueNode(issue);
833
- if (node === void 0 || node.nodeKind !== RelationalSchemaNodeKind.table) return true;
834
- const tableName = issue.path[1];
835
- return tableName === void 0 || !ownership.declaresEntity({
836
- namespaceId: UNBOUND_NAMESPACE_ID,
837
- entityKind: "table",
838
- entityName: tableName
839
- });
840
- });
841
- }
842
850
  //#endregion
843
- export { verifySqliteDatabaseSchema as a, sqliteContractToSchema as i, createSqliteMigrationPlanner as n, diffSqliteSchema as r, SqliteMigrationPlanner as t };
851
+ export { diffSqliteSchema as a, pairIndexReplacements as c, sqlitePlannerStrategies as d, verifySqliteDatabaseSchema as f, conflictForDisallowedCall as i, planIssues as l, buildSqlitePlanDiff as n, indexNameCaseChange as o, coalesceSubtreeIssues as r, issueNode as s, SqliteMigration as t, sqliteContractToSchema as u };
844
852
 
845
- //# sourceMappingURL=planner-CWfPzOwZ-DVj6Tm5a.mjs.map
853
+ //# sourceMappingURL=sqlite-migration-D1Zk_YEy-BRKDlY8h.mjs.map