@prisma-next/target-sqlite 0.14.0-dev.5 → 0.14.0-dev.50
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 +16 -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/native-type-normalizer.mjs +13 -1
- package/dist/native-type-normalizer.mjs.map +1 -0
- package/dist/{op-factory-call-DmdfD1yd.mjs → op-factory-call-D_eYsHTp.mjs} +134 -116
- package/dist/op-factory-call-D_eYsHTp.mjs.map +1 -0
- 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-DhvFrgPT.mjs +854 -0
- package/dist/planner-DhvFrgPT.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-DyRmcteq.mjs} +46 -17
- package/dist/planner-produced-sqlite-migration-DyRmcteq.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 +47 -11
- package/dist/planner.d.mts.map +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-BEwi0mUC.mjs} +34 -9
- package/dist/sqlite-contract-view-BEwi0mUC.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-D93wCdSD.mjs} +29 -2
- package/dist/sqlite-migration-D93wCdSD.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 +13 -18
- package/src/core/migrations/column-ddl-rendering.ts +177 -0
- package/src/core/migrations/diff-database-schema.ts +240 -0
- package/src/core/migrations/issue-planner.ts +359 -488
- package/src/core/migrations/op-factory-call.ts +5 -0
- package/src/core/migrations/operations/tables.ts +107 -67
- package/src/core/migrations/planner-strategies.ts +118 -137
- package/src/core/migrations/planner.ts +117 -30
- 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 +29 -14
- package/src/core/sqlite-contract-view.ts +41 -0
- package/src/core/sqlite-schema-verifier.ts +6 -3
- 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/native-type-normalizer-CiSyVmMP.mjs +0 -14
- package/dist/native-type-normalizer-CiSyVmMP.mjs.map +0 -1
- package/dist/op-factory-call-DmdfD1yd.mjs.map +0 -1
- package/dist/planner-Ciq8p_dL.mjs +0 -622
- 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
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { ColumnDefault, Contract, ControlPolicy } from '@prisma-next/contract/types';
|
|
2
|
+
import type { NativeTypeExpander, SqlSchemaDiffResult } from '@prisma-next/family-sql/control';
|
|
3
|
+
import { buildNativeTypeExpander, contractToSchemaIR } from '@prisma-next/family-sql/control';
|
|
4
|
+
import {
|
|
5
|
+
neutralizeFlatExpectedFkSchemas,
|
|
6
|
+
normalizeFlatActualForDiff,
|
|
7
|
+
verifySqlSchemaByDiff,
|
|
8
|
+
} from '@prisma-next/family-sql/diff';
|
|
9
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
10
|
+
import type {
|
|
11
|
+
SchemaDiffIssue,
|
|
12
|
+
VerifyDatabaseSchemaResult,
|
|
13
|
+
} from '@prisma-next/framework-components/control';
|
|
14
|
+
import { diffSchemas } from '@prisma-next/framework-components/control';
|
|
15
|
+
import { entityAt } from '@prisma-next/framework-components/ir';
|
|
16
|
+
import type { SqlStorage, StorageColumn, StorageTable } from '@prisma-next/sql-contract/types';
|
|
17
|
+
import type {
|
|
18
|
+
SqlColumnIRInput,
|
|
19
|
+
SqlSchemaIRInput,
|
|
20
|
+
SqlSchemaIRNode,
|
|
21
|
+
SqlTableIRInput,
|
|
22
|
+
} from '@prisma-next/sql-schema-ir/types';
|
|
23
|
+
import { relationalNodeGranularity, SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
24
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
25
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
26
|
+
import { renderDefaultLiteral } from './planner-ddl-builders';
|
|
27
|
+
|
|
28
|
+
interface SqliteDiffDatabaseSchemaInput {
|
|
29
|
+
readonly contract: Contract<SqlStorage>;
|
|
30
|
+
readonly actualSchema: SqlSchemaIRNode;
|
|
31
|
+
readonly strict: boolean;
|
|
32
|
+
readonly typeMetadataRegistry: ReadonlyMap<string, { readonly nativeType?: string }>;
|
|
33
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Renders a column default for the SQLite dialect. */
|
|
37
|
+
export function sqliteRenderDefault(def: ColumnDefault, _column: StorageColumn): string {
|
|
38
|
+
if (def.kind === 'function') {
|
|
39
|
+
if (def.expression === 'now()') {
|
|
40
|
+
return "datetime('now')";
|
|
41
|
+
}
|
|
42
|
+
return def.expression;
|
|
43
|
+
}
|
|
44
|
+
return renderDefaultLiteral(def.value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The SQLite expected-side projection: contract → flat relational schema IR.
|
|
49
|
+
*
|
|
50
|
+
* `extras` thread the plan-time derivation input: the native-type expander,
|
|
51
|
+
* so the expected side carries resolved native types (like the verify
|
|
52
|
+
* side). Every expected column also carries its `codecRef` unconditionally
|
|
53
|
+
* (Decision 5) — the planner's op-builders resolve DDL rendering from it at
|
|
54
|
+
* plan time, so no separate render stamper is threaded here.
|
|
55
|
+
*/
|
|
56
|
+
export function sqliteContractToSchema(
|
|
57
|
+
contract: Contract<SqlStorage> | null,
|
|
58
|
+
extras?: {
|
|
59
|
+
readonly expandNativeType?: NativeTypeExpander;
|
|
60
|
+
},
|
|
61
|
+
): SqlSchemaIR {
|
|
62
|
+
return contractToSchemaIR(contract, {
|
|
63
|
+
annotationNamespace: 'sqlite',
|
|
64
|
+
renderDefault: sqliteRenderDefault,
|
|
65
|
+
...ifDefined('expandNativeType', extras?.expandNativeType),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The SQLite schema verify: the full-tree node-diff verdict wrapped in the
|
|
71
|
+
* issue-based result envelope. Used by the runner's post-apply check; the
|
|
72
|
+
* family `verifySchema` runs the same composition via the descriptor hook.
|
|
73
|
+
*/
|
|
74
|
+
export function verifySqliteDatabaseSchema(
|
|
75
|
+
input: SqliteDiffDatabaseSchemaInput,
|
|
76
|
+
): VerifyDatabaseSchemaResult {
|
|
77
|
+
return verifySqlSchemaByDiff({
|
|
78
|
+
contract: input.contract,
|
|
79
|
+
schema: input.actualSchema,
|
|
80
|
+
strict: input.strict,
|
|
81
|
+
frameworkComponents: input.frameworkComponents,
|
|
82
|
+
diffSchema: diffSqliteSchema,
|
|
83
|
+
granularityOf: relationalNodeGranularity,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Resolves a verdict-diff issue's subject table's declared control policy
|
|
89
|
+
* directly from the contract. SQLite's expected tree is flat, so the issue
|
|
90
|
+
* path carries no namespace segment — `path[1]` is the table name (`path[0]`
|
|
91
|
+
* is the tree root's own id); every contract namespace is searched for that
|
|
92
|
+
* table name (table names are globally unique in the flat tree — duplicates
|
|
93
|
+
* across namespaces are rejected earlier, at `contractToSchemaIR`).
|
|
94
|
+
*/
|
|
95
|
+
function resolveControlPolicy(
|
|
96
|
+
issue: SchemaDiffIssue,
|
|
97
|
+
contract: Contract<SqlStorage>,
|
|
98
|
+
): ControlPolicy | undefined {
|
|
99
|
+
const tableName = issue.path[1];
|
|
100
|
+
if (tableName === undefined) return undefined;
|
|
101
|
+
for (const namespaceId of Object.keys(contract.storage.namespaces)) {
|
|
102
|
+
const table = entityAt<StorageTable>(contract.storage, {
|
|
103
|
+
namespaceId,
|
|
104
|
+
entityKind: 'table',
|
|
105
|
+
entityName: tableName,
|
|
106
|
+
});
|
|
107
|
+
if (table !== undefined) return table.control;
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The SQLite full-tree node diff for the family verify verdict: derive the
|
|
114
|
+
* expected flat tree with resolved leaf values (expander threaded so
|
|
115
|
+
* parameterized types compare expanded), neutralize the FK schema segment
|
|
116
|
+
* (single-schema target — introspection stamps none), normalize the actual
|
|
117
|
+
* tree for semantic satisfaction, and run the generic differ. Flat targets
|
|
118
|
+
* need no ownership scoping. The codec `verifyType` hooks run once per
|
|
119
|
+
* contract namespace with tables, each against the sole flat actual root —
|
|
120
|
+
* exactly the legacy per-namespace pairing.
|
|
121
|
+
*/
|
|
122
|
+
export function diffSqliteSchema(input: {
|
|
123
|
+
readonly contract: Contract<SqlStorage>;
|
|
124
|
+
readonly schema: SqlSchemaIRNode;
|
|
125
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
126
|
+
}): SqlSchemaDiffResult {
|
|
127
|
+
const expandNativeType = buildNativeTypeExpander(input.frameworkComponents);
|
|
128
|
+
const expected = neutralizeFlatExpectedFkSchemas(
|
|
129
|
+
contractToSchemaIR(input.contract, {
|
|
130
|
+
annotationNamespace: 'sqlite',
|
|
131
|
+
renderDefault: sqliteRenderDefault,
|
|
132
|
+
...ifDefined('expandNativeType', expandNativeType),
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
135
|
+
const actual =
|
|
136
|
+
input.schema instanceof SqlSchemaIR
|
|
137
|
+
? input.schema
|
|
138
|
+
: blindCast<
|
|
139
|
+
SqlSchemaIR,
|
|
140
|
+
'the SQLite introspection adapter always produces a flat SqlSchemaIR root'
|
|
141
|
+
>(input.schema);
|
|
142
|
+
const normalizedActual = normalizeFlatActualForDiff(expected, actual);
|
|
143
|
+
const issues = diffSchemas(expected, normalizedActual);
|
|
144
|
+
const namespacesWithTables = Object.values(input.contract.storage.namespaces).filter(
|
|
145
|
+
(ns) => Object.keys(ns.entries.table ?? {}).length > 0,
|
|
146
|
+
);
|
|
147
|
+
return {
|
|
148
|
+
issues,
|
|
149
|
+
resolveControlPolicy: (issue) => resolveControlPolicy(issue, input.contract),
|
|
150
|
+
namespacePairs: namespacesWithTables.map(() => ({ actual })),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface SqlitePlanDiff {
|
|
155
|
+
/** The desired ("end") tree — resolved leaf values, incl. `codecRef`, on every column. */
|
|
156
|
+
readonly expected: SqlSchemaIR;
|
|
157
|
+
/** The live ("start") tree, normalized for semantic satisfaction against `expected`. */
|
|
158
|
+
readonly actual: SqlSchemaIR;
|
|
159
|
+
readonly issues: readonly SchemaDiffIssue[];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The SQLite planner's diff input: the same tree-building
|
|
164
|
+
* `diffSqliteSchema` uses (expander threaded, FK schema segment
|
|
165
|
+
* neutralized, actual tree normalized for semantic satisfaction). One differ
|
|
166
|
+
* drives both verify and plan; this is the plan-side derivation — column DDL
|
|
167
|
+
* resolves from each expected column's `codecRef` at plan time
|
|
168
|
+
* (`column-ddl-rendering.ts`), so no separate render stamping happens here.
|
|
169
|
+
*/
|
|
170
|
+
export function buildSqlitePlanDiff(input: {
|
|
171
|
+
readonly contract: Contract<SqlStorage>;
|
|
172
|
+
readonly actualSchema: SqlSchemaIRNode;
|
|
173
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
174
|
+
}): SqlitePlanDiff {
|
|
175
|
+
const expandNativeType = buildNativeTypeExpander(input.frameworkComponents);
|
|
176
|
+
const expected = neutralizeFlatExpectedFkSchemas(
|
|
177
|
+
sqliteContractToSchema(input.contract, {
|
|
178
|
+
...ifDefined('expandNativeType', expandNativeType),
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
181
|
+
// The differ dispatches polymorphically (`.isEqualTo()` / `.children()`), so
|
|
182
|
+
// the actual tree must be genuine `SqlSchemaIR`/`SqlTableIR`/`SqlColumnIR`
|
|
183
|
+
// instances, not plain data shaped like them. `new SqlSchemaIR(...)`
|
|
184
|
+
// normalizes either input uniformly (an already-real tree passes through
|
|
185
|
+
// untouched — its nested values are already instances) and is a no-op
|
|
186
|
+
// rebuild in the common (real-instance) case, so this is always safe to run.
|
|
187
|
+
const actualRaw = new SqlSchemaIR(withRecordKeyNames(input.actualSchema));
|
|
188
|
+
const actual = normalizeFlatActualForDiff(expected, actualRaw);
|
|
189
|
+
const issues = diffSchemas(expected, actual);
|
|
190
|
+
return { expected, actual, issues };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Every schema-tree builder in this codebase derives a table's / column's
|
|
195
|
+
* `name` from the record key it's stored under (`contractToSchemaIR`,
|
|
196
|
+
* the SQLite introspection adapter) rather than trusting a redundant
|
|
197
|
+
* embedded field — the record key IS the identity. Mirrors that discipline
|
|
198
|
+
* for the actual/live tree before construction, so `SqlTableIR.id` /
|
|
199
|
+
* `SqlColumnIR.id` (both derived from `.name`) are always correct without
|
|
200
|
+
* requiring every caller to duplicate the key onto the value. A no-op for a
|
|
201
|
+
* tree that already carries matching names (the real introspection adapter
|
|
202
|
+
* always does).
|
|
203
|
+
*/
|
|
204
|
+
function withRecordKeyNames(actualSchema: SqlSchemaIRNode): SqlSchemaIRInput {
|
|
205
|
+
const raw = blindCast<
|
|
206
|
+
{ readonly tables?: Readonly<Record<string, unknown>> },
|
|
207
|
+
'the SQLite introspection adapter always produces a flat, tables-keyed root'
|
|
208
|
+
>(actualSchema);
|
|
209
|
+
const tables: Record<string, SqlTableIRInput> = {};
|
|
210
|
+
for (const [tableName, table] of Object.entries(raw.tables ?? {})) {
|
|
211
|
+
const rawTable = blindCast<
|
|
212
|
+
Omit<SqlTableIRInput, 'name' | 'columns'>,
|
|
213
|
+
'every table value in a tables record is SqlTableIR(Input)-shaped'
|
|
214
|
+
>(table);
|
|
215
|
+
const columns: Record<string, SqlColumnIRInput> = {};
|
|
216
|
+
for (const [columnName, column] of Object.entries(
|
|
217
|
+
blindCast<
|
|
218
|
+
{ readonly columns?: Readonly<Record<string, unknown>> },
|
|
219
|
+
'every SqlTableIR(Input) carries a columns record keyed by column name'
|
|
220
|
+
>(table).columns ?? {},
|
|
221
|
+
)) {
|
|
222
|
+
columns[columnName] = {
|
|
223
|
+
...blindCast<
|
|
224
|
+
SqlColumnIRInput,
|
|
225
|
+
'every column value in a columns record is SqlColumnIR(Input)-shaped'
|
|
226
|
+
>(column),
|
|
227
|
+
name: columnName,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
tables[tableName] = {
|
|
231
|
+
...rawTable,
|
|
232
|
+
name: tableName,
|
|
233
|
+
columns,
|
|
234
|
+
foreignKeys: rawTable.foreignKeys ?? [],
|
|
235
|
+
uniques: rawTable.uniques ?? [],
|
|
236
|
+
indexes: rawTable.indexes ?? [],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return { tables };
|
|
240
|
+
}
|