@prisma-next/target-sqlite 0.16.0-dev.3 → 0.16.0-dev.31
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.
- package/dist/codecs-DGgo--O0.d.mts.map +1 -1
- package/dist/codecs.mjs +25 -6
- package/dist/codecs.mjs.map +1 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +10 -5
- package/dist/control.mjs.map +1 -1
- package/dist/errors-B1JPoWDh.mjs +38 -0
- package/dist/errors-B1JPoWDh.mjs.map +1 -0
- package/dist/migration.d.mts +1 -1
- package/dist/migration.mjs +2 -2
- package/dist/{op-factory-call-8pTnIHhR.mjs → op-factory-call-BkqsWGiy.mjs} +39 -13
- package/dist/op-factory-call-BkqsWGiy.mjs.map +1 -0
- package/dist/op-factory-call.d.mts.map +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/{planner-D4B8Rugz.mjs → planner-Cdl1Lziz.mjs} +19 -15
- package/dist/planner-Cdl1Lziz.mjs.map +1 -0
- package/dist/{planner-produced-sqlite-migration-hyDa7QK-.mjs → planner-produced-sqlite-migration-BGcreGfL.mjs} +22 -12
- package/dist/planner-produced-sqlite-migration-BGcreGfL.mjs.map +1 -0
- package/dist/{planner-produced-sqlite-migration-C9k0q8Il.d.mts → planner-produced-sqlite-migration-fd_Jw-mL.d.mts} +3 -3
- package/dist/planner-produced-sqlite-migration-fd_Jw-mL.d.mts.map +1 -0
- package/dist/planner-produced-sqlite-migration.d.mts +1 -1
- package/dist/planner-produced-sqlite-migration.mjs +1 -1
- package/dist/planner.d.mts +7 -1
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/{render-ops-BDW2tUeR.mjs → render-ops-BAw6MQWl.mjs} +7 -2
- package/dist/render-ops-BAw6MQWl.mjs.map +1 -0
- package/dist/render-ops.d.mts.map +1 -1
- package/dist/render-ops.mjs +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/{sql-utils-CV8Bdgtc.mjs → sql-utils-BMteAbKH.mjs} +15 -15
- package/dist/sql-utils-BMteAbKH.mjs.map +1 -0
- package/dist/sql-utils.d.mts +1 -6
- package/dist/sql-utils.d.mts.map +1 -1
- package/dist/sql-utils.mjs +2 -2
- package/dist/{sqlite-contract-view-B8qeCczc.mjs → sqlite-contract-view-DthhfCpb.mjs} +3 -2
- package/dist/sqlite-contract-view-DthhfCpb.mjs.map +1 -0
- package/dist/{sqlite-migration-BbSrmBAa.d.mts → sqlite-migration-CBXynqeE.d.mts} +4 -3
- package/dist/sqlite-migration-CBXynqeE.d.mts.map +1 -0
- package/dist/{sqlite-migration-BcFf2OFa.mjs → sqlite-migration-DrZIdg3i.mjs} +7 -36
- package/dist/sqlite-migration-DrZIdg3i.mjs.map +1 -0
- package/package.json +18 -18
- package/src/core/codecs.ts +33 -6
- package/src/core/control-target.ts +3 -1
- package/src/core/errors.ts +24 -0
- package/src/core/migrations/column-ddl-rendering.ts +4 -2
- package/src/core/migrations/issue-planner.ts +5 -6
- package/src/core/migrations/op-factory-call.ts +41 -8
- package/src/core/migrations/planner-ddl-builders.ts +10 -3
- package/src/core/migrations/planner-produced-sqlite-migration.ts +4 -0
- package/src/core/migrations/planner-strategies.ts +2 -3
- package/src/core/migrations/planner.ts +8 -0
- package/src/core/migrations/render-ops.ts +4 -1
- package/src/core/migrations/render-typescript.ts +20 -8
- package/src/core/migrations/runner.ts +6 -2
- package/src/core/migrations/sqlite-migration.ts +3 -2
- package/src/core/sql-utils.ts +10 -21
- package/src/core/sqlite-unbound-database.ts +4 -1
- package/src/exports/sql-utils.ts +1 -1
- package/dist/op-factory-call-8pTnIHhR.mjs.map +0 -1
- package/dist/planner-D4B8Rugz.mjs.map +0 -1
- package/dist/planner-produced-sqlite-migration-C9k0q8Il.d.mts.map +0 -1
- package/dist/planner-produced-sqlite-migration-hyDa7QK-.mjs.map +0 -1
- package/dist/render-ops-BDW2tUeR.mjs.map +0 -1
- package/dist/sql-utils-CV8Bdgtc.mjs.map +0 -1
- package/dist/sqlite-contract-view-B8qeCczc.mjs.map +0 -1
- package/dist/sqlite-migration-BbSrmBAa.d.mts.map +0 -1
- package/dist/sqlite-migration-BcFf2OFa.mjs.map +0 -1
|
@@ -1,39 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { t as errorSqliteMigrationStackMissing } from "./errors-B1JPoWDh.mjs";
|
|
2
|
+
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-BkqsWGiy.mjs";
|
|
3
|
+
import { t as SqliteContractView } from "./sqlite-contract-view-DthhfCpb.mjs";
|
|
3
4
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
4
5
|
import { Migration } from "@prisma-next/family-sql/migration";
|
|
5
6
|
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 `MIGRATION.UNFILLED_PLACEHOLDER` (placeholder not filled)
|
|
21
|
-
* because the missing input is the stack itself, not the per-operation
|
|
22
|
-
* contract.
|
|
23
|
-
*
|
|
24
|
-
* Lives in `@prisma-next/target-sqlite/errors` rather than the shared
|
|
25
|
-
* framework migration errors module because the failure is target-specific:
|
|
26
|
-
* the contract it talks about (`SqliteMigration`, the SQLite control
|
|
27
|
-
* adapter, the SQLite-target stack) only exists in this package.
|
|
28
|
-
*/
|
|
29
|
-
function errorSqliteMigrationStackMissing(operation) {
|
|
30
|
-
return new CliStructuredError("MIGRATION.SQLITE_CONTROL_STACK_MISSING", `SqliteMigration.${operation} requires a control adapter`, {
|
|
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
7
|
//#region src/core/migrations/sqlite-migration.ts
|
|
38
8
|
/**
|
|
39
9
|
* Target-owned base class for SQLite migrations. Fixes the `SqlMigration`
|
|
@@ -49,8 +19,9 @@ function errorSqliteMigrationStackMissing(operation) {
|
|
|
49
19
|
* through every call.
|
|
50
20
|
*
|
|
51
21
|
* Binds the framework base's `Start` / `End` contract generics so a subclass
|
|
52
|
-
* that assigns its
|
|
53
|
-
* fully-typed view accessors:
|
|
22
|
+
* that assigns its snapshot-store `contract.json` imports to
|
|
23
|
+
* `startContractJson` / `endContractJson` gets fully-typed view accessors:
|
|
24
|
+
* `this.endContract` is a `SqliteContractView<End>`
|
|
54
25
|
* (sole namespace unwrapped to the root — `this.endContract.table.<name>`),
|
|
55
26
|
* built lazily from the JSON fields via the shared `MigrationContractViews`
|
|
56
27
|
* helper. Mirrors `MongoMigration`'s view getters; the framework base derives
|
|
@@ -120,4 +91,4 @@ var SqliteMigration = class extends Migration {
|
|
|
120
91
|
//#endregion
|
|
121
92
|
export { SqliteMigration as t };
|
|
122
93
|
|
|
123
|
-
//# sourceMappingURL=sqlite-migration-
|
|
94
|
+
//# sourceMappingURL=sqlite-migration-DrZIdg3i.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-migration-DrZIdg3i.mjs","names":["SqlMigration","#endView","#startView"],"sources":["../src/core/migrations/sqlite-migration.ts"],"sourcesContent":["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 snapshot-store `contract.json` imports to\n * `startContractJson` / `endContractJson` gets fully-typed view accessors:\n * `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 MIGRATION.SQLITE_CONTROL_STACK_MISSING 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 MIGRATION.SQLITE_CONTROL_STACK_MISSING 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,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"}
|
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/target-sqlite",
|
|
3
|
-
"version": "0.16.0-dev.
|
|
3
|
+
"version": "0.16.0-dev.31",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@prisma-next/cli": "0.16.0-dev.
|
|
9
|
-
"@prisma-next/contract": "0.16.0-dev.
|
|
10
|
-
"@prisma-next/errors": "0.16.0-dev.
|
|
11
|
-
"@prisma-next/family-sql": "0.16.0-dev.
|
|
12
|
-
"@prisma-next/framework-components": "0.16.0-dev.
|
|
13
|
-
"@prisma-next/migration-tools": "0.16.0-dev.
|
|
14
|
-
"@prisma-next/sql-contract": "0.16.0-dev.
|
|
15
|
-
"@prisma-next/sql-errors": "0.16.0-dev.
|
|
16
|
-
"@prisma-next/sql-relational-core": "0.16.0-dev.
|
|
17
|
-
"@prisma-next/sql-runtime": "0.16.0-dev.
|
|
18
|
-
"@prisma-next/sql-schema-ir": "0.16.0-dev.
|
|
19
|
-
"@prisma-next/ts-render": "0.16.0-dev.
|
|
20
|
-
"@prisma-next/utils": "0.16.0-dev.
|
|
8
|
+
"@prisma-next/cli": "0.16.0-dev.31",
|
|
9
|
+
"@prisma-next/contract": "0.16.0-dev.31",
|
|
10
|
+
"@prisma-next/errors": "0.16.0-dev.31",
|
|
11
|
+
"@prisma-next/family-sql": "0.16.0-dev.31",
|
|
12
|
+
"@prisma-next/framework-components": "0.16.0-dev.31",
|
|
13
|
+
"@prisma-next/migration-tools": "0.16.0-dev.31",
|
|
14
|
+
"@prisma-next/sql-contract": "0.16.0-dev.31",
|
|
15
|
+
"@prisma-next/sql-errors": "0.16.0-dev.31",
|
|
16
|
+
"@prisma-next/sql-relational-core": "0.16.0-dev.31",
|
|
17
|
+
"@prisma-next/sql-runtime": "0.16.0-dev.31",
|
|
18
|
+
"@prisma-next/sql-schema-ir": "0.16.0-dev.31",
|
|
19
|
+
"@prisma-next/ts-render": "0.16.0-dev.31",
|
|
20
|
+
"@prisma-next/utils": "0.16.0-dev.31",
|
|
21
21
|
"@standard-schema/spec": "1.1.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@prisma-next/driver-sqlite": "0.16.0-dev.
|
|
25
|
-
"@prisma-next/test-utils": "0.16.0-dev.
|
|
26
|
-
"@prisma-next/tsconfig": "0.16.0-dev.
|
|
27
|
-
"@prisma-next/tsdown": "0.16.0-dev.
|
|
24
|
+
"@prisma-next/driver-sqlite": "0.16.0-dev.31",
|
|
25
|
+
"@prisma-next/test-utils": "0.16.0-dev.31",
|
|
26
|
+
"@prisma-next/tsconfig": "0.16.0-dev.31",
|
|
27
|
+
"@prisma-next/tsdown": "0.16.0-dev.31",
|
|
28
28
|
"tsdown": "0.22.8",
|
|
29
29
|
"typescript": "5.9.3",
|
|
30
30
|
"vitest": "4.1.10"
|
package/src/core/codecs.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
SQLITE_REAL_CODEC_ID,
|
|
39
39
|
SQLITE_TEXT_CODEC_ID,
|
|
40
40
|
} from './codec-ids';
|
|
41
|
+
import { sqliteError } from './errors';
|
|
41
42
|
|
|
42
43
|
export class SqliteTextCodec extends CodecImpl<
|
|
43
44
|
typeof SQLITE_TEXT_CODEC_ID,
|
|
@@ -170,7 +171,13 @@ export class SqliteBlobCodec extends CodecImpl<
|
|
|
170
171
|
}
|
|
171
172
|
decodeJson(json: JsonValue): Uint8Array {
|
|
172
173
|
if (typeof json !== 'string') {
|
|
173
|
-
throw
|
|
174
|
+
throw sqliteError(
|
|
175
|
+
'RUNTIME.DECODE_FAILED',
|
|
176
|
+
'sqlite/blob@1 contract value must be a base64 string',
|
|
177
|
+
{
|
|
178
|
+
meta: { codecId: SQLITE_BLOB_CODEC_ID, received: typeof json },
|
|
179
|
+
},
|
|
180
|
+
);
|
|
174
181
|
}
|
|
175
182
|
return new Uint8Array(Buffer.from(json, 'base64'));
|
|
176
183
|
}
|
|
@@ -204,7 +211,11 @@ export class SqliteDatetimeCodec extends CodecImpl<
|
|
|
204
211
|
private parseDate(value: string): Date {
|
|
205
212
|
const date = new Date(value);
|
|
206
213
|
if (Number.isNaN(date.getTime())) {
|
|
207
|
-
throw
|
|
214
|
+
throw sqliteError(
|
|
215
|
+
'RUNTIME.DECODE_FAILED',
|
|
216
|
+
`sqlite/datetime@1 value must be a valid ISO-8601 string: ${value}`,
|
|
217
|
+
{ meta: { codecId: SQLITE_DATETIME_CODEC_ID, received: value } },
|
|
218
|
+
);
|
|
208
219
|
}
|
|
209
220
|
return date;
|
|
210
221
|
}
|
|
@@ -219,7 +230,11 @@ export class SqliteDatetimeCodec extends CodecImpl<
|
|
|
219
230
|
}
|
|
220
231
|
decodeJson(json: JsonValue): Date {
|
|
221
232
|
if (typeof json !== 'string') {
|
|
222
|
-
throw
|
|
233
|
+
throw sqliteError(
|
|
234
|
+
'RUNTIME.DECODE_FAILED',
|
|
235
|
+
'sqlite/datetime@1 contract value must be an ISO-8601 string',
|
|
236
|
+
{ meta: { codecId: SQLITE_DATETIME_CODEC_ID, received: typeof json } },
|
|
237
|
+
);
|
|
223
238
|
}
|
|
224
239
|
return this.parseDate(json);
|
|
225
240
|
}
|
|
@@ -296,16 +311,28 @@ export class SqliteBigintCodec extends CodecImpl<
|
|
|
296
311
|
encodeJson(value: bigint): JsonValue {
|
|
297
312
|
const number = Number(value);
|
|
298
313
|
if (!Number.isSafeInteger(number)) {
|
|
299
|
-
throw
|
|
314
|
+
throw sqliteError(
|
|
315
|
+
'RUNTIME.ENCODE_FAILED',
|
|
316
|
+
'sqlite/bigint@1 database JSON value must be a safe integer',
|
|
317
|
+
{ meta: { codecId: SQLITE_BIGINT_CODEC_ID, received: String(value) } },
|
|
318
|
+
);
|
|
300
319
|
}
|
|
301
320
|
return number;
|
|
302
321
|
}
|
|
303
322
|
decodeJson(json: JsonValue): bigint {
|
|
304
323
|
if (typeof json !== 'number') {
|
|
305
|
-
throw
|
|
324
|
+
throw sqliteError(
|
|
325
|
+
'RUNTIME.DECODE_FAILED',
|
|
326
|
+
'sqlite/bigint@1 database JSON value must be a number',
|
|
327
|
+
{ meta: { codecId: SQLITE_BIGINT_CODEC_ID, received: typeof json } },
|
|
328
|
+
);
|
|
306
329
|
}
|
|
307
330
|
if (!Number.isSafeInteger(json)) {
|
|
308
|
-
throw
|
|
331
|
+
throw sqliteError(
|
|
332
|
+
'RUNTIME.DECODE_FAILED',
|
|
333
|
+
'sqlite/bigint@1 database JSON value must be a safe integer',
|
|
334
|
+
{ meta: { codecId: SQLITE_BIGINT_CODEC_ID, received: json } },
|
|
335
|
+
);
|
|
309
336
|
}
|
|
310
337
|
return BigInt(json);
|
|
311
338
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
relationalNodeGranularity,
|
|
13
13
|
} from '@prisma-next/sql-schema-ir/types';
|
|
14
14
|
import { sqliteTargetDescriptorMeta } from './descriptor-meta';
|
|
15
|
+
import { sqliteError } from './errors';
|
|
15
16
|
import { diffSqliteSchema, sqliteContractToSchema } from './migrations/diff-database-schema';
|
|
16
17
|
import { createSqliteMigrationPlanner } from './migrations/planner';
|
|
17
18
|
import type { SqlitePlanTargetDetails } from './migrations/planner-target-details';
|
|
@@ -49,7 +50,8 @@ const sqliteControlTargetDescriptor: SqlControlTargetDescriptor<'sqlite', Sqlite
|
|
|
49
50
|
// encodes that invariant at runtime + narrows the generic
|
|
50
51
|
// to `Contract<SqlStorage>` without a blind cast.
|
|
51
52
|
if (!isSqlContract(contract)) {
|
|
52
|
-
throw
|
|
53
|
+
throw sqliteError(
|
|
54
|
+
'CONTRACT.TARGET_MISMATCH',
|
|
53
55
|
'sqliteControlTargetDescriptor.contractToSchema received a non-SQL contract; expected Contract<SqlStorage>',
|
|
54
56
|
);
|
|
55
57
|
}
|
package/src/core/errors.ts
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
import { CliStructuredError } from '@prisma-next/errors/control';
|
|
2
|
+
import type { StructuredError, StructuredErrorOptions } from '@prisma-next/utils/structured-error';
|
|
3
|
+
import { structuredError } from '@prisma-next/utils/structured-error';
|
|
4
|
+
|
|
5
|
+
export type SqliteTargetErrorCode =
|
|
6
|
+
| 'CONTRACT.CONSTRAINT_INVALID'
|
|
7
|
+
| 'CONTRACT.DEFAULT_INVALID'
|
|
8
|
+
| 'CONTRACT.IDENTIFIER_INVALID'
|
|
9
|
+
| 'CONTRACT.NAMESPACE_INVALID'
|
|
10
|
+
| 'CONTRACT.NATIVE_TYPE_INVALID'
|
|
11
|
+
| 'CONTRACT.TARGET_MISMATCH'
|
|
12
|
+
| 'CONTRACT.TYPE_UNKNOWN'
|
|
13
|
+
| 'MIGRATION.CONTRACT_SPACE_VIOLATION'
|
|
14
|
+
| 'MIGRATION.SQLITE_CONTROL_STACK_MISSING'
|
|
15
|
+
| 'MIGRATION.TARGET_MISMATCH'
|
|
16
|
+
| 'RUNTIME.DECODE_FAILED'
|
|
17
|
+
| 'RUNTIME.ENCODE_FAILED';
|
|
18
|
+
|
|
19
|
+
export function sqliteError(
|
|
20
|
+
code: SqliteTargetErrorCode,
|
|
21
|
+
message: string,
|
|
22
|
+
options?: StructuredErrorOptions,
|
|
23
|
+
): StructuredError {
|
|
24
|
+
return structuredError(code, message, options);
|
|
25
|
+
}
|
|
2
26
|
|
|
3
27
|
/**
|
|
4
28
|
* A `SqliteMigration` operation that needs the materialized control adapter
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '@prisma-next/sql-relational-core/ast';
|
|
11
11
|
import type { SqlColumnIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';
|
|
12
12
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
13
|
+
import { assertNever, InternalError } from '@prisma-next/utils/internal-error';
|
|
13
14
|
import type { SqliteColumnSpec } from './operations/shared';
|
|
14
15
|
import { buildColumnDefaultSql, buildColumnTypeSql } from './planner-ddl-builders';
|
|
15
16
|
|
|
@@ -28,7 +29,7 @@ function columnLike(
|
|
|
28
29
|
column: SqlColumnIR,
|
|
29
30
|
): Pick<StorageColumn, 'nativeType' | 'codecId' | 'nullable' | 'many' | 'typeParams' | 'default'> {
|
|
30
31
|
if (column.codecRef === undefined || column.codecBaseNativeType === undefined) {
|
|
31
|
-
throw new
|
|
32
|
+
throw new InternalError(
|
|
32
33
|
`columnLike: expected column "${column.name}" carries no codec identity — the expected tree must be derived via contractToSchemaIR for planning`,
|
|
33
34
|
);
|
|
34
35
|
}
|
|
@@ -69,7 +70,8 @@ function sqliteDefaultToDdlColumnDefault(
|
|
|
69
70
|
return new FunctionColumnDefault(columnDefault.expression);
|
|
70
71
|
default: {
|
|
71
72
|
const exhaustive: never = columnDefault;
|
|
72
|
-
|
|
73
|
+
return assertNever(
|
|
74
|
+
exhaustive,
|
|
73
75
|
`sqliteDefaultToDdlColumnDefault: unhandled kind "${blindCast<{ kind: string }, 'exhaustiveness: surface the unhandled default kind'>(exhaustive).kind}"`,
|
|
74
76
|
);
|
|
75
77
|
}
|
|
@@ -22,7 +22,6 @@ import type {
|
|
|
22
22
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
23
23
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
24
24
|
import { issueOutcome, orderIssuesByDependencies } from '@prisma-next/framework-components/control';
|
|
25
|
-
import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
|
|
26
25
|
import {
|
|
27
26
|
RelationalSchemaNodeKind,
|
|
28
27
|
type SqlColumnIR,
|
|
@@ -218,8 +217,8 @@ function buildCreateTableCalls(table: SqlTableIR): SqliteOpFactoryCall[] {
|
|
|
218
217
|
new CreateTableCall(table.name, columns, constraints.length > 0 ? constraints : undefined),
|
|
219
218
|
];
|
|
220
219
|
for (const index of table.indexes) {
|
|
221
|
-
const indexName = index.name
|
|
222
|
-
calls.push(new CreateIndexCall(table.name, indexName, index.columns));
|
|
220
|
+
const indexName = index.name;
|
|
221
|
+
calls.push(new CreateIndexCall(table.name, indexName, index.columns ?? []));
|
|
223
222
|
}
|
|
224
223
|
return calls;
|
|
225
224
|
}
|
|
@@ -319,15 +318,15 @@ function mapIndexIssue(
|
|
|
319
318
|
SqlIndexIR,
|
|
320
319
|
'a not-found index issue always carries the expected index node'
|
|
321
320
|
>(issue.expected);
|
|
322
|
-
const indexName = index.name
|
|
323
|
-
return ok([new CreateIndexCall(tableName, indexName, index.columns)]);
|
|
321
|
+
const indexName = index.name;
|
|
322
|
+
return ok([new CreateIndexCall(tableName, indexName, index.columns ?? [])]);
|
|
324
323
|
}
|
|
325
324
|
if (issueOutcome(issue) === 'not-expected') {
|
|
326
325
|
const index = blindCast<
|
|
327
326
|
SqlIndexIR,
|
|
328
327
|
'a not-expected index issue always carries the actual index node'
|
|
329
328
|
>(issue.actual);
|
|
330
|
-
const indexName = index.name
|
|
329
|
+
const indexName = index.name;
|
|
331
330
|
return ok([new DropIndexCall(tableName, indexName)]);
|
|
332
331
|
}
|
|
333
332
|
// not-equal: index type/options/uniqueness drift. SQLite can't ALTER an
|
|
@@ -25,6 +25,7 @@ import { type ImportRequirement, jsonToTsSource, TsExpression } from '@prisma-ne
|
|
|
25
25
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
26
26
|
import { columnExistsAst, indexExistsAst, tableExistsAst } from '../../contract-free/checks';
|
|
27
27
|
import * as contractFreeDdl from '../../contract-free/ddl';
|
|
28
|
+
import { sqliteError } from '../errors';
|
|
28
29
|
import { quoteIdentifier } from '../sql-utils';
|
|
29
30
|
import { addColumnExecuteSql, dropColumnExecuteSql } from './operations/columns';
|
|
30
31
|
import type { SqliteColumnSpec, SqliteIndexSpec, SqliteTableSpec } from './operations/shared';
|
|
@@ -97,9 +98,11 @@ function renderDdlConstraintAsTsCall(constraint: DdlTableConstraint): string {
|
|
|
97
98
|
return `unique(${jsonToTsSource(constraint.columns)}${nameOpt})`;
|
|
98
99
|
}
|
|
99
100
|
case 'check-expression':
|
|
100
|
-
throw
|
|
101
|
+
throw sqliteError(
|
|
102
|
+
'CONTRACT.CONSTRAINT_INVALID',
|
|
101
103
|
`SQLite does not support expression CHECK constraints (constraint "${constraint.name}"). ` +
|
|
102
104
|
'Scalar-array columns and their element-non-null checks are Postgres-only.',
|
|
105
|
+
{ meta: { constraintName: constraint.name } },
|
|
103
106
|
);
|
|
104
107
|
}
|
|
105
108
|
}
|
|
@@ -147,8 +150,10 @@ export class CreateTableCall extends SqliteOpFactoryCallNode {
|
|
|
147
150
|
|
|
148
151
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
149
152
|
if (lowerer === undefined) {
|
|
150
|
-
throw
|
|
153
|
+
throw sqliteError(
|
|
154
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
151
155
|
`CreateTableCall.toOp: a DDL lowerer is required on the SQLite planner path (table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
156
|
+
{ meta: { factory: this.factoryName, tableName: this.tableName } },
|
|
152
157
|
);
|
|
153
158
|
}
|
|
154
159
|
const ddlNode = contractFreeDdl.createTable({
|
|
@@ -223,8 +228,10 @@ export class DropTableCall extends SqliteOpFactoryCallNode {
|
|
|
223
228
|
|
|
224
229
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
225
230
|
if (lowerer === undefined) {
|
|
226
|
-
throw
|
|
231
|
+
throw sqliteError(
|
|
232
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
227
233
|
`DropTableCall.toOp: a lowerer is required on the SQLite planner path (table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
234
|
+
{ meta: { factory: this.factoryName, tableName: this.tableName } },
|
|
228
235
|
);
|
|
229
236
|
}
|
|
230
237
|
const checks = tableExistsAst(this.tableName);
|
|
@@ -287,8 +294,10 @@ export class RecreateTableCall extends SqliteOpFactoryCallNode {
|
|
|
287
294
|
|
|
288
295
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
289
296
|
if (lowerer === undefined) {
|
|
290
|
-
throw
|
|
297
|
+
throw sqliteError(
|
|
298
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
291
299
|
`RecreateTableCall.toOp: a lowerer is required on the SQLite planner path (table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
300
|
+
{ meta: { factory: this.factoryName, tableName: this.tableName } },
|
|
292
301
|
);
|
|
293
302
|
}
|
|
294
303
|
return recreateTable(
|
|
@@ -346,8 +355,16 @@ export class AddColumnCall extends SqliteOpFactoryCallNode {
|
|
|
346
355
|
|
|
347
356
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
348
357
|
if (lowerer === undefined) {
|
|
349
|
-
throw
|
|
358
|
+
throw sqliteError(
|
|
359
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
350
360
|
`AddColumnCall.toOp: a lowerer is required on the SQLite planner path (column "${this.column.name}" on table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
361
|
+
{
|
|
362
|
+
meta: {
|
|
363
|
+
factory: this.factoryName,
|
|
364
|
+
tableName: this.tableName,
|
|
365
|
+
columnName: this.column.name,
|
|
366
|
+
},
|
|
367
|
+
},
|
|
351
368
|
);
|
|
352
369
|
}
|
|
353
370
|
const checks = columnExistsAst(this.tableName, this.column.name);
|
|
@@ -396,8 +413,16 @@ export class DropColumnCall extends SqliteOpFactoryCallNode {
|
|
|
396
413
|
|
|
397
414
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
398
415
|
if (lowerer === undefined) {
|
|
399
|
-
throw
|
|
416
|
+
throw sqliteError(
|
|
417
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
400
418
|
`DropColumnCall.toOp: a lowerer is required on the SQLite planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
419
|
+
{
|
|
420
|
+
meta: {
|
|
421
|
+
factory: this.factoryName,
|
|
422
|
+
tableName: this.tableName,
|
|
423
|
+
columnName: this.columnName,
|
|
424
|
+
},
|
|
425
|
+
},
|
|
401
426
|
);
|
|
402
427
|
}
|
|
403
428
|
const checks = columnExistsAst(this.tableName, this.columnName);
|
|
@@ -467,8 +492,12 @@ export class CreateIndexCall extends SqliteOpFactoryCallNode {
|
|
|
467
492
|
|
|
468
493
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
469
494
|
if (lowerer === undefined) {
|
|
470
|
-
throw
|
|
495
|
+
throw sqliteError(
|
|
496
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
471
497
|
`CreateIndexCall.toOp: a lowerer is required on the SQLite planner path (index "${this.indexName}" on table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
498
|
+
{
|
|
499
|
+
meta: { factory: this.factoryName, tableName: this.tableName, indexName: this.indexName },
|
|
500
|
+
},
|
|
472
501
|
);
|
|
473
502
|
}
|
|
474
503
|
const checks = indexExistsAst(this.indexName);
|
|
@@ -520,8 +549,12 @@ export class DropIndexCall extends SqliteOpFactoryCallNode {
|
|
|
520
549
|
|
|
521
550
|
async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
|
|
522
551
|
if (lowerer === undefined) {
|
|
523
|
-
throw
|
|
552
|
+
throw sqliteError(
|
|
553
|
+
'MIGRATION.SQLITE_CONTROL_STACK_MISSING',
|
|
524
554
|
`DropIndexCall.toOp: a lowerer is required on the SQLite planner path (index "${this.indexName}" on table "${this.tableName}"). Pass the control adapter to createSqliteMigrationPlanner.`,
|
|
555
|
+
{
|
|
556
|
+
meta: { factory: this.factoryName, tableName: this.tableName, indexName: this.indexName },
|
|
557
|
+
},
|
|
525
558
|
);
|
|
526
559
|
}
|
|
527
560
|
const checks = indexExistsAst(this.indexName);
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
StorageTable,
|
|
14
14
|
StorageTypeInstance,
|
|
15
15
|
} from '@prisma-next/sql-contract/types';
|
|
16
|
+
import { sqliteError } from '../errors';
|
|
16
17
|
import { escapeLiteral, quoteIdentifier } from '../sql-utils';
|
|
17
18
|
|
|
18
19
|
type SqliteColumnDefault = StorageColumn['default'];
|
|
@@ -21,18 +22,22 @@ const SAFE_NATIVE_TYPE_PATTERN = /^[a-zA-Z][a-zA-Z0-9_ ]*$/;
|
|
|
21
22
|
|
|
22
23
|
function assertSafeNativeType(nativeType: string): void {
|
|
23
24
|
if (!SAFE_NATIVE_TYPE_PATTERN.test(nativeType)) {
|
|
24
|
-
throw
|
|
25
|
+
throw sqliteError(
|
|
26
|
+
'CONTRACT.NATIVE_TYPE_INVALID',
|
|
25
27
|
`Unsafe native type name in contract: "${nativeType}". ` +
|
|
26
28
|
'Native type names must match /^[a-zA-Z][a-zA-Z0-9_ ]*$/',
|
|
29
|
+
{ meta: { nativeType } },
|
|
27
30
|
);
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
function assertSafeDefaultExpression(expression: string): void {
|
|
32
35
|
if (expression.includes(';') || /--|\/\*|\bSELECT\b/i.test(expression)) {
|
|
33
|
-
throw
|
|
36
|
+
throw sqliteError(
|
|
37
|
+
'CONTRACT.DEFAULT_INVALID',
|
|
34
38
|
`Unsafe default expression in contract: "${expression}". ` +
|
|
35
39
|
'Default expressions must not contain semicolons, SQL comment tokens, or subqueries.',
|
|
40
|
+
{ meta: { expression } },
|
|
36
41
|
);
|
|
37
42
|
}
|
|
38
43
|
}
|
|
@@ -130,8 +135,10 @@ export function resolveColumnTypeMetadata(
|
|
|
130
135
|
}
|
|
131
136
|
const referencedType = storageTypes[column.typeRef];
|
|
132
137
|
if (!referencedType) {
|
|
133
|
-
throw
|
|
138
|
+
throw sqliteError(
|
|
139
|
+
'CONTRACT.TYPE_UNKNOWN',
|
|
134
140
|
`Storage type "${column.typeRef}" referenced by column is not defined in storage.types.`,
|
|
141
|
+
{ meta: { typeRef: column.typeRef } },
|
|
135
142
|
);
|
|
136
143
|
}
|
|
137
144
|
return {
|
|
@@ -25,6 +25,7 @@ export class TypeScriptRenderableSqliteMigration
|
|
|
25
25
|
readonly #meta: MigrationMeta;
|
|
26
26
|
readonly #destination: SqliteMigrationDestinationInfo;
|
|
27
27
|
readonly #spaceId: string;
|
|
28
|
+
readonly #snapshotsImportPath: string;
|
|
28
29
|
readonly #lowerer: ExecuteRequestLowerer | undefined;
|
|
29
30
|
#operationsCache: readonly (Op | Promise<Op>)[] | undefined;
|
|
30
31
|
|
|
@@ -32,6 +33,7 @@ export class TypeScriptRenderableSqliteMigration
|
|
|
32
33
|
calls: readonly OpFactoryCall[],
|
|
33
34
|
meta: MigrationMeta,
|
|
34
35
|
spaceId: string,
|
|
36
|
+
snapshotsImportPath: string,
|
|
35
37
|
destination?: SqliteMigrationDestinationInfo,
|
|
36
38
|
lowerer?: ExecuteRequestLowerer,
|
|
37
39
|
) {
|
|
@@ -39,6 +41,7 @@ export class TypeScriptRenderableSqliteMigration
|
|
|
39
41
|
this.#calls = calls;
|
|
40
42
|
this.#meta = meta;
|
|
41
43
|
this.#spaceId = spaceId;
|
|
44
|
+
this.#snapshotsImportPath = snapshotsImportPath;
|
|
42
45
|
this.#destination = destination ?? { storageHash: meta.to };
|
|
43
46
|
this.#lowerer = lowerer;
|
|
44
47
|
}
|
|
@@ -69,6 +72,7 @@ export class TypeScriptRenderableSqliteMigration
|
|
|
69
72
|
return renderCallsToTypeScript(this.#calls, {
|
|
70
73
|
from: this.#meta.from,
|
|
71
74
|
to: this.#meta.to,
|
|
75
|
+
snapshotsImportPath: this.#snapshotsImportPath,
|
|
72
76
|
});
|
|
73
77
|
}
|
|
74
78
|
}
|
|
@@ -20,7 +20,6 @@ import type {
|
|
|
20
20
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
21
21
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
22
22
|
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
23
|
-
import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
|
|
24
23
|
import {
|
|
25
24
|
RelationalSchemaNodeKind,
|
|
26
25
|
type SqlColumnIR,
|
|
@@ -150,8 +149,8 @@ export const recreateTableStrategy: CallMigrationStrategy = (issues, ctx) => {
|
|
|
150
149
|
// Indexes (declared + FK-backing) are already merged and deduped by
|
|
151
150
|
// column-set at derivation (`contractToSchemaIR`'s `convertTable`).
|
|
152
151
|
const indexes: SqliteIndexSpec[] = expectedTable.indexes.map((idx) => ({
|
|
153
|
-
name: idx.name
|
|
154
|
-
columns: idx.columns,
|
|
152
|
+
name: idx.name,
|
|
153
|
+
columns: idx.columns ?? [],
|
|
155
154
|
}));
|
|
156
155
|
|
|
157
156
|
calls.push(
|
|
@@ -92,6 +92,12 @@ export class SqliteMigrationPlanner
|
|
|
92
92
|
* {@link SqlMigrationPlannerPlanOptions.ownership}.
|
|
93
93
|
*/
|
|
94
94
|
readonly ownership?: SchemaOwnership;
|
|
95
|
+
/**
|
|
96
|
+
* POSIX-relative path from the migration package dir to
|
|
97
|
+
* `migrations/snapshots` — see
|
|
98
|
+
* {@link SqlMigrationPlannerPlanOptions.snapshotsImportPath}.
|
|
99
|
+
*/
|
|
100
|
+
readonly snapshotsImportPath: string;
|
|
95
101
|
}): SqlitePlanResult {
|
|
96
102
|
return this.planSql(options as SqlMigrationPlannerPlanOptions);
|
|
97
103
|
}
|
|
@@ -107,6 +113,7 @@ export class SqliteMigrationPlanner
|
|
|
107
113
|
to: context.toHash,
|
|
108
114
|
},
|
|
109
115
|
spaceId,
|
|
116
|
+
context.snapshotsImportPath,
|
|
110
117
|
undefined,
|
|
111
118
|
this.#lowerer,
|
|
112
119
|
);
|
|
@@ -164,6 +171,7 @@ export class SqliteMigrationPlanner
|
|
|
164
171
|
to: options.contract.storage.storageHash,
|
|
165
172
|
},
|
|
166
173
|
options.spaceId,
|
|
174
|
+
options.snapshotsImportPath,
|
|
167
175
|
destination,
|
|
168
176
|
this.#lowerer,
|
|
169
177
|
),
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '@prisma-next/framework-components/control';
|
|
7
7
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
8
8
|
import { isThenable } from '@prisma-next/utils/promise';
|
|
9
|
+
import { sqliteError } from '../errors';
|
|
9
10
|
import type { SqlitePlanTargetDetails } from './planner-target-details';
|
|
10
11
|
|
|
11
12
|
type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
|
|
@@ -16,8 +17,10 @@ function assertSqliteOp(op: MigrationPlanOperation, callFactoryName: string): as
|
|
|
16
17
|
'op.target is present on concrete SqlMigrationPlanOperation but absent on the framework MigrationPlanOperation base'
|
|
17
18
|
>(op).target?.id;
|
|
18
19
|
if (targetId !== 'sqlite') {
|
|
19
|
-
throw
|
|
20
|
+
throw sqliteError(
|
|
21
|
+
'MIGRATION.TARGET_MISMATCH',
|
|
20
22
|
`renderOps: expected sqlite op but got target.id="${String(targetId)}" for op.id="${op.id}" (factoryName="${callFactoryName}"). An OpFactoryCall produced an op for a different target on the sqlite planner path; check the call's target binding.`,
|
|
23
|
+
{ meta: { opId: op.id, targetId: String(targetId), factoryName: callFactoryName } },
|
|
21
24
|
);
|
|
22
25
|
}
|
|
23
26
|
}
|