@prisma-next/target-sqlite 0.14.0-dev.4 → 0.14.0-dev.41
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/contract-free.mjs +1 -1
- package/dist/control.d.mts +3 -4
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +28 -27
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-DxmEeTJ-.mjs → descriptor-meta-D1fap-5t.mjs} +4 -11
- package/dist/descriptor-meta-D1fap-5t.mjs.map +1 -0
- package/dist/descriptor-meta-runtime-BkXK3OjD.mjs +12 -0
- package/dist/descriptor-meta-runtime-BkXK3OjD.mjs.map +1 -0
- package/dist/migration.d.mts +2 -2
- package/dist/migration.mjs +2 -2
- package/dist/{op-factory-call-DmdfD1yd.mjs → op-factory-call-CMBTpb4M.mjs} +54 -53
- package/dist/{op-factory-call-DmdfD1yd.mjs.map → op-factory-call-CMBTpb4M.mjs.map} +1 -1
- package/dist/op-factory-call.d.mts +2 -2
- package/dist/op-factory-call.d.mts.map +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-Ciq8p_dL.mjs → planner-BzIVyjD-.mjs} +68 -14
- package/dist/planner-BzIVyjD-.mjs.map +1 -0
- package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts → planner-produced-sqlite-migration-B9UZVDPa.d.mts} +3 -3
- package/dist/{planner-produced-sqlite-migration-CpgsY-M9.d.mts.map → planner-produced-sqlite-migration-B9UZVDPa.d.mts.map} +1 -1
- package/dist/{planner-produced-sqlite-migration-0xPEm3R1.mjs → planner-produced-sqlite-migration-DuQtGNO7.mjs} +46 -17
- package/dist/planner-produced-sqlite-migration-DuQtGNO7.mjs.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 +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/runtime.d.mts +6 -4
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +3 -3
- package/dist/{shared-Dhc8mLK1.d.mts → shared-C6sM-wel.d.mts} +2 -2
- package/dist/{shared-Dhc8mLK1.d.mts.map → shared-C6sM-wel.d.mts.map} +1 -1
- package/dist/{sqlite-contract-serializer--iaDgC8e.mjs → sqlite-contract-view-1h0aHx1n.mjs} +34 -9
- package/dist/sqlite-contract-view-1h0aHx1n.mjs.map +1 -0
- package/dist/sqlite-contract-view-J32K82Gi.d.mts +29 -0
- package/dist/sqlite-contract-view-J32K82Gi.d.mts.map +1 -0
- package/dist/{sqlite-migration-A0rwqPOG.mjs → sqlite-migration-Dx3LlQNU.mjs} +29 -2
- package/dist/sqlite-migration-Dx3LlQNU.mjs.map +1 -0
- package/dist/{sqlite-migration-DVfhQwN_.d.mts → sqlite-migration-_BhTcnIe.d.mts} +27 -4
- package/dist/sqlite-migration-_BhTcnIe.d.mts.map +1 -0
- package/package.json +18 -18
- package/src/core/control-target.ts +26 -18
- package/src/core/migrations/diff-database-schema.ts +74 -0
- package/src/core/migrations/op-factory-call.ts +5 -0
- package/src/core/migrations/planner.ts +21 -9
- package/src/core/migrations/render-typescript.ts +42 -15
- package/src/core/migrations/runner.ts +4 -10
- package/src/core/migrations/sqlite-migration.ts +42 -1
- package/src/core/sqlite-contract-serializer.ts +41 -14
- package/src/core/sqlite-contract-view.ts +41 -0
- package/src/core/sqlite-unbound-database.ts +8 -8
- package/src/exports/runtime.ts +1 -0
- package/dist/descriptor-meta-DxmEeTJ-.mjs.map +0 -1
- package/dist/planner-Ciq8p_dL.mjs.map +0 -1
- package/dist/planner-produced-sqlite-migration-0xPEm3R1.mjs.map +0 -1
- package/dist/sqlite-contract-serializer--iaDgC8e.mjs.map +0 -1
- package/dist/sqlite-migration-A0rwqPOG.mjs.map +0 -1
- package/dist/sqlite-migration-DVfhQwN_.d.mts.map +0 -1
|
@@ -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-
|
|
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,8 +23,17 @@ 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
|
|
@@ -31,6 +43,17 @@ declare abstract class SqliteMigration extends Migration<SqlitePlanTargetDetails
|
|
|
31
43
|
*/
|
|
32
44
|
protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;
|
|
33
45
|
constructor(stack?: ControlStack<'sql', 'sqlite'>);
|
|
46
|
+
/**
|
|
47
|
+
* The typed SQLite view over this migration's end-state contract — sole
|
|
48
|
+
* namespace unwrapped to the root, so `this.endContract.table.<name>` etc.
|
|
49
|
+
* Throws if no `endContractJson` was provided.
|
|
50
|
+
*/
|
|
51
|
+
get endContract(): SqliteContractView<End>;
|
|
52
|
+
/**
|
|
53
|
+
* The typed SQLite view over this migration's start-state contract, or
|
|
54
|
+
* `null` for a baseline migration (no `startContractJson`).
|
|
55
|
+
*/
|
|
56
|
+
get startContract(): SqliteContractView<Start> | null;
|
|
34
57
|
protected createTable(options: {
|
|
35
58
|
readonly table: string;
|
|
36
59
|
readonly ifNotExists?: boolean;
|
|
@@ -72,4 +95,4 @@ declare abstract class SqliteMigration extends Migration<SqlitePlanTargetDetails
|
|
|
72
95
|
}
|
|
73
96
|
//#endregion
|
|
74
97
|
export { SqliteMigration as t };
|
|
75
|
-
//# sourceMappingURL=sqlite-migration-
|
|
98
|
+
//# sourceMappingURL=sqlite-migration-_BhTcnIe.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-migration-_BhTcnIe.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;EA0C+B;;;;;;EAAA,mBAlCrB,cAAA,EAAgB,iBAAA;cAWvB,KAAA,GAAQ,YAAA;EAkDD;;;;;EAAA,IAnCf,WAAA,IAAe,kBAAA,CAAmB,GAAA;EAsDlC;;;;EAAA,IA9CA,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,UASF,SAAA,CAAU,OAAA;IAAA,SAAoB,KAAA;EAAA,IAAkB,OAAA,CAAQ,EAAA;EAAA,UAOxD,SAAA,CAAU,OAAA;IAAA,SACT,KAAA;IAAA,SACA,MAAA,EAAQ,gBAAA;EAAA,IACf,OAAA,CAAQ,EAAA;EAAA,UAOF,UAAA,CAAW,OAAA;IAAA,SAAoB,KAAA;IAAA,SAAwB,MAAA;EAAA,IAAmB,OAAA,CAAQ,EAAA;EAAA,UAOlF,WAAA,CAAY,OAAA;IAAA,SACX,KAAA;IAAA,SACA,KAAA;IAAA,SACA,OAAA;EAAA,IACP,OAAA,CAAQ,EAAA;EAAA,UASF,SAAA,CAAU,OAAA;IAAA,SAAoB,KAAA;IAAA,SAAwB,KAAA;EAAA,IAAkB,OAAA,CAAQ,EAAA;EAAA,UAOhF,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.
|
|
3
|
+
"version": "0.14.0-dev.41",
|
|
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.
|
|
9
|
-
"@prisma-next/contract": "0.14.0-dev.
|
|
10
|
-
"@prisma-next/errors": "0.14.0-dev.
|
|
11
|
-
"@prisma-next/family-sql": "0.14.0-dev.
|
|
12
|
-
"@prisma-next/framework-components": "0.14.0-dev.
|
|
13
|
-
"@prisma-next/migration-tools": "0.14.0-dev.
|
|
14
|
-
"@prisma-next/sql-contract": "0.14.0-dev.
|
|
15
|
-
"@prisma-next/sql-errors": "0.14.0-dev.
|
|
16
|
-
"@prisma-next/sql-relational-core": "0.14.0-dev.
|
|
17
|
-
"@prisma-next/sql-runtime": "0.14.0-dev.
|
|
18
|
-
"@prisma-next/sql-schema-ir": "0.14.0-dev.
|
|
19
|
-
"@prisma-next/ts-render": "0.14.0-dev.
|
|
20
|
-
"@prisma-next/utils": "0.14.0-dev.
|
|
8
|
+
"@prisma-next/cli": "0.14.0-dev.41",
|
|
9
|
+
"@prisma-next/contract": "0.14.0-dev.41",
|
|
10
|
+
"@prisma-next/errors": "0.14.0-dev.41",
|
|
11
|
+
"@prisma-next/family-sql": "0.14.0-dev.41",
|
|
12
|
+
"@prisma-next/framework-components": "0.14.0-dev.41",
|
|
13
|
+
"@prisma-next/migration-tools": "0.14.0-dev.41",
|
|
14
|
+
"@prisma-next/sql-contract": "0.14.0-dev.41",
|
|
15
|
+
"@prisma-next/sql-errors": "0.14.0-dev.41",
|
|
16
|
+
"@prisma-next/sql-relational-core": "0.14.0-dev.41",
|
|
17
|
+
"@prisma-next/sql-runtime": "0.14.0-dev.41",
|
|
18
|
+
"@prisma-next/sql-schema-ir": "0.14.0-dev.41",
|
|
19
|
+
"@prisma-next/ts-render": "0.14.0-dev.41",
|
|
20
|
+
"@prisma-next/utils": "0.14.0-dev.41",
|
|
21
21
|
"@standard-schema/spec": "1.1.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@prisma-next/driver-sqlite": "0.14.0-dev.
|
|
25
|
-
"@prisma-next/test-utils": "0.14.0-dev.
|
|
26
|
-
"@prisma-next/tsconfig": "0.14.0-dev.
|
|
27
|
-
"@prisma-next/tsdown": "0.14.0-dev.
|
|
24
|
+
"@prisma-next/driver-sqlite": "0.14.0-dev.41",
|
|
25
|
+
"@prisma-next/test-utils": "0.14.0-dev.41",
|
|
26
|
+
"@prisma-next/tsconfig": "0.14.0-dev.41",
|
|
27
|
+
"@prisma-next/tsdown": "0.14.0-dev.41",
|
|
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 {
|
|
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
|
|
9
|
+
import { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
11
10
|
import { sqliteTargetDescriptorMeta } from './descriptor-meta';
|
|
11
|
+
import {
|
|
12
|
+
diffSqliteDatabaseSchema,
|
|
13
|
+
sqliteContractToSchema,
|
|
14
|
+
verifySqliteDatabaseSchema,
|
|
15
|
+
} 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,29 @@ 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
|
+
diffDatabaseSchema(input) {
|
|
32
|
+
return diffSqliteDatabaseSchema({
|
|
33
|
+
contract: input.contract,
|
|
34
|
+
actualSchema: input.schema,
|
|
35
|
+
strict: input.strict,
|
|
36
|
+
typeMetadataRegistry: input.typeMetadataRegistry,
|
|
37
|
+
frameworkComponents: input.frameworkComponents,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
verifyDatabaseSchema(input) {
|
|
41
|
+
return verifySqliteDatabaseSchema({
|
|
42
|
+
contract: input.contract,
|
|
43
|
+
actualSchema: input.schema,
|
|
44
|
+
strict: input.strict,
|
|
45
|
+
typeMetadataRegistry: input.typeMetadataRegistry,
|
|
46
|
+
frameworkComponents: input.frameworkComponents,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
38
49
|
migrations: {
|
|
39
50
|
createPlanner(adapter: SqlControlAdapter<'sqlite'>): MigrationPlanner<'sql', 'sqlite'> {
|
|
40
51
|
return createSqliteMigrationPlanner(adapter);
|
|
@@ -55,10 +66,7 @@ const sqliteControlTargetDescriptor: SqlControlTargetDescriptor<'sqlite', Sqlite
|
|
|
55
66
|
'sqliteControlTargetDescriptor.contractToSchema received a non-SQL contract; expected Contract<SqlStorage>',
|
|
56
67
|
);
|
|
57
68
|
}
|
|
58
|
-
return
|
|
59
|
-
annotationNamespace: 'sqlite',
|
|
60
|
-
renderDefault: sqliteRenderDefault,
|
|
61
|
-
});
|
|
69
|
+
return sqliteContractToSchema(contract);
|
|
62
70
|
},
|
|
63
71
|
},
|
|
64
72
|
create(): ControlTargetInstance<'sql', 'sqlite'> {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ColumnDefault, Contract } from '@prisma-next/contract/types';
|
|
2
|
+
import { contractToSchemaIR } from '@prisma-next/family-sql/control';
|
|
3
|
+
import { verifySqlSchemaTree } from '@prisma-next/family-sql/diff';
|
|
4
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
5
|
+
import type { VerifyDatabaseSchemaResult } from '@prisma-next/framework-components/control';
|
|
6
|
+
import { SchemaDiff } from '@prisma-next/framework-components/control';
|
|
7
|
+
import type { SqlStorage, StorageColumn } from '@prisma-next/sql-contract/types';
|
|
8
|
+
import type { SqlSchemaIR, SqlSchemaIRNode } from '@prisma-next/sql-schema-ir/types';
|
|
9
|
+
import { parseSqliteDefault } from '../default-normalizer';
|
|
10
|
+
import { normalizeSqliteNativeType } from '../native-type-normalizer';
|
|
11
|
+
import { renderDefaultLiteral } from './planner-ddl-builders';
|
|
12
|
+
|
|
13
|
+
interface SqliteDiffDatabaseSchemaInput {
|
|
14
|
+
readonly contract: Contract<SqlStorage>;
|
|
15
|
+
readonly actualSchema: SqlSchemaIRNode;
|
|
16
|
+
readonly strict: boolean;
|
|
17
|
+
readonly typeMetadataRegistry: ReadonlyMap<string, { readonly nativeType?: string }>;
|
|
18
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Renders a column default for the SQLite dialect. */
|
|
22
|
+
export function sqliteRenderDefault(def: ColumnDefault, _column: StorageColumn): string {
|
|
23
|
+
if (def.kind === 'function') {
|
|
24
|
+
if (def.expression === 'now()') {
|
|
25
|
+
return "datetime('now')";
|
|
26
|
+
}
|
|
27
|
+
return def.expression;
|
|
28
|
+
}
|
|
29
|
+
return renderDefaultLiteral(def.value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The SQLite expected-side projection: contract → flat relational schema IR. */
|
|
33
|
+
export function sqliteContractToSchema(contract: Contract<SqlStorage> | null): SqlSchemaIR {
|
|
34
|
+
return contractToSchemaIR(contract, {
|
|
35
|
+
annotationNamespace: 'sqlite',
|
|
36
|
+
renderDefault: sqliteRenderDefault,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function computeSqliteSchemaComparison(
|
|
41
|
+
input: SqliteDiffDatabaseSchemaInput,
|
|
42
|
+
): VerifyDatabaseSchemaResult {
|
|
43
|
+
return verifySqlSchemaTree({
|
|
44
|
+
contract: input.contract,
|
|
45
|
+
actualSchema: input.actualSchema,
|
|
46
|
+
buildExpectedSchema: sqliteContractToSchema,
|
|
47
|
+
strict: input.strict,
|
|
48
|
+
typeMetadataRegistry: input.typeMetadataRegistry,
|
|
49
|
+
frameworkComponents: input.frameworkComponents,
|
|
50
|
+
normalizeDefault: parseSqliteDefault,
|
|
51
|
+
normalizeNativeType: normalizeSqliteNativeType,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The SQLite `SchemaDiffer` — relational only. SQLite has a single flat
|
|
57
|
+
* schema and no structural (policy) diff, so it runs the shared per-schema
|
|
58
|
+
* relational diff and returns no `schemaDiffIssues`.
|
|
59
|
+
*/
|
|
60
|
+
export function diffSqliteDatabaseSchema(input: SqliteDiffDatabaseSchemaInput): SchemaDiff {
|
|
61
|
+
const relational = computeSqliteSchemaComparison(input);
|
|
62
|
+
return new SchemaDiff(relational.schema.issues, relational.schema.schemaDiffIssues);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The same comparison as {@link diffSqliteDatabaseSchema}, wrapped in the
|
|
67
|
+
* verify envelope (`ok`/`summary`/`code`/`target`/`timings`) plus the
|
|
68
|
+
* pass/warn/fail tree the CLI renders.
|
|
69
|
+
*/
|
|
70
|
+
export function verifySqliteDatabaseSchema(
|
|
71
|
+
input: SqliteDiffDatabaseSchemaInput,
|
|
72
|
+
): VerifyDatabaseSchemaResult {
|
|
73
|
+
return computeSqliteSchemaComparison(input);
|
|
74
|
+
}
|
|
@@ -96,6 +96,11 @@ function renderDdlConstraintAsTsCall(constraint: DdlTableConstraint): string {
|
|
|
96
96
|
const nameOpt = constraint.name ? `, { name: ${jsonToTsSource(constraint.name)} }` : '';
|
|
97
97
|
return `unique(${jsonToTsSource(constraint.columns)}${nameOpt})`;
|
|
98
98
|
}
|
|
99
|
+
case 'check-expression':
|
|
100
|
+
throw new Error(
|
|
101
|
+
`SQLite does not support expression CHECK constraints (constraint "${constraint.name}"). ` +
|
|
102
|
+
'Scalar-array columns and their element-non-null checks are Postgres-only.',
|
|
103
|
+
);
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
|
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
plannerFailure,
|
|
12
12
|
} from '@prisma-next/family-sql/control';
|
|
13
13
|
import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
|
|
14
|
-
import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
|
|
15
14
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
16
15
|
import type {
|
|
17
16
|
MigrationPlanner,
|
|
18
17
|
MigrationScaffoldContext,
|
|
19
18
|
SchemaIssue,
|
|
20
19
|
} from '@prisma-next/framework-components/control';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
20
|
+
import type { SqlSchemaIR, SqlSchemaIRNode } from '@prisma-next/sql-schema-ir/types';
|
|
21
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
22
|
+
import { diffSqliteDatabaseSchema } from './diff-database-schema';
|
|
23
23
|
import { planIssues } from './issue-planner';
|
|
24
24
|
import {
|
|
25
25
|
type SqliteMigrationDestinationInfo,
|
|
@@ -117,7 +117,7 @@ export class SqliteMigrationPlanner
|
|
|
117
117
|
fromContract: options.fromContract,
|
|
118
118
|
codecHooks,
|
|
119
119
|
storageTypes,
|
|
120
|
-
schema: options.schema,
|
|
120
|
+
schema: sqliteFlatSchema(options.schema),
|
|
121
121
|
policy: options.policy,
|
|
122
122
|
frameworkComponents: options.frameworkComponents,
|
|
123
123
|
strategies: sqlitePlannerStrategies,
|
|
@@ -181,15 +181,27 @@ export class SqliteMigrationPlanner
|
|
|
181
181
|
private collectSchemaIssues(options: SqlMigrationPlannerPlanOptions): readonly SchemaIssue[] {
|
|
182
182
|
const allowed = options.policy.allowedOperationClasses;
|
|
183
183
|
const strict = allowed.includes('widening') || allowed.includes('destructive');
|
|
184
|
-
const
|
|
184
|
+
const rawDiff = diffSqliteDatabaseSchema({
|
|
185
185
|
contract: options.contract,
|
|
186
|
-
|
|
186
|
+
actualSchema: options.schema,
|
|
187
187
|
strict,
|
|
188
188
|
typeMetadataRegistry: new Map(),
|
|
189
189
|
frameworkComponents: options.frameworkComponents,
|
|
190
|
-
normalizeDefault: parseSqliteDefault,
|
|
191
|
-
normalizeNativeType: normalizeSqliteNativeType,
|
|
192
190
|
});
|
|
193
|
-
|
|
191
|
+
// The caller-supplied predicate is applied blindly — any scoping (e.g.
|
|
192
|
+
// multi-space ownership) is the orchestration's, never worked out here.
|
|
193
|
+
const diff = options.keepDiffIssue ? rawDiff.filter(options.keepDiffIssue) : rawDiff;
|
|
194
|
+
return diff.issues;
|
|
194
195
|
}
|
|
195
196
|
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* SQLite has a single, flat schema — its introspected node IS a per-schema
|
|
200
|
+
* `SqlSchemaIR`, never the multi-namespace tree the Postgres target builds. The
|
|
201
|
+
* planner consumes that flat shape directly when building ops.
|
|
202
|
+
*/
|
|
203
|
+
function sqliteFlatSchema(schema: SqlSchemaIRNode): SqlSchemaIR {
|
|
204
|
+
return blindCast<SqlSchemaIR, 'the SQLite introspected node is a flat per-schema SqlSchemaIR'>(
|
|
205
|
+
schema,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
@@ -35,15 +35,19 @@ export function renderCallsToTypeScript(
|
|
|
35
35
|
calls: ReadonlyArray<OpFactoryCall>,
|
|
36
36
|
meta: RenderMigrationMeta,
|
|
37
37
|
): string {
|
|
38
|
-
const imports = buildImports(calls);
|
|
38
|
+
const imports = buildImports(calls, meta);
|
|
39
39
|
const operationsBody = calls.map((c) => c.renderTypeScript()).join(',\n');
|
|
40
|
+
const hasStart = meta.from !== null;
|
|
41
|
+
const startField = hasStart ? [' override readonly startContractJson = startContract;'] : [];
|
|
40
42
|
|
|
41
43
|
return [
|
|
42
44
|
shebangLineFor(detectScaffoldRuntime()),
|
|
43
45
|
imports,
|
|
44
46
|
'',
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
`export default class M extends Migration<${hasStart ? 'Start' : 'never'}, End> {`,
|
|
48
|
+
...startField,
|
|
49
|
+
' override readonly endContractJson = endContract;',
|
|
50
|
+
'',
|
|
47
51
|
' override get operations() {',
|
|
48
52
|
' return [',
|
|
49
53
|
indent(operationsBody, 6),
|
|
@@ -56,8 +60,8 @@ export function renderCallsToTypeScript(
|
|
|
56
60
|
].join('\n');
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
function buildImports(calls: ReadonlyArray<OpFactoryCall
|
|
60
|
-
const requirements: ImportRequirement[] = [...BASE_IMPORTS];
|
|
63
|
+
function buildImports(calls: ReadonlyArray<OpFactoryCall>, meta: RenderMigrationMeta): string {
|
|
64
|
+
const requirements: ImportRequirement[] = [...BASE_IMPORTS, ...contractImports(meta)];
|
|
61
65
|
for (const call of calls) {
|
|
62
66
|
for (const req of call.importRequirements()) {
|
|
63
67
|
requirements.push(req);
|
|
@@ -66,16 +70,39 @@ function buildImports(calls: ReadonlyArray<OpFactoryCall>): string {
|
|
|
66
70
|
return renderImports(requirements);
|
|
67
71
|
}
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
/**
|
|
74
|
+
* The committed contract-JSON imports the scaffold reads its from/to identity
|
|
75
|
+
* from. `end-contract.json` is always present; `start-contract.json` is added
|
|
76
|
+
* only for a non-baseline migration (`meta.from !== null`). The matching
|
|
77
|
+
* `Contract` type imports (aliased `Start`/`End`) feed the
|
|
78
|
+
* `Migration<Start, End>` generics. Baseline emits `Migration<never, End>` with
|
|
79
|
+
* no start imports — `never` is the honest "no prior contract" Start.
|
|
80
|
+
*/
|
|
81
|
+
function contractImports(meta: RenderMigrationMeta): readonly ImportRequirement[] {
|
|
82
|
+
const reqs: ImportRequirement[] = [
|
|
83
|
+
{
|
|
84
|
+
moduleSpecifier: './end-contract.json',
|
|
85
|
+
symbol: 'endContract',
|
|
86
|
+
kind: 'default',
|
|
87
|
+
attributes: { type: 'json' },
|
|
88
|
+
},
|
|
89
|
+
{ moduleSpecifier: './end-contract', symbol: 'Contract', alias: 'End', typeOnly: true },
|
|
90
|
+
];
|
|
91
|
+
if (meta.from !== null) {
|
|
92
|
+
reqs.push({
|
|
93
|
+
moduleSpecifier: './start-contract.json',
|
|
94
|
+
symbol: 'startContract',
|
|
95
|
+
kind: 'default',
|
|
96
|
+
attributes: { type: 'json' },
|
|
97
|
+
});
|
|
98
|
+
reqs.push({
|
|
99
|
+
moduleSpecifier: './start-contract',
|
|
100
|
+
symbol: 'Contract',
|
|
101
|
+
alias: 'Start',
|
|
102
|
+
typeOnly: true,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return reqs;
|
|
79
106
|
}
|
|
80
107
|
|
|
81
108
|
function indent(text: string, spaces: number): string {
|
|
@@ -12,7 +12,6 @@ import type {
|
|
|
12
12
|
SqlMigrationRunnerSuccessValue,
|
|
13
13
|
} from '@prisma-next/family-sql/control';
|
|
14
14
|
import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
|
|
15
|
-
import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
|
|
16
15
|
import type { MigrationRunnerResult } from '@prisma-next/framework-components/control';
|
|
17
16
|
import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
|
|
18
17
|
import type { SqlControlDriverInstance, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
@@ -22,8 +21,7 @@ import { ifDefined } from '@prisma-next/utils/defined';
|
|
|
22
21
|
import type { Result } from '@prisma-next/utils/result';
|
|
23
22
|
import { notOk, ok, okVoid } from '@prisma-next/utils/result';
|
|
24
23
|
import { MARKER_TABLE_NAME } from '../control-tables';
|
|
25
|
-
import {
|
|
26
|
-
import { normalizeSqliteNativeType } from '../native-type-normalizer';
|
|
24
|
+
import { verifySqliteDatabaseSchema } from './diff-database-schema';
|
|
27
25
|
import type { SqlitePlanTargetDetails } from './planner-target-details';
|
|
28
26
|
|
|
29
27
|
export function createSqliteMigrationRunner(
|
|
@@ -92,20 +90,16 @@ class SqliteMigrationRunner implements SqlMigrationRunner<SqlitePlanTargetDetail
|
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
if (space === APP_SPACE_ID) {
|
|
95
|
-
const
|
|
93
|
+
const schemaNode = await this.family.introspect({
|
|
96
94
|
driver,
|
|
97
95
|
contract: options.destinationContract,
|
|
98
96
|
});
|
|
99
|
-
|
|
100
|
-
const schemaVerifyResult = verifySqlSchema({
|
|
97
|
+
const schemaVerifyResult = verifySqliteDatabaseSchema({
|
|
101
98
|
contract: options.destinationContract,
|
|
102
|
-
|
|
99
|
+
actualSchema: schemaNode,
|
|
103
100
|
strict: options.strictVerification ?? true,
|
|
104
|
-
context: options.context ?? {},
|
|
105
101
|
typeMetadataRegistry: this.family.typeMetadataRegistry,
|
|
106
102
|
frameworkComponents: options.frameworkComponents,
|
|
107
|
-
normalizeDefault: parseSqliteDefault,
|
|
108
|
-
normalizeNativeType: normalizeSqliteNativeType,
|
|
109
103
|
});
|
|
110
104
|
if (!schemaVerifyResult.ok) {
|
|
111
105
|
return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Contract } from '@prisma-next/contract/types';
|
|
1
2
|
import type {
|
|
2
3
|
MigrationOperationClass,
|
|
3
4
|
SqlMigrationPlanOperation,
|
|
@@ -5,9 +6,12 @@ import type {
|
|
|
5
6
|
import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
|
|
6
7
|
import { Migration as SqlMigration } from '@prisma-next/family-sql/migration';
|
|
7
8
|
import type { ControlStack } from '@prisma-next/framework-components/control';
|
|
9
|
+
import { MigrationContractViews } from '@prisma-next/migration-tools/migration';
|
|
10
|
+
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
8
11
|
import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
|
|
9
12
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
10
13
|
import { errorSqliteMigrationStackMissing } from '../errors';
|
|
14
|
+
import { SqliteContractView } from '../sqlite-contract-view';
|
|
11
15
|
import {
|
|
12
16
|
AddColumnCall,
|
|
13
17
|
CreateIndexCall,
|
|
@@ -34,8 +38,19 @@ type Op = SqlMigrationPlanOperation<SqlitePlanTargetDetails>;
|
|
|
34
38
|
* forward to the corresponding `*Call` with that stored adapter, so user
|
|
35
39
|
* migrations can write `this.createTable({...})` without threading the adapter
|
|
36
40
|
* through every call.
|
|
41
|
+
*
|
|
42
|
+
* Binds the framework base's `Start` / `End` contract generics so a subclass
|
|
43
|
+
* that assigns its `start-contract.json` / `end-contract.json` imports gets
|
|
44
|
+
* fully-typed view accessors: `this.endContract` is a `SqliteContractView<End>`
|
|
45
|
+
* (sole namespace unwrapped to the root — `this.endContract.table.<name>`),
|
|
46
|
+
* built lazily from the JSON fields via the shared `MigrationContractViews`
|
|
47
|
+
* helper. Mirrors `MongoMigration`'s view getters; the framework base derives
|
|
48
|
+
* `describe()` from the same JSON.
|
|
37
49
|
*/
|
|
38
|
-
export abstract class SqliteMigration
|
|
50
|
+
export abstract class SqliteMigration<
|
|
51
|
+
Start extends Contract<SqlStorage> = Contract<SqlStorage>,
|
|
52
|
+
End extends Contract<SqlStorage> = Contract<SqlStorage>,
|
|
53
|
+
> extends SqlMigration<SqlitePlanTargetDetails, 'sqlite', Start, End> {
|
|
39
54
|
readonly targetId = 'sqlite' as const;
|
|
40
55
|
|
|
41
56
|
/**
|
|
@@ -46,6 +61,15 @@ export abstract class SqliteMigration extends SqlMigration<SqlitePlanTargetDetai
|
|
|
46
61
|
*/
|
|
47
62
|
protected readonly controlAdapter: SqlControlAdapter<'sqlite'> | undefined;
|
|
48
63
|
|
|
64
|
+
#endView = new MigrationContractViews<SqliteContractView<End>>(this, 'SqliteMigration', (json) =>
|
|
65
|
+
SqliteContractView.fromJson<End>(json),
|
|
66
|
+
);
|
|
67
|
+
#startView = new MigrationContractViews<SqliteContractView<Start>>(
|
|
68
|
+
this,
|
|
69
|
+
'SqliteMigration',
|
|
70
|
+
(json) => SqliteContractView.fromJson<Start>(json),
|
|
71
|
+
);
|
|
72
|
+
|
|
49
73
|
constructor(stack?: ControlStack<'sql', 'sqlite'>) {
|
|
50
74
|
super(stack);
|
|
51
75
|
this.controlAdapter = stack?.adapter
|
|
@@ -56,6 +80,23 @@ export abstract class SqliteMigration extends SqlMigration<SqlitePlanTargetDetai
|
|
|
56
80
|
: undefined;
|
|
57
81
|
}
|
|
58
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(): SqliteContractView<End> {
|
|
89
|
+
return this.#endView.endContract;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The typed SQLite view over this migration's start-state contract, or
|
|
94
|
+
* `null` for a baseline migration (no `startContractJson`).
|
|
95
|
+
*/
|
|
96
|
+
get startContract(): SqliteContractView<Start> | null {
|
|
97
|
+
return this.#startView.startContract;
|
|
98
|
+
}
|
|
99
|
+
|
|
59
100
|
protected createTable(options: {
|
|
60
101
|
readonly table: string;
|
|
61
102
|
readonly ifNotExists?: boolean;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
2
|
import { SqlContractSerializerBase } from '@prisma-next/family-sql/ir';
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
3
|
+
import type { Namespace } from '@prisma-next/framework-components/ir';
|
|
4
|
+
import type { SqlNamespaceInput, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
5
5
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
6
|
-
import {
|
|
6
|
+
import type { JsonObject } from '@prisma-next/utils/json';
|
|
7
7
|
import { buildSqliteNamespace } from './sqlite-unbound-database';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -17,21 +17,48 @@ export class SqliteContractSerializer extends SqlContractSerializerBase<Contract
|
|
|
17
17
|
super(new Map());
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
protected override get defaultNamespaceId(): string {
|
|
21
|
-
return sqliteTargetDescriptorMeta.defaultNamespaceId;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
20
|
protected override hydrateSqlNamespaceEntry(
|
|
25
21
|
nsId: string,
|
|
26
|
-
raw:
|
|
27
|
-
): Namespace |
|
|
28
|
-
if (raw instanceof NamespaceBase) {
|
|
29
|
-
return raw;
|
|
30
|
-
}
|
|
22
|
+
raw: Record<string, unknown>,
|
|
23
|
+
): Namespace | SqlNamespaceInput {
|
|
31
24
|
const hydrated = blindCast<
|
|
32
|
-
|
|
33
|
-
'
|
|
25
|
+
SqlNamespaceInput,
|
|
26
|
+
'raw is always plain JSON, so super.hydrateSqlNamespaceEntry returns SqlNamespaceInput'
|
|
34
27
|
>(super.hydrateSqlNamespaceEntry(nsId, raw));
|
|
35
28
|
return buildSqliteNamespace(hydrated);
|
|
36
29
|
}
|
|
30
|
+
|
|
31
|
+
override serializeContract(contract: Contract<SqlStorage>): JsonObject {
|
|
32
|
+
const { storage, ...rest } = contract;
|
|
33
|
+
const namespacesJson: Record<string, JsonObject> = {};
|
|
34
|
+
for (const [nsId, ns] of Object.entries(storage.namespaces)) {
|
|
35
|
+
namespacesJson[nsId] = {
|
|
36
|
+
id: ns.id,
|
|
37
|
+
entries: {
|
|
38
|
+
table: blindCast<
|
|
39
|
+
JsonObject,
|
|
40
|
+
'JSON.parse(JSON.stringify(...)) strips class methods; result is a plain JsonObject'
|
|
41
|
+
>(JSON.parse(JSON.stringify(ns.entries.table ?? {}))),
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return blindCast<
|
|
46
|
+
JsonObject,
|
|
47
|
+
'rest + storage are serialized plain values; spread preserves JSON-clean contract envelope'
|
|
48
|
+
>({
|
|
49
|
+
...rest,
|
|
50
|
+
storage: {
|
|
51
|
+
storageHash: String(storage.storageHash),
|
|
52
|
+
namespaces: namespacesJson,
|
|
53
|
+
...(storage.types !== undefined
|
|
54
|
+
? {
|
|
55
|
+
types: blindCast<
|
|
56
|
+
JsonObject,
|
|
57
|
+
'JSON.parse(JSON.stringify(...)) strips class methods; result is plain JsonObject'
|
|
58
|
+
>(JSON.parse(JSON.stringify(storage.types))),
|
|
59
|
+
}
|
|
60
|
+
: {}),
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
37
64
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
+
import {
|
|
3
|
+
buildSqlSingleNamespaceView,
|
|
4
|
+
type SqlSingleNamespaceView,
|
|
5
|
+
} from '@prisma-next/sql-contract/contract-view';
|
|
6
|
+
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
7
|
+
import { SqliteContractSerializer } from './sqlite-contract-serializer';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A SQLite contract view: the deserialized contract intersected with by-name
|
|
11
|
+
* accessors. It is substitutable for `Contract` (carries `storage`, `domain`,
|
|
12
|
+
* …) and also exposes the single default namespace unwrapped with the SQL
|
|
13
|
+
* built-in kinds promoted:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* const view = SqliteContractView.fromJson<Contract>(contractJson);
|
|
17
|
+
* view.table.users // typed table leaf
|
|
18
|
+
* view.entries.policy.X // pack-contributed kind (singular key)
|
|
19
|
+
* view.storage // the full contract is still present
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* SQLite has `sql.enums: false`, so it never emits `valueSet` entries; the
|
|
23
|
+
* `valueSet` slot is therefore an empty map.
|
|
24
|
+
*/
|
|
25
|
+
export type SqliteContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> =
|
|
26
|
+
SqlSingleNamespaceView<TContract>;
|
|
27
|
+
|
|
28
|
+
export const SqliteContractView = {
|
|
29
|
+
/** Wrap an already-deserialized SQLite contract in a view. */
|
|
30
|
+
from<TContract extends Contract<SqlStorage>>(contract: TContract): SqliteContractView<TContract> {
|
|
31
|
+
return buildSqlSingleNamespaceView(contract);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
/** Deserialize a SQLite contract JSON envelope and wrap it in a view. */
|
|
35
|
+
fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage>>(
|
|
36
|
+
json: unknown,
|
|
37
|
+
): SqliteContractView<TContract> {
|
|
38
|
+
const contract = new SqliteContractSerializer().deserializeContract<TContract>(json);
|
|
39
|
+
return buildSqlSingleNamespaceView(contract);
|
|
40
|
+
},
|
|
41
|
+
};
|