@prisma-next/target-sqlite 0.14.0-dev.6 → 0.14.0-dev.60

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 (72) hide show
  1. package/dist/contract-free.mjs +1 -1
  2. package/dist/control.d.mts +3 -4
  3. package/dist/control.d.mts.map +1 -1
  4. package/dist/control.mjs +16 -27
  5. package/dist/control.mjs.map +1 -1
  6. package/dist/{descriptor-meta-DxmEeTJ-.mjs → descriptor-meta-D1fap-5t.mjs} +4 -11
  7. package/dist/descriptor-meta-D1fap-5t.mjs.map +1 -0
  8. package/dist/descriptor-meta-runtime-BkXK3OjD.mjs +12 -0
  9. package/dist/descriptor-meta-runtime-BkXK3OjD.mjs.map +1 -0
  10. package/dist/migration.d.mts +2 -2
  11. package/dist/migration.mjs +2 -2
  12. package/dist/native-type-normalizer.mjs +13 -1
  13. package/dist/native-type-normalizer.mjs.map +1 -0
  14. package/dist/{op-factory-call-DmdfD1yd.mjs → op-factory-call-Do03QgD9.mjs} +134 -117
  15. package/dist/op-factory-call-Do03QgD9.mjs.map +1 -0
  16. package/dist/op-factory-call.d.mts +2 -2
  17. package/dist/op-factory-call.d.mts.map +1 -1
  18. package/dist/op-factory-call.mjs +1 -1
  19. package/dist/pack.mjs +1 -1
  20. package/dist/planner-DGhzXuGh.mjs +848 -0
  21. package/dist/planner-DGhzXuGh.mjs.map +1 -0
  22. package/dist/{planner-produced-sqlite-migration-0xPEm3R1.mjs → planner-produced-sqlite-migration-BDzhFAoW.mjs} +46 -17
  23. package/dist/planner-produced-sqlite-migration-BDzhFAoW.mjs.map +1 -0
  24. package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts → planner-produced-sqlite-migration-o1qUzwLk.d.mts} +3 -3
  25. package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts.map → planner-produced-sqlite-migration-o1qUzwLk.d.mts.map} +1 -1
  26. package/dist/planner-produced-sqlite-migration.d.mts +1 -1
  27. package/dist/planner-produced-sqlite-migration.mjs +1 -1
  28. package/dist/planner.d.mts +47 -11
  29. package/dist/planner.d.mts.map +1 -1
  30. package/dist/planner.mjs +1 -1
  31. package/dist/runtime.d.mts +6 -4
  32. package/dist/runtime.d.mts.map +1 -1
  33. package/dist/runtime.mjs +3 -3
  34. package/dist/{shared-Dhc8mLK1.d.mts → shared-C6sM-wel.d.mts} +2 -2
  35. package/dist/{shared-Dhc8mLK1.d.mts.map → shared-C6sM-wel.d.mts.map} +1 -1
  36. package/dist/{sqlite-contract-serializer--iaDgC8e.mjs → sqlite-contract-view-BEwi0mUC.mjs} +34 -9
  37. package/dist/sqlite-contract-view-BEwi0mUC.mjs.map +1 -0
  38. package/dist/sqlite-contract-view-J32K82Gi.d.mts +29 -0
  39. package/dist/sqlite-contract-view-J32K82Gi.d.mts.map +1 -0
  40. package/dist/sqlite-migration-BNiSiP0z.mjs +123 -0
  41. package/dist/sqlite-migration-BNiSiP0z.mjs.map +1 -0
  42. package/dist/{sqlite-migration-DVfhQwN_.d.mts → sqlite-migration-BYbzskpE.d.mts} +35 -6
  43. package/dist/sqlite-migration-BYbzskpE.d.mts.map +1 -0
  44. package/package.json +18 -18
  45. package/src/core/control-target.ts +13 -18
  46. package/src/core/errors.ts +14 -12
  47. package/src/core/migrations/column-ddl-rendering.ts +177 -0
  48. package/src/core/migrations/diff-database-schema.ts +230 -0
  49. package/src/core/migrations/issue-planner.ts +361 -488
  50. package/src/core/migrations/op-factory-call.ts +5 -0
  51. package/src/core/migrations/operations/tables.ts +107 -68
  52. package/src/core/migrations/planner-strategies.ts +118 -137
  53. package/src/core/migrations/planner.ts +117 -30
  54. package/src/core/migrations/render-typescript.ts +42 -15
  55. package/src/core/migrations/runner.ts +4 -10
  56. package/src/core/migrations/sqlite-migration.ts +69 -31
  57. package/src/core/sqlite-contract-serializer.ts +29 -14
  58. package/src/core/sqlite-contract-view.ts +41 -0
  59. package/src/core/sqlite-schema-verifier.ts +6 -3
  60. package/src/core/sqlite-unbound-database.ts +8 -8
  61. package/src/exports/runtime.ts +1 -0
  62. package/dist/descriptor-meta-DxmEeTJ-.mjs.map +0 -1
  63. package/dist/native-type-normalizer-CiSyVmMP.mjs +0 -14
  64. package/dist/native-type-normalizer-CiSyVmMP.mjs.map +0 -1
  65. package/dist/op-factory-call-DmdfD1yd.mjs.map +0 -1
  66. package/dist/planner-Ciq8p_dL.mjs +0 -622
  67. package/dist/planner-Ciq8p_dL.mjs.map +0 -1
  68. package/dist/planner-produced-sqlite-migration-0xPEm3R1.mjs.map +0 -1
  69. package/dist/sqlite-contract-serializer--iaDgC8e.mjs.map +0 -1
  70. package/dist/sqlite-migration-A0rwqPOG.mjs +0 -92
  71. package/dist/sqlite-migration-A0rwqPOG.mjs.map +0 -1
  72. package/dist/sqlite-migration-DVfhQwN_.d.mts.map +0 -1
@@ -0,0 +1,29 @@
1
+ import { SqlStorage } from "@prisma-next/sql-contract/types";
2
+ import { SqlSingleNamespaceView } from "@prisma-next/sql-contract/contract-view";
3
+ import { Contract } from "@prisma-next/contract/types";
4
+
5
+ //#region src/core/sqlite-contract-view.d.ts
6
+ /**
7
+ * A SQLite contract view: the deserialized contract intersected with by-name
8
+ * accessors. It is substitutable for `Contract` (carries `storage`, `domain`,
9
+ * …) and also exposes the single default namespace unwrapped with the SQL
10
+ * built-in kinds promoted:
11
+ *
12
+ * ```ts
13
+ * const view = SqliteContractView.fromJson<Contract>(contractJson);
14
+ * view.table.users // typed table leaf
15
+ * view.entries.policy.X // pack-contributed kind (singular key)
16
+ * view.storage // the full contract is still present
17
+ * ```
18
+ *
19
+ * SQLite has `sql.enums: false`, so it never emits `valueSet` entries; the
20
+ * `valueSet` slot is therefore an empty map.
21
+ */
22
+ type SqliteContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> = SqlSingleNamespaceView<TContract>;
23
+ declare const SqliteContractView: {
24
+ /** Wrap an already-deserialized SQLite contract in a view. */from<TContract extends Contract<SqlStorage>>(contract: TContract): SqliteContractView<TContract>; /** Deserialize a SQLite contract JSON envelope and wrap it in a view. */
25
+ fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage<string>>>(json: unknown): SqliteContractView<TContract>;
26
+ };
27
+ //#endregion
28
+ export { SqliteContractView as t };
29
+ //# sourceMappingURL=sqlite-contract-view-J32K82Gi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-contract-view-J32K82Gi.d.mts","names":[],"sources":["../src/core/sqlite-contract-view.ts"],"mappings":";;;;;;;AAwBA;;;;;;;;;;;;;;KAAY,kBAAA,mBAAqC,QAAA,CAAS,UAAA,IAAc,QAAA,CAAS,UAAA,KAC/E,sBAAA,CAAuB,SAAA;AAAA,cAEZ,kBAAA;EAFX,qFAIuB,QAAA,CAAS,UAAA,GAAW,QAAA,EAAY,SAAA,GAAY,kBAAA,CAAmB,SAAA,GAJtD;6BASL,QAAA,CAAS,UAAA,IAAW,QAAA,CAAA,UAAA,WAAA,IAAA,YAE5C,kBAAA,CAAmB,SAAA;AAAA"}
@@ -0,0 +1,123 @@
1
+ import { a as DropColumnCall, l as RecreateTableCall, n as CreateIndexCall, o as DropIndexCall, r as CreateTableCall, s as DropTableCall, t as AddColumnCall } from "./op-factory-call-Do03QgD9.mjs";
2
+ import { t as SqliteContractView } from "./sqlite-contract-view-BEwi0mUC.mjs";
3
+ import { blindCast } from "@prisma-next/utils/casts";
4
+ import { Migration } from "@prisma-next/family-sql/migration";
5
+ import { MigrationContractViews } from "@prisma-next/migration-tools/migration";
6
+ import { CliStructuredError } from "@prisma-next/errors/control";
7
+ //#region src/core/errors.ts
8
+ /**
9
+ * A `SqliteMigration` operation that needs the materialized control adapter
10
+ * — named by `operation` (e.g. `createTable`, `dropColumn`, `recreateTable`) —
11
+ * was invoked, but the migration was constructed without a `ControlStack`.
12
+ * Concrete authoring usage always goes through the migration CLI entrypoint,
13
+ * which assembles a stack from the loaded `prisma-next.config.ts`; reaching this
14
+ * error means a test fixture or ad-hoc consumer instantiated `SqliteMigration`
15
+ * with the no-arg form (legal for `operations` / `describe` introspection only).
16
+ *
17
+ * The `operation` argument is required so every throw site names the operation
18
+ * that actually failed; a new operation cannot inherit a misattributed message.
19
+ *
20
+ * Distinct from `PN-MIG-2001` (placeholder not filled) because the missing
21
+ * input is the stack itself, not the per-operation contract.
22
+ *
23
+ * Lives in `@prisma-next/target-sqlite/errors` rather than the shared
24
+ * framework migration errors module because the failure is target-specific:
25
+ * the contract it talks about (`SqliteMigration`, the SQLite control
26
+ * adapter, the SQLite-target stack) only exists in this package.
27
+ */
28
+ function errorSqliteMigrationStackMissing(operation) {
29
+ return new CliStructuredError("2008", `SqliteMigration.${operation} requires a control adapter`, {
30
+ domain: "MIG",
31
+ why: `SqliteMigration.${operation} was invoked on an instance constructed without a ControlStack, so the stored controlAdapter is undefined and the operation cannot lower its DDL node.`,
32
+ fix: "Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma-next.config.ts), or pass a ControlStack containing a SQLite adapter to the migration constructor in test fixtures.",
33
+ meta: { operation }
34
+ });
35
+ }
36
+ //#endregion
37
+ //#region src/core/migrations/sqlite-migration.ts
38
+ /**
39
+ * Target-owned base class for SQLite migrations. Fixes the `SqlMigration`
40
+ * generic to `SqlitePlanTargetDetails` and the abstract `targetId` to the
41
+ * SQLite literal, so both user-authored migrations and renderer-generated
42
+ * scaffolds can extend `SqliteMigration` directly without redeclaring
43
+ * target-local identity.
44
+ *
45
+ * The constructor materializes a single SQLite `SqlControlAdapter` from
46
+ * `stack.adapter.create(stack)` and stores it; the protected instance methods
47
+ * forward to the corresponding `*Call` with that stored adapter, so user
48
+ * migrations can write `this.createTable({...})` without threading the adapter
49
+ * through every call.
50
+ *
51
+ * Binds the framework base's `Start` / `End` contract generics so a subclass
52
+ * that assigns its `start-contract.json` / `end-contract.json` imports gets
53
+ * fully-typed view accessors: `this.endContract` is a `SqliteContractView<End>`
54
+ * (sole namespace unwrapped to the root — `this.endContract.table.<name>`),
55
+ * built lazily from the JSON fields via the shared `MigrationContractViews`
56
+ * helper. Mirrors `MongoMigration`'s view getters; the framework base derives
57
+ * `describe()` from the same JSON.
58
+ */
59
+ var SqliteMigration = class extends Migration {
60
+ targetId = "sqlite";
61
+ /**
62
+ * Materialized SQLite control adapter, created once per migration
63
+ * instance from the injected stack. `undefined` only when the migration
64
+ * was instantiated without a stack (test fixtures); `controlAdapterFor`
65
+ * throws a PN-MIG-2008 in that case to surface the misuse.
66
+ */
67
+ controlAdapter;
68
+ #endView = new MigrationContractViews(this, "SqliteMigration", (json) => SqliteContractView.fromJson(json));
69
+ #startView = new MigrationContractViews(this, "SqliteMigration", (json) => SqliteContractView.fromJson(json));
70
+ constructor(stack) {
71
+ super(stack);
72
+ this.controlAdapter = stack?.adapter ? blindCast(stack.adapter.create(stack)) : void 0;
73
+ }
74
+ /**
75
+ * Returns the materialized control adapter, or throws a PN-MIG-2008 naming
76
+ * `operation` when the migration was constructed without a `ControlStack`.
77
+ * Single home for the null-check that every DDL/DML method shares.
78
+ */
79
+ controlAdapterFor(operation) {
80
+ if (!this.controlAdapter) throw errorSqliteMigrationStackMissing(operation);
81
+ return this.controlAdapter;
82
+ }
83
+ /**
84
+ * The typed SQLite view over this migration's end-state contract — sole
85
+ * namespace unwrapped to the root, so `this.endContract.table.<name>` etc.
86
+ * Throws if no `endContractJson` was provided.
87
+ */
88
+ get endContract() {
89
+ return this.#endView.endContract;
90
+ }
91
+ /**
92
+ * The typed SQLite view over this migration's start-state contract, or
93
+ * `null` for a baseline migration (no `startContractJson`).
94
+ */
95
+ get startContract() {
96
+ return this.#startView.startContract;
97
+ }
98
+ createTable(options) {
99
+ return new CreateTableCall(options.table, options.columns, options.constraints).toOp(this.controlAdapterFor("createTable"));
100
+ }
101
+ dropTable(options) {
102
+ return new DropTableCall(options.table).toOp(this.controlAdapterFor("dropTable"));
103
+ }
104
+ addColumn(options) {
105
+ return new AddColumnCall(options.table, options.column).toOp(this.controlAdapterFor("addColumn"));
106
+ }
107
+ dropColumn(options) {
108
+ return new DropColumnCall(options.table, options.column).toOp(this.controlAdapterFor("dropColumn"));
109
+ }
110
+ createIndex(options) {
111
+ return new CreateIndexCall(options.table, options.index, options.columns).toOp(this.controlAdapterFor("createIndex"));
112
+ }
113
+ dropIndex(options) {
114
+ return new DropIndexCall(options.table, options.index).toOp(this.controlAdapterFor("dropIndex"));
115
+ }
116
+ recreateTable(options) {
117
+ return new RecreateTableCall(options).toOp(this.controlAdapterFor("recreateTable"));
118
+ }
119
+ };
120
+ //#endregion
121
+ export { SqliteMigration as t };
122
+
123
+ //# sourceMappingURL=sqlite-migration-BNiSiP0z.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-migration-BNiSiP0z.mjs","names":["SqlMigration","#endView","#startView"],"sources":["../src/core/errors.ts","../src/core/migrations/sqlite-migration.ts"],"sourcesContent":["import { CliStructuredError } from '@prisma-next/errors/control';\n\n/**\n * A `SqliteMigration` operation that needs the materialized control adapter\n * — named by `operation` (e.g. `createTable`, `dropColumn`, `recreateTable`) —\n * was invoked, but the migration was constructed without a `ControlStack`.\n * Concrete authoring usage always goes through the migration CLI entrypoint,\n * which assembles a stack from the loaded `prisma-next.config.ts`; reaching this\n * error means a test fixture or ad-hoc consumer instantiated `SqliteMigration`\n * with the no-arg form (legal for `operations` / `describe` introspection only).\n *\n * The `operation` argument is required so every throw site names the operation\n * that actually failed; a new operation cannot inherit a misattributed message.\n *\n * Distinct from `PN-MIG-2001` (placeholder not filled) because the missing\n * input is the stack itself, not the per-operation contract.\n *\n * Lives in `@prisma-next/target-sqlite/errors` rather than the shared\n * framework migration errors module because the failure is target-specific:\n * the contract it talks about (`SqliteMigration`, the SQLite control\n * adapter, the SQLite-target stack) only exists in this package.\n */\nexport function errorSqliteMigrationStackMissing(operation: string): CliStructuredError {\n return new CliStructuredError('2008', `SqliteMigration.${operation} requires a control adapter`, {\n domain: 'MIG',\n why: `SqliteMigration.${operation} was invoked on an instance constructed without a ControlStack, so the stored controlAdapter is undefined and the operation cannot lower its DDL node.`,\n fix: 'Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma-next.config.ts), or pass a ControlStack containing a SQLite adapter to the migration constructor in test fixtures.',\n meta: { operation },\n });\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationClass,\n SqlMigrationPlanOperation,\n} from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { Migration as SqlMigration } from '@prisma-next/family-sql/migration';\nimport type { ControlStack } from '@prisma-next/framework-components/control';\nimport { MigrationContractViews } from '@prisma-next/migration-tools/migration';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { errorSqliteMigrationStackMissing } from '../errors';\nimport { SqliteContractView } from '../sqlite-contract-view';\nimport {\n AddColumnCall,\n CreateIndexCall,\n CreateTableCall,\n DropColumnCall,\n DropIndexCall,\n DropTableCall,\n RecreateTableCall,\n} from './op-factory-call';\nimport type { SqliteColumnSpec, SqliteIndexSpec, SqliteTableSpec } from './operations/shared';\nimport type { SqlitePlanTargetDetails } from './planner-target-details';\n\ntype Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;\n\n/**\n * Target-owned base class for SQLite migrations. Fixes the `SqlMigration`\n * generic to `SqlitePlanTargetDetails` and the abstract `targetId` to the\n * SQLite literal, so both user-authored migrations and renderer-generated\n * scaffolds can extend `SqliteMigration` directly without redeclaring\n * target-local identity.\n *\n * The constructor materializes a single SQLite `SqlControlAdapter` from\n * `stack.adapter.create(stack)` and stores it; the protected instance methods\n * forward to the corresponding `*Call` with that stored adapter, so user\n * migrations can write `this.createTable({...})` without threading the adapter\n * through every call.\n *\n * Binds the framework base's `Start` / `End` contract generics so a subclass\n * that assigns its `start-contract.json` / `end-contract.json` imports gets\n * fully-typed view accessors: `this.endContract` is a `SqliteContractView<End>`\n * (sole namespace unwrapped to the root — `this.endContract.table.<name>`),\n * built lazily from the JSON fields via the shared `MigrationContractViews`\n * helper. Mirrors `MongoMigration`'s view getters; the framework base derives\n * `describe()` from the same JSON.\n */\nexport abstract class SqliteMigration<\n Start extends Contract<SqlStorage> = Contract<SqlStorage>,\n End extends Contract<SqlStorage> = Contract<SqlStorage>,\n> extends SqlMigration<SqlitePlanTargetDetails, 'sqlite', Start, End> {\n readonly targetId = 'sqlite' as const;\n\n /**\n * Materialized SQLite control adapter, created once per migration\n * instance from the injected stack. `undefined` only when the migration\n * was instantiated without a stack (test fixtures); `controlAdapterFor`\n * throws a PN-MIG-2008 in that case to surface the misuse.\n */\n protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;\n\n #endView = new MigrationContractViews<SqliteContractView<End>>(this, 'SqliteMigration', (json) =>\n SqliteContractView.fromJson<End>(json),\n );\n #startView = new MigrationContractViews<SqliteContractView<Start>>(\n this,\n 'SqliteMigration',\n (json) => SqliteContractView.fromJson<Start>(json),\n );\n\n constructor(stack?: ControlStack<'sql', 'sqlite'>) {\n super(stack);\n this.controlAdapter = stack?.adapter\n ? blindCast<\n SqlControlAdapter<'sqlite'>,\n 'The SQLite descriptor create() returns SqlControlAdapter<sqlite>; typed as wider ControlAdapterInstance at the framework boundary'\n >(stack.adapter.create(stack))\n : undefined;\n }\n\n /**\n * Returns the materialized control adapter, or throws a PN-MIG-2008 naming\n * `operation` when the migration was constructed without a `ControlStack`.\n * Single home for the null-check that every DDL/DML method shares.\n */\n private controlAdapterFor(operation: string): SqlControlAdapter<'sqlite'> {\n if (!this.controlAdapter) {\n throw errorSqliteMigrationStackMissing(operation);\n }\n return this.controlAdapter;\n }\n\n /**\n * The typed SQLite view over this migration's end-state contract — sole\n * namespace unwrapped to the root, so `this.endContract.table.<name>` etc.\n * Throws if no `endContractJson` was provided.\n */\n get endContract(): SqliteContractView<End> {\n return this.#endView.endContract;\n }\n\n /**\n * The typed SQLite view over this migration's start-state contract, or\n * `null` for a baseline migration (no `startContractJson`).\n */\n get startContract(): SqliteContractView<Start> | null {\n return this.#startView.startContract;\n }\n\n protected createTable(options: {\n readonly table: string;\n readonly ifNotExists?: boolean;\n readonly columns: readonly DdlColumn[];\n readonly constraints?: readonly DdlTableConstraint[];\n }): Promise<Op> {\n return new CreateTableCall(options.table, options.columns, options.constraints).toOp(\n this.controlAdapterFor('createTable'),\n );\n }\n\n protected dropTable(options: { readonly table: string }): Promise<Op> {\n return new DropTableCall(options.table).toOp(this.controlAdapterFor('dropTable'));\n }\n\n protected addColumn(options: {\n readonly table: string;\n readonly column: SqliteColumnSpec;\n }): Promise<Op> {\n return new AddColumnCall(options.table, options.column).toOp(\n this.controlAdapterFor('addColumn'),\n );\n }\n\n protected dropColumn(options: { readonly table: string; readonly column: string }): Promise<Op> {\n return new DropColumnCall(options.table, options.column).toOp(\n this.controlAdapterFor('dropColumn'),\n );\n }\n\n protected createIndex(options: {\n readonly table: string;\n readonly index: string;\n readonly columns: readonly string[];\n }): Promise<Op> {\n return new CreateIndexCall(options.table, options.index, options.columns).toOp(\n this.controlAdapterFor('createIndex'),\n );\n }\n\n protected dropIndex(options: { readonly table: string; readonly index: string }): Promise<Op> {\n return new DropIndexCall(options.table, options.index).toOp(\n this.controlAdapterFor('dropIndex'),\n );\n }\n\n protected recreateTable(options: {\n readonly tableName: string;\n readonly contractTable: SqliteTableSpec;\n readonly schemaColumnNames: readonly string[];\n readonly indexes: readonly SqliteIndexSpec[];\n readonly summary: string;\n readonly postchecks: readonly { readonly description: string; readonly sql: string }[];\n readonly operationClass: MigrationOperationClass;\n }): Promise<Op> {\n return new RecreateTableCall(options).toOp(this.controlAdapterFor('recreateTable'));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iCAAiC,WAAuC;CACtF,OAAO,IAAI,mBAAmB,QAAQ,mBAAmB,UAAU,8BAA8B;EAC/F,QAAQ;EACR,KAAK,mBAAmB,UAAU;EAClC,KAAK;EACL,MAAM,EAAE,UAAU;CACpB,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;ACoBA,IAAsB,kBAAtB,cAGUA,UAA4D;CACpE,WAAoB;;;;;;;CAQpB;CAEA,WAAW,IAAI,uBAAgD,MAAM,oBAAoB,SACvF,mBAAmB,SAAc,IAAI,CACvC;CACA,aAAa,IAAI,uBACf,MACA,oBACC,SAAS,mBAAmB,SAAgB,IAAI,CACnD;CAEA,YAAY,OAAuC;EACjD,MAAM,KAAK;EACX,KAAK,iBAAiB,OAAO,UACzB,UAGE,MAAM,QAAQ,OAAO,KAAK,CAAC,IAC7B,KAAA;CACN;;;;;;CAOA,kBAA0B,WAAgD;EACxE,IAAI,CAAC,KAAK,gBACR,MAAM,iCAAiC,SAAS;EAElD,OAAO,KAAK;CACd;;;;;;CAOA,IAAI,cAAuC;EACzC,OAAO,KAAKC,SAAS;CACvB;;;;;CAMA,IAAI,gBAAkD;EACpD,OAAO,KAAKC,WAAW;CACzB;CAEA,YAAsB,SAKN;EACd,OAAO,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,SAAS,QAAQ,WAAW,CAAC,CAAC,KAC9E,KAAK,kBAAkB,aAAa,CACtC;CACF;CAEA,UAAoB,SAAkD;EACpE,OAAO,IAAI,cAAc,QAAQ,KAAK,CAAC,CAAC,KAAK,KAAK,kBAAkB,WAAW,CAAC;CAClF;CAEA,UAAoB,SAGJ;EACd,OAAO,IAAI,cAAc,QAAQ,OAAO,QAAQ,MAAM,CAAC,CAAC,KACtD,KAAK,kBAAkB,WAAW,CACpC;CACF;CAEA,WAAqB,SAA2E;EAC9F,OAAO,IAAI,eAAe,QAAQ,OAAO,QAAQ,MAAM,CAAC,CAAC,KACvD,KAAK,kBAAkB,YAAY,CACrC;CACF;CAEA,YAAsB,SAIN;EACd,OAAO,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,OAAO,QAAQ,OAAO,CAAC,CAAC,KACxE,KAAK,kBAAkB,aAAa,CACtC;CACF;CAEA,UAAoB,SAA0E;EAC5F,OAAO,IAAI,cAAc,QAAQ,OAAO,QAAQ,KAAK,CAAC,CAAC,KACrD,KAAK,kBAAkB,WAAW,CACpC;CACF;CAEA,cAAwB,SAQR;EACd,OAAO,IAAI,kBAAkB,OAAO,CAAC,CAAC,KAAK,KAAK,kBAAkB,eAAe,CAAC;CACpF;AACF"}
@@ -1,9 +1,12 @@
1
1
  import { t as SqlitePlanTargetDetails } from "./planner-target-details-xR6UfIcz.mjs";
2
- import { i as SqliteTableSpec, n as SqliteColumnSpec, r as SqliteIndexSpec } from "./shared-Dhc8mLK1.mjs";
2
+ import { i as SqliteTableSpec, n as SqliteColumnSpec, r as SqliteIndexSpec } from "./shared-C6sM-wel.mjs";
3
+ import { t as SqliteContractView } from "./sqlite-contract-view-J32K82Gi.mjs";
3
4
  import { DdlColumn, DdlTableConstraint } from "@prisma-next/sql-relational-core/ast";
5
+ import { SqlStorage } from "@prisma-next/sql-contract/types";
4
6
  import { MigrationOperationClass, SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
5
- import { Migration } from "@prisma-next/family-sql/migration";
6
7
  import { ControlStack } from "@prisma-next/framework-components/control";
8
+ import { Migration } from "@prisma-next/family-sql/migration";
9
+ import { Contract } from "@prisma-next/contract/types";
7
10
  import { SqlControlAdapter } from "@prisma-next/family-sql/control-adapter";
8
11
 
9
12
  //#region src/core/migrations/sqlite-migration.d.ts
@@ -20,17 +23,43 @@ type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
20
23
  * forward to the corresponding `*Call` with that stored adapter, so user
21
24
  * migrations can write `this.createTable({...})` without threading the adapter
22
25
  * through every call.
26
+ *
27
+ * Binds the framework base's `Start` / `End` contract generics so a subclass
28
+ * that assigns its `start-contract.json` / `end-contract.json` imports gets
29
+ * fully-typed view accessors: `this.endContract` is a `SqliteContractView<End>`
30
+ * (sole namespace unwrapped to the root — `this.endContract.table.<name>`),
31
+ * built lazily from the JSON fields via the shared `MigrationContractViews`
32
+ * helper. Mirrors `MongoMigration`'s view getters; the framework base derives
33
+ * `describe()` from the same JSON.
23
34
  */
24
- declare abstract class SqliteMigration extends Migration<SqlitePlanTargetDetails, 'sqlite'> {
35
+ declare abstract class SqliteMigration<Start extends Contract<SqlStorage> = Contract<SqlStorage>, End extends Contract<SqlStorage> = Contract<SqlStorage>> extends Migration<SqlitePlanTargetDetails, 'sqlite', Start, End> {
36
+ #private;
25
37
  readonly targetId: "sqlite";
26
38
  /**
27
39
  * Materialized SQLite control adapter, created once per migration
28
40
  * instance from the injected stack. `undefined` only when the migration
29
- * was instantiated without a stack (test fixtures); the operation methods
30
- * throw in that case to surface the misuse.
41
+ * was instantiated without a stack (test fixtures); `controlAdapterFor`
42
+ * throws a PN-MIG-2008 in that case to surface the misuse.
31
43
  */
32
44
  protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;
33
45
  constructor(stack?: ControlStack<'sql', 'sqlite'>);
46
+ /**
47
+ * Returns the materialized control adapter, or throws a PN-MIG-2008 naming
48
+ * `operation` when the migration was constructed without a `ControlStack`.
49
+ * Single home for the null-check that every DDL/DML method shares.
50
+ */
51
+ private controlAdapterFor;
52
+ /**
53
+ * The typed SQLite view over this migration's end-state contract — sole
54
+ * namespace unwrapped to the root, so `this.endContract.table.<name>` etc.
55
+ * Throws if no `endContractJson` was provided.
56
+ */
57
+ get endContract(): SqliteContractView<End>;
58
+ /**
59
+ * The typed SQLite view over this migration's start-state contract, or
60
+ * `null` for a baseline migration (no `startContractJson`).
61
+ */
62
+ get startContract(): SqliteContractView<Start> | null;
34
63
  protected createTable(options: {
35
64
  readonly table: string;
36
65
  readonly ifNotExists?: boolean;
@@ -72,4 +101,4 @@ declare abstract class SqliteMigration extends Migration<SqlitePlanTargetDetails
72
101
  }
73
102
  //#endregion
74
103
  export { SqliteMigration as t };
75
- //# sourceMappingURL=sqlite-migration-DVfhQwN_.d.mts.map
104
+ //# sourceMappingURL=sqlite-migration-BYbzskpE.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-migration-BYbzskpE.d.mts","names":[],"sources":["../src/core/migrations/sqlite-migration.ts"],"mappings":";;;;;;;;;;;;KA0BK,EAAA,GAAK,yBAAyB,CAAC,uBAAA;;AAFoC;;;;AAEb;AAuB3D;;;;;;;;;;;;;;;uBAAsB,eAAA,eACN,QAAA,CAAS,UAAA,IAAc,QAAA,CAAS,UAAA,eAClC,QAAA,CAAS,UAAA,IAAc,QAAA,CAAS,UAAA,WACpC,SAAA,CAAa,uBAAA,YAAmC,KAAA,EAAO,GAAA;EAAA;WACtD,QAAA;EAsD+B;;;;;;EAAA,mBA9CrB,cAAA,EAAgB,iBAAA;cAWvB,KAAA,GAAQ,YAAA;EAwDD;;;;;EAAA,QAzCX,iBAAA;EA0DJ;;;;;EAAA,IA9CA,WAAA,IAAe,kBAAA,CAAmB,GAAA;EAkE1B;;;;EAAA,IA1DR,aAAA,IAAiB,kBAAA,CAAmB,KAAA;EAAA,UAI9B,WAAA,CAAY,OAAA;IAAA,SACX,KAAA;IAAA,SACA,WAAA;IAAA,SACA,OAAA,WAAkB,SAAA;IAAA,SAClB,WAAA,YAAuB,kBAAA;EAAA,IAC9B,OAAA,CAAQ,EAAA;EAAA,UAMF,SAAA,CAAU,OAAA;IAAA,SAAoB,KAAA;EAAA,IAAkB,OAAA,CAAQ,EAAA;EAAA,UAIxD,SAAA,CAAU,OAAA;IAAA,SACT,KAAA;IAAA,SACA,MAAA,EAAQ,gBAAA;EAAA,IACf,OAAA,CAAQ,EAAA;EAAA,UAMF,UAAA,CAAW,OAAA;IAAA,SAAoB,KAAA;IAAA,SAAwB,MAAA;EAAA,IAAmB,OAAA,CAAQ,EAAA;EAAA,UAMlF,WAAA,CAAY,OAAA;IAAA,SACX,KAAA;IAAA,SACA,KAAA;IAAA,SACA,OAAA;EAAA,IACP,OAAA,CAAQ,EAAA;EAAA,UAMF,SAAA,CAAU,OAAA;IAAA,SAAoB,KAAA;IAAA,SAAwB,KAAA;EAAA,IAAkB,OAAA,CAAQ,EAAA;EAAA,UAMhF,aAAA,CAAc,OAAA;IAAA,SACb,SAAA;IAAA,SACA,aAAA,EAAe,eAAA;IAAA,SACf,iBAAA;IAAA,SACA,OAAA,WAAkB,eAAA;IAAA,SAClB,OAAA;IAAA,SACA,UAAA;MAAA,SAAgC,WAAA;MAAA,SAA8B,GAAA;IAAA;IAAA,SAC9D,cAAA,EAAgB,uBAAA;EAAA,IACvB,OAAA,CAAQ,EAAA;AAAA"}
package/package.json CHANGED
@@ -1,30 +1,30 @@
1
1
  {
2
2
  "name": "@prisma-next/target-sqlite",
3
- "version": "0.14.0-dev.6",
3
+ "version": "0.14.0-dev.60",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "dependencies": {
8
- "@prisma-next/cli": "0.14.0-dev.6",
9
- "@prisma-next/contract": "0.14.0-dev.6",
10
- "@prisma-next/errors": "0.14.0-dev.6",
11
- "@prisma-next/family-sql": "0.14.0-dev.6",
12
- "@prisma-next/framework-components": "0.14.0-dev.6",
13
- "@prisma-next/migration-tools": "0.14.0-dev.6",
14
- "@prisma-next/sql-contract": "0.14.0-dev.6",
15
- "@prisma-next/sql-errors": "0.14.0-dev.6",
16
- "@prisma-next/sql-relational-core": "0.14.0-dev.6",
17
- "@prisma-next/sql-runtime": "0.14.0-dev.6",
18
- "@prisma-next/sql-schema-ir": "0.14.0-dev.6",
19
- "@prisma-next/ts-render": "0.14.0-dev.6",
20
- "@prisma-next/utils": "0.14.0-dev.6",
8
+ "@prisma-next/cli": "0.14.0-dev.60",
9
+ "@prisma-next/contract": "0.14.0-dev.60",
10
+ "@prisma-next/errors": "0.14.0-dev.60",
11
+ "@prisma-next/family-sql": "0.14.0-dev.60",
12
+ "@prisma-next/framework-components": "0.14.0-dev.60",
13
+ "@prisma-next/migration-tools": "0.14.0-dev.60",
14
+ "@prisma-next/sql-contract": "0.14.0-dev.60",
15
+ "@prisma-next/sql-errors": "0.14.0-dev.60",
16
+ "@prisma-next/sql-relational-core": "0.14.0-dev.60",
17
+ "@prisma-next/sql-runtime": "0.14.0-dev.60",
18
+ "@prisma-next/sql-schema-ir": "0.14.0-dev.60",
19
+ "@prisma-next/ts-render": "0.14.0-dev.60",
20
+ "@prisma-next/utils": "0.14.0-dev.60",
21
21
  "@standard-schema/spec": "1.1.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@prisma-next/driver-sqlite": "0.14.0-dev.6",
25
- "@prisma-next/test-utils": "0.14.0-dev.6",
26
- "@prisma-next/tsconfig": "0.14.0-dev.6",
27
- "@prisma-next/tsdown": "0.14.0-dev.6",
24
+ "@prisma-next/driver-sqlite": "0.14.0-dev.60",
25
+ "@prisma-next/test-utils": "0.14.0-dev.60",
26
+ "@prisma-next/tsconfig": "0.14.0-dev.60",
27
+ "@prisma-next/tsdown": "0.14.0-dev.60",
28
28
  "tsdown": "0.22.1",
29
29
  "typescript": "5.9.3",
30
30
  "vitest": "4.1.8"
@@ -1,16 +1,19 @@
1
- import type { ColumnDefault, Contract } from '@prisma-next/contract/types';
1
+ import type { Contract } from '@prisma-next/contract/types';
2
2
  import type { SqlControlTargetDescriptor } from '@prisma-next/family-sql/control';
3
- import { contractToSchemaIR } from '@prisma-next/family-sql/control';
4
3
  import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
5
4
  import type {
6
5
  ControlTargetInstance,
7
6
  MigrationPlanner,
8
7
  MigrationRunner,
9
8
  } from '@prisma-next/framework-components/control';
10
- import { SqlStorage, type StorageColumn } from '@prisma-next/sql-contract/types';
9
+ import { SqlStorage } from '@prisma-next/sql-contract/types';
10
+ import {
11
+ relationalNodeEntityKind,
12
+ relationalNodeGranularity,
13
+ } from '@prisma-next/sql-schema-ir/types';
11
14
  import { sqliteTargetDescriptorMeta } from './descriptor-meta';
15
+ import { diffSqliteSchema, sqliteContractToSchema } from './migrations/diff-database-schema';
12
16
  import { createSqliteMigrationPlanner } from './migrations/planner';
13
- import { renderDefaultLiteral } from './migrations/planner-ddl-builders';
14
17
  import type { SqlitePlanTargetDetails } from './migrations/planner-target-details';
15
18
  import { createSqliteMigrationRunner } from './migrations/runner';
16
19
  import { SqliteContractSerializer } from './sqlite-contract-serializer';
@@ -20,21 +23,16 @@ function isSqlContract(contract: Contract | null): contract is Contract<SqlStora
20
23
  return contract === null || contract.storage instanceof SqlStorage;
21
24
  }
22
25
 
23
- function sqliteRenderDefault(def: ColumnDefault, _column: StorageColumn): string {
24
- if (def.kind === 'function') {
25
- if (def.expression === 'now()') {
26
- return "datetime('now')";
27
- }
28
- return def.expression;
29
- }
30
- return renderDefaultLiteral(def.value);
31
- }
32
-
33
26
  const sqliteControlTargetDescriptor: SqlControlTargetDescriptor<'sqlite', SqlitePlanTargetDetails> =
34
27
  {
35
28
  ...sqliteTargetDescriptorMeta,
36
29
  contractSerializer: new SqliteContractSerializer(),
37
30
  schemaVerifier: new SqliteSchemaVerifier(),
31
+ diffSchema(input) {
32
+ return diffSqliteSchema(input);
33
+ },
34
+ classifySubjectGranularity: relationalNodeGranularity,
35
+ classifyEntityKind: relationalNodeEntityKind,
38
36
  migrations: {
39
37
  createPlanner(adapter: SqlControlAdapter<'sqlite'>): MigrationPlanner<'sql', 'sqlite'> {
40
38
  return createSqliteMigrationPlanner(adapter);
@@ -55,10 +53,7 @@ const sqliteControlTargetDescriptor: SqlControlTargetDescriptor<'sqlite', Sqlite
55
53
  'sqliteControlTargetDescriptor.contractToSchema received a non-SQL contract; expected Contract<SqlStorage>',
56
54
  );
57
55
  }
58
- return contractToSchemaIR(contract, {
59
- annotationNamespace: 'sqlite',
60
- renderDefault: sqliteRenderDefault,
61
- });
56
+ return sqliteContractToSchema(contract);
62
57
  },
63
58
  },
64
59
  create(): ControlTargetInstance<'sql', 'sqlite'> {
@@ -1,14 +1,16 @@
1
1
  import { CliStructuredError } from '@prisma-next/errors/control';
2
2
 
3
3
  /**
4
- * A `SqliteMigration` instance method that needs the materialized control
5
- * adapter (currently only `this.createTable(...)`) was invoked, but the
6
- * migration was constructed without a `ControlStack`. Concrete authoring
7
- * usage always goes through the migration CLI entrypoint, which assembles
8
- * a stack from the loaded `prisma-next.config.ts`; reaching this error
9
- * means a test fixture or ad-hoc consumer instantiated `SqliteMigration`
10
- * with the no-arg form (legal for `operations` / `describe` introspection
11
- * only).
4
+ * A `SqliteMigration` operation that needs the materialized control adapter
5
+ * named by `operation` (e.g. `createTable`, `dropColumn`, `recreateTable`)
6
+ * was invoked, but the migration was constructed without a `ControlStack`.
7
+ * Concrete authoring usage always goes through the migration CLI entrypoint,
8
+ * which assembles a stack from the loaded `prisma-next.config.ts`; reaching this
9
+ * error means a test fixture or ad-hoc consumer instantiated `SqliteMigration`
10
+ * with the no-arg form (legal for `operations` / `describe` introspection only).
11
+ *
12
+ * The `operation` argument is required so every throw site names the operation
13
+ * that actually failed; a new operation cannot inherit a misattributed message.
12
14
  *
13
15
  * Distinct from `PN-MIG-2001` (placeholder not filled) because the missing
14
16
  * input is the stack itself, not the per-operation contract.
@@ -18,11 +20,11 @@ import { CliStructuredError } from '@prisma-next/errors/control';
18
20
  * the contract it talks about (`SqliteMigration`, the SQLite control
19
21
  * adapter, the SQLite-target stack) only exists in this package.
20
22
  */
21
- export function errorSqliteMigrationStackMissing(): CliStructuredError {
22
- return new CliStructuredError('2008', 'SqliteMigration.createTable requires a control adapter', {
23
+ export function errorSqliteMigrationStackMissing(operation: string): CliStructuredError {
24
+ return new CliStructuredError('2008', `SqliteMigration.${operation} requires a control adapter`, {
23
25
  domain: 'MIG',
24
- why: 'SqliteMigration.createTable was invoked on an instance constructed without a ControlStack. The stored controlAdapter is undefined, so createTable cannot lower its DDL node.',
26
+ why: `SqliteMigration.${operation} was invoked on an instance constructed without a ControlStack, so the stored controlAdapter is undefined and the operation cannot lower its DDL node.`,
25
27
  fix: 'Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma-next.config.ts), or pass a ControlStack containing a SQLite adapter to the migration constructor in test fixtures.',
26
- meta: {},
28
+ meta: { operation },
27
29
  });
28
30
  }
@@ -0,0 +1,177 @@
1
+ import type { StorageColumn } from '@prisma-next/sql-contract/types';
2
+ import {
3
+ DdlColumn,
4
+ type DdlTableConstraint,
5
+ ForeignKeyConstraint,
6
+ FunctionColumnDefault,
7
+ LiteralColumnDefault,
8
+ PrimaryKeyConstraint,
9
+ UniqueConstraint,
10
+ } from '@prisma-next/sql-relational-core/ast';
11
+ import type { SqlColumnIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';
12
+ import { blindCast } from '@prisma-next/utils/casts';
13
+ import type { SqliteColumnSpec } from './operations/shared';
14
+ import { buildColumnDefaultSql, buildColumnTypeSql } from './planner-ddl-builders';
15
+
16
+ /**
17
+ * Reconstructs the `StorageColumn`-shaped fields `buildColumnTypeSql` /
18
+ * `buildColumnDefaultSql` expect, from a column node's own stamped codec
19
+ * identity (`codecRef` / `codecBaseNativeType`, Decision 5) — never the
20
+ * contract. SQLite's type renderer only uppercases the resolved base type
21
+ * (no parameterized expansion, no named-type quoting), so `typeRef` is
22
+ * deliberately left unset here: setting it would send `buildColumnTypeSql`
23
+ * back through a live `storageTypes` lookup the node's fields have already
24
+ * resolved past, which throws for an unrecognized reference (unlike
25
+ * Postgres's lenient fallback).
26
+ */
27
+ function columnLike(
28
+ column: SqlColumnIR,
29
+ ): Pick<StorageColumn, 'nativeType' | 'codecId' | 'nullable' | 'many' | 'typeParams' | 'default'> {
30
+ if (column.codecRef === undefined || column.codecBaseNativeType === undefined) {
31
+ throw new Error(
32
+ `columnLike: expected column "${column.name}" carries no codec identity — the expected tree must be derived via contractToSchemaIR for planning`,
33
+ );
34
+ }
35
+ return {
36
+ nativeType: column.codecBaseNativeType,
37
+ codecId: column.codecRef.codecId,
38
+ nullable: column.nullable,
39
+ // `column.many` is unset on contract-derived columns (array-ness rides
40
+ // on the `nativeType` `[]` suffix there instead) — `codecRef.many`
41
+ // carries it. Hand-built/introspected columns set `column.many` directly.
42
+ ...((column.many ?? column.codecRef.many) !== undefined
43
+ ? { many: column.many ?? column.codecRef.many }
44
+ : {}),
45
+ ...(column.codecRef.typeParams !== undefined
46
+ ? {
47
+ typeParams: blindCast<
48
+ Record<string, unknown>,
49
+ 'CodecRef.typeParams is JsonValue-shaped; the DDL builders only ever read it as the Record the contract column originally carried'
50
+ >(column.codecRef.typeParams),
51
+ }
52
+ : {}),
53
+ ...(column.resolvedDefault !== undefined ? { default: column.resolvedDefault } : {}),
54
+ };
55
+ }
56
+
57
+ function sqliteDefaultToDdlColumnDefault(
58
+ columnDefault: StorageColumn['default'],
59
+ ): DdlColumn['default'] {
60
+ if (!columnDefault) return undefined;
61
+ switch (columnDefault.kind) {
62
+ case 'literal':
63
+ return new LiteralColumnDefault(columnDefault.value);
64
+ case 'function':
65
+ // `autoincrement()` is not a DEFAULT clause — SQLite encodes it as
66
+ // `INTEGER PRIMARY KEY AUTOINCREMENT` inline on the column. Skip it
67
+ // here; the renderer also has a defensive guard for the same case.
68
+ if (columnDefault.expression === 'autoincrement()') return undefined;
69
+ return new FunctionColumnDefault(columnDefault.expression);
70
+ default: {
71
+ const exhaustive: never = columnDefault;
72
+ throw new Error(
73
+ `sqliteDefaultToDdlColumnDefault: unhandled kind "${blindCast<{ kind: string }, 'exhaustiveness: surface the unhandled default kind'>(exhaustive).kind}"`,
74
+ );
75
+ }
76
+ }
77
+ }
78
+
79
+ /**
80
+ * True when the column is rendered inline as `INTEGER PRIMARY KEY
81
+ * AUTOINCREMENT` — the sole member of the table's primary key with an
82
+ * `autoincrement()` default. Node-based sibling of the retired
83
+ * `isInlineAutoincrementPrimaryKey` (which read the raw `StorageTable`);
84
+ * reads the table/column nodes instead.
85
+ */
86
+ export function isInlineAutoincrementPrimaryKeyNode(
87
+ table: SqlTableIR,
88
+ column: SqlColumnIR,
89
+ ): boolean {
90
+ if (table.primaryKey?.columns.length !== 1) return false;
91
+ if (table.primaryKey.columns[0] !== column.name) return false;
92
+ return (
93
+ column.resolvedDefault?.kind === 'function' &&
94
+ column.resolvedDefault.expression === 'autoincrement()'
95
+ );
96
+ }
97
+
98
+ /**
99
+ * Builds the flat `SqliteColumnSpec` `AddColumnCall` / `RecreateTableCall`
100
+ * need, resolved from the column node's codec identity — the same builders
101
+ * the pre-`plan(start, end)` op-path called, so the output is
102
+ * byte-identical.
103
+ */
104
+ export function columnSpecFromNode(column: SqlColumnIR, inline: boolean): SqliteColumnSpec {
105
+ const like = columnLike(column);
106
+ const typeSql = buildColumnTypeSql(like, {});
107
+ const defaultSql = buildColumnDefaultSql(like.default);
108
+ return {
109
+ name: column.name,
110
+ typeSql,
111
+ defaultSql,
112
+ nullable: column.nullable,
113
+ ...(inline ? { inlineAutoincrementPrimaryKey: true } : {}),
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Builds the `DdlColumn` the `CreateTableCall` path needs, resolved from the
119
+ * column node's codec identity.
120
+ */
121
+ export function ddlColumnFromNode(column: SqlColumnIR, inline: boolean): DdlColumn {
122
+ const like = columnLike(column);
123
+ const typeSql = buildColumnTypeSql(like, {});
124
+ if (inline) {
125
+ // `DdlColumn` has no SQLite-specific autoincrement flag, so the full
126
+ // `PRIMARY KEY AUTOINCREMENT` clause is embedded in the `type` string.
127
+ // The DDL renderer (`ddl-renderer.ts`) substring-detects `AUTOINCREMENT`
128
+ // to suppress the normal NOT NULL / PRIMARY KEY / DEFAULT clause rendering
129
+ // and emit the entire type string verbatim. Both sites must stay in sync.
130
+ // The structural fix (a SQLite-specific column option) is tracked in TML-2866.
131
+ return new DdlColumn({ name: column.name, type: `${typeSql} PRIMARY KEY AUTOINCREMENT` });
132
+ }
133
+ const colDefault = sqliteDefaultToDdlColumnDefault(like.default);
134
+ return new DdlColumn({
135
+ name: column.name,
136
+ type: typeSql,
137
+ ...(!column.nullable ? { notNull: true } : {}),
138
+ ...(colDefault !== undefined ? { default: colDefault } : {}),
139
+ ...(column.codecRef !== undefined ? { codecRef: column.codecRef } : {}),
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Builds the table-level constraints (PK / unique / FK) for a `CreateTable`
145
+ * path from the table node — the node-sourced sibling of the retired
146
+ * contract-based `tableToDdlParts`'s constraint half.
147
+ */
148
+ export function tableConstraintsFromNode(
149
+ table: SqlTableIR,
150
+ hasInlinePk: boolean,
151
+ ): DdlTableConstraint[] {
152
+ const constraints: DdlTableConstraint[] = [];
153
+ if (table.primaryKey && !hasInlinePk) {
154
+ constraints.push(new PrimaryKeyConstraint({ columns: table.primaryKey.columns }));
155
+ }
156
+ for (const u of table.uniques) {
157
+ constraints.push(
158
+ new UniqueConstraint({
159
+ columns: u.columns,
160
+ ...(u.name !== undefined ? { name: u.name } : {}),
161
+ }),
162
+ );
163
+ }
164
+ for (const fk of table.foreignKeys) {
165
+ constraints.push(
166
+ new ForeignKeyConstraint({
167
+ columns: fk.columns,
168
+ refTable: fk.referencedTable,
169
+ refColumns: fk.referencedColumns,
170
+ ...(fk.name !== undefined ? { name: fk.name } : {}),
171
+ ...(fk.onDelete !== undefined ? { onDelete: fk.onDelete } : {}),
172
+ ...(fk.onUpdate !== undefined ? { onUpdate: fk.onUpdate } : {}),
173
+ }),
174
+ );
175
+ }
176
+ return constraints;
177
+ }