@prisma-next/family-sql 0.14.0-dev.49 → 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/{control-adapter-DHYFuOBy.d.mts → control-adapter-BVOj4gXI.d.mts} +34 -5
- package/dist/control-adapter-BVOj4gXI.d.mts.map +1 -0
- package/dist/control-adapter.d.mts +1 -1
- package/dist/control.d.mts +65 -50
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +308 -56
- package/dist/control.mjs.map +1 -1
- package/dist/diff.d.mts +141 -30
- package/dist/diff.d.mts.map +1 -1
- package/dist/diff.mjs +155 -1384
- package/dist/diff.mjs.map +1 -1
- package/dist/ir.d.mts +5 -5
- package/dist/ir.d.mts.map +1 -1
- package/dist/ir.mjs +2 -2
- package/dist/ir.mjs.map +1 -1
- package/dist/migration.d.mts +1 -1
- package/dist/schema-differ-DnoopSXm.d.mts +45 -0
- package/dist/schema-differ-DnoopSXm.d.mts.map +1 -0
- package/dist/schema-verify-W3r631Jh.mjs +226 -0
- package/dist/schema-verify-W3r631Jh.mjs.map +1 -0
- package/dist/{sql-contract-serializer-DwUSJ4PO.mjs → sql-contract-serializer-C75cfMSS.mjs} +2 -2
- package/dist/{sql-contract-serializer-DwUSJ4PO.mjs.map → sql-contract-serializer-C75cfMSS.mjs.map} +1 -1
- package/dist/{types-DBxrwN1d.d.mts → types-BW7pzb2j.d.mts} +24 -15
- package/dist/types-BW7pzb2j.d.mts.map +1 -0
- package/package.json +21 -21
- package/src/core/control-instance.ts +99 -80
- package/src/core/control-target-descriptor.ts +29 -14
- package/src/core/diff/diff-tree-normalization.ts +211 -0
- package/src/core/diff/schema-verify.ts +324 -0
- package/src/core/diff/sql-schema-diff.ts +40 -1466
- package/src/core/diff/verifier-disposition.ts +14 -42
- package/src/core/ir/sql-schema-verifier-base.ts +5 -5
- package/src/core/migrations/contract-to-schema-ir.ts +63 -20
- package/src/core/migrations/native-type-expander.ts +28 -0
- package/src/core/migrations/schema-differ.ts +30 -29
- package/src/core/migrations/types.ts +23 -14
- package/src/exports/control.ts +6 -0
- package/src/exports/diff.ts +28 -8
- package/dist/contract-to-schema-ir-S-evq8E6.mjs +0 -264
- package/dist/contract-to-schema-ir-S-evq8E6.mjs.map +0 -1
- package/dist/control-adapter-DHYFuOBy.d.mts.map +0 -1
- package/dist/sql-schema-diff-6z36dZt6.d.mts +0 -105
- package/dist/sql-schema-diff-6z36dZt6.d.mts.map +0 -1
- package/dist/types-DBxrwN1d.d.mts.map +0 -1
- package/src/core/diff/control-verify-emit.ts +0 -46
- package/src/core/diff/verify-helpers.ts +0 -832
|
@@ -1,58 +1,30 @@
|
|
|
1
1
|
import type { ControlPolicy } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
|
-
|
|
3
|
+
SchemaDiffIssue,
|
|
4
4
|
VerifierIssueCategory,
|
|
5
5
|
VerifierOutcome,
|
|
6
6
|
} from '@prisma-next/framework-components/control';
|
|
7
7
|
import { dispositionForCategory } from '@prisma-next/framework-components/control';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Classifies
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Classifies a codec `verifyType` hook finding into the target-neutral
|
|
11
|
+
* categories the framework grades. A storage type is a named type instance
|
|
12
|
+
* (e.g. a native enum); the only shape divergence it can carry is a change
|
|
13
|
+
* to its value set, so a paired mismatch always classifies as `valueDrift`.
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return 'extraNestedElement';
|
|
19
|
-
case 'extra_primary_key':
|
|
20
|
-
case 'extra_foreign_key':
|
|
21
|
-
case 'extra_unique_constraint':
|
|
22
|
-
case 'extra_index':
|
|
23
|
-
case 'extra_validator':
|
|
24
|
-
case 'extra_default':
|
|
25
|
-
return 'extraAuxiliary';
|
|
26
|
-
case 'extra_table':
|
|
27
|
-
return 'extraTopLevelObject';
|
|
28
|
-
case 'missing_schema':
|
|
29
|
-
case 'missing_table':
|
|
30
|
-
case 'missing_column':
|
|
31
|
-
case 'type_missing':
|
|
32
|
-
case 'default_missing':
|
|
33
|
-
return 'declaredMissing';
|
|
34
|
-
case 'type_values_mismatch':
|
|
35
|
-
case 'enum_values_changed':
|
|
36
|
-
case 'check_mismatch':
|
|
37
|
-
return 'valueDrift';
|
|
38
|
-
case 'type_mismatch':
|
|
39
|
-
case 'nullability_mismatch':
|
|
40
|
-
case 'primary_key_mismatch':
|
|
41
|
-
case 'foreign_key_mismatch':
|
|
42
|
-
case 'unique_constraint_mismatch':
|
|
43
|
-
case 'index_mismatch':
|
|
44
|
-
case 'default_mismatch':
|
|
45
|
-
return 'declaredIncompatible';
|
|
46
|
-
case 'check_missing':
|
|
47
|
-
return 'declaredMissing';
|
|
48
|
-
case 'check_removed':
|
|
49
|
-
return 'extraAuxiliary';
|
|
15
|
+
export function classifyStorageTypeDiffIssue(issue: SchemaDiffIssue): VerifierIssueCategory {
|
|
16
|
+
if (issue.reason === 'not-found') {
|
|
17
|
+
return 'declaredMissing';
|
|
50
18
|
}
|
|
19
|
+
if (issue.reason === 'not-expected') {
|
|
20
|
+
return 'extraAuxiliary';
|
|
21
|
+
}
|
|
22
|
+
return 'valueDrift';
|
|
51
23
|
}
|
|
52
24
|
|
|
53
25
|
export function verifierDisposition(
|
|
54
26
|
controlPolicy: ControlPolicy,
|
|
55
|
-
|
|
27
|
+
issue: SchemaDiffIssue,
|
|
56
28
|
): VerifierOutcome {
|
|
57
|
-
return dispositionForCategory(controlPolicy,
|
|
29
|
+
return dispositionForCategory(controlPolicy, classifyStorageTypeDiffIssue(issue));
|
|
58
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
2
|
+
SchemaDiffIssue,
|
|
3
3
|
SchemaVerifier,
|
|
4
4
|
SchemaVerifyOptions,
|
|
5
5
|
SchemaVerifyResult,
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
* SQL family `SchemaVerifier` abstract base. Centralises the SQL-shared
|
|
10
10
|
* walk (table-by-table + column-by-column matching keyed by
|
|
11
11
|
* `(namespace.id, name)`, FK / unique / index comparisons via the
|
|
12
|
-
*
|
|
12
|
+
* shared satisfaction helpers in `sql-schema-diff.ts`) and exposes a protected hook
|
|
13
13
|
* for target extensions (Postgres functions, RLS policies, future
|
|
14
14
|
* target-only kinds).
|
|
15
15
|
*
|
|
@@ -29,7 +29,7 @@ export abstract class SqlSchemaVerifierBase<TContract, TSchema>
|
|
|
29
29
|
implements SchemaVerifier<TContract, TSchema>
|
|
30
30
|
{
|
|
31
31
|
verifySchema(options: SchemaVerifyOptions<TContract, TSchema>): SchemaVerifyResult {
|
|
32
|
-
const issues:
|
|
32
|
+
const issues: SchemaDiffIssue[] = [];
|
|
33
33
|
issues.push(...this.verifyCommonSqlSchema(options));
|
|
34
34
|
issues.push(...this.verifyTargetExtensions(options));
|
|
35
35
|
return { ok: issues.length === 0, issues };
|
|
@@ -43,7 +43,7 @@ export abstract class SqlSchemaVerifierBase<TContract, TSchema>
|
|
|
43
43
|
*/
|
|
44
44
|
protected abstract verifyCommonSqlSchema(
|
|
45
45
|
options: SchemaVerifyOptions<TContract, TSchema>,
|
|
46
|
-
): readonly
|
|
46
|
+
): readonly SchemaDiffIssue[];
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Target-specific extensions — e.g. Postgres functions, future RLS
|
|
@@ -52,5 +52,5 @@ export abstract class SqlSchemaVerifierBase<TContract, TSchema>
|
|
|
52
52
|
*/
|
|
53
53
|
protected abstract verifyTargetExtensions(
|
|
54
54
|
options: SchemaVerifyOptions<TContract, TSchema>,
|
|
55
|
-
): readonly
|
|
55
|
+
): readonly SchemaDiffIssue[];
|
|
56
56
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColumnDefault, Contract, JsonValue } from '@prisma-next/contract/types';
|
|
2
|
+
import type { CodecRef } from '@prisma-next/framework-components/codec';
|
|
2
3
|
import type { MigrationPlannerConflict } from '@prisma-next/framework-components/control';
|
|
3
4
|
import {
|
|
4
5
|
type CheckConstraint,
|
|
@@ -12,16 +13,17 @@ import {
|
|
|
12
13
|
type UniqueConstraint,
|
|
13
14
|
} from '@prisma-next/sql-contract/types';
|
|
14
15
|
import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
|
|
15
|
-
import
|
|
16
|
-
SqlAnnotations,
|
|
17
|
-
SqlCheckConstraintIRInput,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
import {
|
|
17
|
+
type SqlAnnotations,
|
|
18
|
+
type SqlCheckConstraintIRInput,
|
|
19
|
+
type SqlColumnIRInput,
|
|
20
|
+
type SqlForeignKeyIRInput,
|
|
21
|
+
type SqlIndexIRInput,
|
|
21
22
|
SqlSchemaIR,
|
|
22
23
|
SqlTableIR,
|
|
23
|
-
|
|
24
|
+
type SqlUniqueIRInput,
|
|
24
25
|
} from '@prisma-next/sql-schema-ir/types';
|
|
26
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
25
27
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -72,7 +74,7 @@ function convertColumn(
|
|
|
72
74
|
storageTypes: ResolvedStorageTypes,
|
|
73
75
|
expandNativeType: NativeTypeExpander | undefined,
|
|
74
76
|
renderDefault: DefaultRenderer | undefined,
|
|
75
|
-
):
|
|
77
|
+
): SqlColumnIRInput {
|
|
76
78
|
// Resolve `typeRef` so columns that delegate their `nativeType`/`codecId`/
|
|
77
79
|
// `typeParams` to a named `storage.types` entry expand the same way as
|
|
78
80
|
// columns that inline those fields. Without this resolution, a
|
|
@@ -98,6 +100,43 @@ function convertColumn(
|
|
|
98
100
|
'default',
|
|
99
101
|
column.default != null && renderDefault ? renderDefault(column.default, column) : undefined,
|
|
100
102
|
),
|
|
103
|
+
// Contract-derived columns are resolved by construction: the computed
|
|
104
|
+
// full native type doubles as the resolved value, and the contract's
|
|
105
|
+
// structured default is the resolved default (the introspected side
|
|
106
|
+
// stamps its normalizer's parse of the raw expression).
|
|
107
|
+
resolvedNativeType: nativeType,
|
|
108
|
+
...ifDefined('resolvedDefault', column.default ?? undefined),
|
|
109
|
+
// The column's codec identity, carried the same way the query AST
|
|
110
|
+
// carries `CodecRef` (TML-2456) — the migration planner's op-builders
|
|
111
|
+
// resolve DDL rendering from this at plan time (Decision 5), instead of
|
|
112
|
+
// reading a derivation-precomputed render payload.
|
|
113
|
+
codecRef: buildColumnCodecRef(resolved, column.many),
|
|
114
|
+
codecBaseNativeType: resolved.nativeType,
|
|
115
|
+
...(column.typeRef !== undefined ? { codecNamedType: true } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Builds the column's `CodecRef` from its resolved (post-`typeRef`) codec
|
|
121
|
+
* identity — the same construction the query AST and the migration DDL
|
|
122
|
+
* renderer already use (TML-2456, TML-2918).
|
|
123
|
+
*/
|
|
124
|
+
function buildColumnCodecRef(
|
|
125
|
+
resolved: Pick<StorageColumn, 'codecId' | 'nativeType' | 'typeParams'>,
|
|
126
|
+
many: boolean | undefined,
|
|
127
|
+
): CodecRef {
|
|
128
|
+
return {
|
|
129
|
+
codecId: resolved.codecId,
|
|
130
|
+
...ifDefined(
|
|
131
|
+
'typeParams',
|
|
132
|
+
resolved.typeParams !== undefined
|
|
133
|
+
? blindCast<
|
|
134
|
+
JsonValue,
|
|
135
|
+
'resolved.typeParams is JsonValue-shaped storage metadata; the narrowed (non-undefined) value lands in CodecRef.typeParams which is JsonValue'
|
|
136
|
+
>(resolved.typeParams)
|
|
137
|
+
: undefined,
|
|
138
|
+
),
|
|
139
|
+
...ifDefined('many', many),
|
|
101
140
|
};
|
|
102
141
|
}
|
|
103
142
|
|
|
@@ -193,22 +232,26 @@ function convertCheck(check: CheckConstraint, storage: SqlStorage): SqlCheckCons
|
|
|
193
232
|
};
|
|
194
233
|
}
|
|
195
234
|
|
|
196
|
-
function convertUnique(unique: UniqueConstraint):
|
|
235
|
+
function convertUnique(unique: UniqueConstraint): SqlUniqueIRInput {
|
|
197
236
|
return {
|
|
198
237
|
columns: unique.columns,
|
|
199
238
|
...ifDefined('name', unique.name),
|
|
200
239
|
};
|
|
201
240
|
}
|
|
202
241
|
|
|
203
|
-
function convertIndex(index: Index):
|
|
242
|
+
function convertIndex(index: Index): SqlIndexIRInput {
|
|
204
243
|
return {
|
|
205
244
|
columns: index.columns,
|
|
206
245
|
unique: false,
|
|
207
246
|
...ifDefined('name', index.name),
|
|
247
|
+
// Carried so the derived index node compares type/options against the
|
|
248
|
+
// introspected side (the legacy walk read them from the contract).
|
|
249
|
+
...ifDefined('type', index.type),
|
|
250
|
+
...ifDefined('options', index.options),
|
|
208
251
|
};
|
|
209
252
|
}
|
|
210
253
|
|
|
211
|
-
function convertForeignKey(fk: ForeignKey):
|
|
254
|
+
function convertForeignKey(fk: ForeignKey): SqlForeignKeyIRInput {
|
|
212
255
|
return {
|
|
213
256
|
columns: fk.source.columns,
|
|
214
257
|
referencedTable: fk.target.tableName,
|
|
@@ -228,7 +271,7 @@ function convertTable(
|
|
|
228
271
|
renderDefault: DefaultRenderer | undefined,
|
|
229
272
|
storage: SqlStorage,
|
|
230
273
|
): SqlTableIR {
|
|
231
|
-
const columns: Record<string,
|
|
274
|
+
const columns: Record<string, SqlColumnIRInput> = {};
|
|
232
275
|
for (const [colName, colDef] of Object.entries(table.columns)) {
|
|
233
276
|
columns[colName] = convertColumn(
|
|
234
277
|
colName,
|
|
@@ -244,7 +287,7 @@ function convertTable(
|
|
|
244
287
|
...table.uniques.map((unique) => unique.columns.join(',')),
|
|
245
288
|
...(table.primaryKey ? [table.primaryKey.columns.join(',')] : []),
|
|
246
289
|
]);
|
|
247
|
-
const fkBackingIndexes:
|
|
290
|
+
const fkBackingIndexes: SqlIndexIRInput[] = [];
|
|
248
291
|
for (const fk of table.foreignKeys) {
|
|
249
292
|
if (fk.index === false) continue;
|
|
250
293
|
const key = fk.source.columns.join(',');
|
|
@@ -262,7 +305,7 @@ function convertTable(
|
|
|
262
305
|
? table.checks.map((c) => convertCheck(c, storage))
|
|
263
306
|
: undefined;
|
|
264
307
|
|
|
265
|
-
return {
|
|
308
|
+
return new SqlTableIR({
|
|
266
309
|
name,
|
|
267
310
|
columns,
|
|
268
311
|
...ifDefined('primaryKey', table.primaryKey),
|
|
@@ -270,7 +313,7 @@ function convertTable(
|
|
|
270
313
|
uniques: table.uniques.map(convertUnique),
|
|
271
314
|
indexes: [...table.indexes.map(convertIndex), ...fkBackingIndexes],
|
|
272
315
|
...ifDefined('checks', checks),
|
|
273
|
-
};
|
|
316
|
+
});
|
|
274
317
|
}
|
|
275
318
|
|
|
276
319
|
/**
|
|
@@ -383,7 +426,7 @@ export function contractNamespaceToSchemaIR(
|
|
|
383
426
|
}
|
|
384
427
|
const namespace = storage.namespaces[namespaceId];
|
|
385
428
|
if (!namespace) {
|
|
386
|
-
return { tables: {} };
|
|
429
|
+
return new SqlSchemaIR({ tables: {} });
|
|
387
430
|
}
|
|
388
431
|
const storageTypes: ResolvedStorageTypes = { ...(storage.types ?? {}) };
|
|
389
432
|
const tables: Record<string, SqlTableIR> = {};
|
|
@@ -398,7 +441,7 @@ export function contractNamespaceToSchemaIR(
|
|
|
398
441
|
storage,
|
|
399
442
|
);
|
|
400
443
|
}
|
|
401
|
-
return { tables };
|
|
444
|
+
return new SqlSchemaIR({ tables });
|
|
402
445
|
}
|
|
403
446
|
|
|
404
447
|
export function contractToSchemaIR(
|
|
@@ -410,7 +453,7 @@ export function contractToSchemaIR(
|
|
|
410
453
|
}
|
|
411
454
|
|
|
412
455
|
if (!contract) {
|
|
413
|
-
return { tables: {} };
|
|
456
|
+
return new SqlSchemaIR({ tables: {} });
|
|
414
457
|
}
|
|
415
458
|
|
|
416
459
|
const storage = contract.storage;
|
|
@@ -442,10 +485,10 @@ export function contractToSchemaIR(
|
|
|
442
485
|
options.resolveEnumNamespaceSchema,
|
|
443
486
|
);
|
|
444
487
|
|
|
445
|
-
return {
|
|
488
|
+
return new SqlSchemaIR({
|
|
446
489
|
tables,
|
|
447
490
|
...ifDefined('annotations', annotations),
|
|
448
|
-
};
|
|
491
|
+
});
|
|
449
492
|
}
|
|
450
493
|
|
|
451
494
|
function deriveAnnotations(
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
2
|
+
import { extractCodecControlHooks } from '../assembly';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builds the codec-hook-composed `expandNativeType` callback the contract→IR
|
|
6
|
+
* derivation uses to expand parameterized native types (e.g. `character` +
|
|
7
|
+
* `{ length: 36 }` → `character(36)`). Returns `undefined` when no framework
|
|
8
|
+
* components are supplied, so callers can omit the option entirely.
|
|
9
|
+
*/
|
|
10
|
+
export function buildNativeTypeExpander(
|
|
11
|
+
frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>,
|
|
12
|
+
) {
|
|
13
|
+
if (!frameworkComponents) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const codecHooks = extractCodecControlHooks(frameworkComponents);
|
|
17
|
+
return (input: {
|
|
18
|
+
readonly nativeType: string;
|
|
19
|
+
readonly codecId?: string;
|
|
20
|
+
readonly typeParams?: Record<string, unknown>;
|
|
21
|
+
}) => {
|
|
22
|
+
if (!input.typeParams) return input.nativeType;
|
|
23
|
+
if (!input.codecId) return input.nativeType;
|
|
24
|
+
const hooks = codecHooks.get(input.codecId);
|
|
25
|
+
if (!hooks?.expandNativeType) return input.nativeType;
|
|
26
|
+
return hooks.expandNativeType(input);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -1,40 +1,41 @@
|
|
|
1
|
-
import type { Contract } from '@prisma-next/contract/types';
|
|
1
|
+
import type { Contract, ControlPolicy } from '@prisma-next/contract/types';
|
|
2
2
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
3
|
-
import type {
|
|
4
|
-
SchemaDiffer,
|
|
5
|
-
VerifyDatabaseSchemaResult,
|
|
6
|
-
} from '@prisma-next/framework-components/control';
|
|
3
|
+
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
7
4
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
8
5
|
import type { SqlSchemaIRNode } from '@prisma-next/sql-schema-ir/types';
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
8
|
+
* The full-tree node diff a SQL target produces for the family verify
|
|
9
|
+
* verdict: the target derives the expected tree from the contract, applies
|
|
10
|
+
* the pre-diff normalizations (semantic satisfaction, FK schema-segment
|
|
11
|
+
* resolution), runs the generic differ, and ownership-scopes the result.
|
|
12
|
+
* Strict gating, control-policy disposition, and the verdict itself are the
|
|
13
|
+
* family's post-diff filters over this output.
|
|
15
14
|
*/
|
|
16
|
-
export interface
|
|
15
|
+
export interface SqlSchemaDiffResult {
|
|
16
|
+
/** The full, ownership-scoped diff issue list. */
|
|
17
|
+
readonly issues: readonly SchemaDiffIssue[];
|
|
18
|
+
/**
|
|
19
|
+
* Resolves a diff issue's subject table's declared control policy directly
|
|
20
|
+
* from the contract (Decision 5's own-layer-per-concern discipline extends
|
|
21
|
+
* here too: control policy is a contract concern, resolved by the target
|
|
22
|
+
* at disposition time — never stamped on the diff node). `undefined`
|
|
23
|
+
* when the issue's path resolves to no contract table (a genuine orphan,
|
|
24
|
+
* or a non-table subject).
|
|
25
|
+
*/
|
|
26
|
+
readonly resolveControlPolicy: (issue: SchemaDiffIssue) => ControlPolicy | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The expected/actual namespace-node pairs the codec `verifyType` hooks
|
|
29
|
+
* run over — one per contract namespace with tables, paired by DDL
|
|
30
|
+
* schema; a flat target repeats its sole actual root per such namespace.
|
|
31
|
+
*/
|
|
32
|
+
readonly namespacePairs: ReadonlyArray<{ readonly actual: SqlSchemaIRNode | undefined }>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SqlSchemaDiffInput {
|
|
17
36
|
readonly contract: Contract<SqlStorage>;
|
|
18
37
|
readonly schema: SqlSchemaIRNode;
|
|
19
|
-
readonly strict: boolean;
|
|
20
|
-
readonly typeMetadataRegistry: ReadonlyMap<string, { readonly nativeType?: string }>;
|
|
21
38
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
22
39
|
}
|
|
23
40
|
|
|
24
|
-
|
|
25
|
-
* The `SchemaDiffer` a SQL target implements: the black-box comparison of the
|
|
26
|
-
* contract's expected schema against the introspected actual schema, projected
|
|
27
|
-
* to the two issue lists. How it computes them is private to the target.
|
|
28
|
-
*/
|
|
29
|
-
export type SqlDiffDatabaseSchema = SchemaDiffer<DiffDatabaseSchemaInput>['diff'];
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The same combined comparison as {@link SqlDiffDatabaseSchema}, wrapped in the
|
|
33
|
-
* verify envelope (`ok`/`summary`/`code`/`target`/`timings`) plus the
|
|
34
|
-
* pass/warn/fail tree the CLI renders. Verify calls this instead of the diff so
|
|
35
|
-
* the relational walk that produces the tree runs once per verify, not once for
|
|
36
|
-
* the diff and again for the tree.
|
|
37
|
-
*/
|
|
38
|
-
export type SqlVerifyDatabaseSchema = (
|
|
39
|
-
input: DiffDatabaseSchemaInput,
|
|
40
|
-
) => VerifyDatabaseSchemaResult;
|
|
41
|
+
export type SqlSchemaDiffFn = (input: SqlSchemaDiffInput) => SqlSchemaDiffResult;
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
ContractSpace,
|
|
5
5
|
ControlAdapterDescriptor,
|
|
6
6
|
ControlExtensionDescriptor,
|
|
7
|
-
DiffIssue,
|
|
8
7
|
MigrationOperationPolicy,
|
|
9
8
|
MigrationPlan,
|
|
10
9
|
MigrationPlannerConflict,
|
|
@@ -17,7 +16,8 @@ import type {
|
|
|
17
16
|
MigrationRunnerResult,
|
|
18
17
|
OperationContext,
|
|
19
18
|
OpFactoryCall,
|
|
20
|
-
|
|
19
|
+
SchemaDiffIssue,
|
|
20
|
+
SchemaOwnership,
|
|
21
21
|
} from '@prisma-next/framework-components/control';
|
|
22
22
|
import type { AggregateMigrationEdgeRef } from '@prisma-next/migration-tools/aggregate';
|
|
23
23
|
import type {
|
|
@@ -28,7 +28,7 @@ import type {
|
|
|
28
28
|
StorageTypeInstance,
|
|
29
29
|
} from '@prisma-next/sql-contract/types';
|
|
30
30
|
import type { SqlOperationDescriptors } from '@prisma-next/sql-operations';
|
|
31
|
-
import type {
|
|
31
|
+
import type { SqlSchemaIRNode } from '@prisma-next/sql-schema-ir/types';
|
|
32
32
|
import type { Result } from '@prisma-next/utils/result';
|
|
33
33
|
import type { SqlControlAdapter } from '../control-adapter';
|
|
34
34
|
|
|
@@ -99,20 +99,29 @@ export interface FieldEventContext {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export interface CodecControlHooks<TTargetDetails = unknown> {
|
|
102
|
+
/**
|
|
103
|
+
* `schema` is typed as the family-level `SqlSchemaIRNode` (not the concrete
|
|
104
|
+
* `SqlSchemaIR` class) because the actual value handed in is whatever
|
|
105
|
+
* per-namespace node the calling target's tree shape produces — a flat
|
|
106
|
+
* `SqlSchemaIR` for SQLite, a `PostgresNamespaceSchemaNode` for Postgres —
|
|
107
|
+
* read structurally for its `tables`/`nativeEnumTypeNames` fields. Hooks
|
|
108
|
+
* that need the concrete Postgres shape narrow via
|
|
109
|
+
* `PostgresNamespaceSchemaNode.is(schema)`.
|
|
110
|
+
*/
|
|
102
111
|
planTypeOperations?: (options: {
|
|
103
112
|
readonly typeName: string;
|
|
104
113
|
readonly typeInstance: StorageTypeInstance;
|
|
105
114
|
readonly contract: Contract<SqlStorage>;
|
|
106
|
-
readonly schema:
|
|
115
|
+
readonly schema: SqlSchemaIRNode;
|
|
107
116
|
readonly schemaName?: string;
|
|
108
117
|
readonly policy: MigrationOperationPolicy;
|
|
109
118
|
}) => StorageTypePlanResult<TTargetDetails>;
|
|
110
119
|
verifyType?: (options: {
|
|
111
120
|
readonly typeName: string;
|
|
112
121
|
readonly typeInstance: StorageTypeInstance;
|
|
113
|
-
readonly schema:
|
|
122
|
+
readonly schema: SqlSchemaIRNode;
|
|
114
123
|
readonly schemaName?: string;
|
|
115
|
-
}) => readonly
|
|
124
|
+
}) => readonly SchemaDiffIssue[];
|
|
116
125
|
introspectTypes?: (options: {
|
|
117
126
|
readonly driver: SqlControlDriverInstance<string>;
|
|
118
127
|
readonly schemaName?: string;
|
|
@@ -346,15 +355,15 @@ export interface SqlMigrationPlannerPlanOptions {
|
|
|
346
355
|
*/
|
|
347
356
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
348
357
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
358
|
+
* Ownership oracle over the whole contract-space composition (the passive
|
|
359
|
+
* aggregate). The planner asks it, per live extra node, whether any space
|
|
360
|
+
* declares that entity: a sibling-owned node is left untouched, an unowned
|
|
361
|
+
* node is a genuine extra it may drop under a destructive policy. The
|
|
362
|
+
* planner holds no list of other spaces' names — ownership lives in the
|
|
363
|
+
* aggregate; it only asks. Absent for a single-space plan handed no
|
|
364
|
+
* aggregate. See {@link SchemaOwnership}.
|
|
356
365
|
*/
|
|
357
|
-
readonly
|
|
366
|
+
readonly ownership?: SchemaOwnership;
|
|
358
367
|
}
|
|
359
368
|
|
|
360
369
|
export interface SqlMigrationPlanner<TTargetDetails> {
|
package/src/exports/control.ts
CHANGED
|
@@ -39,6 +39,7 @@ export {
|
|
|
39
39
|
} from '../core/migrations/control-policy';
|
|
40
40
|
export type { PlanFieldEventOperationsOptions } from '../core/migrations/field-event-planner';
|
|
41
41
|
export { planFieldEventOperations } from '../core/migrations/field-event-planner';
|
|
42
|
+
export { buildNativeTypeExpander } from '../core/migrations/native-type-expander';
|
|
42
43
|
export {
|
|
43
44
|
createMigrationPlan,
|
|
44
45
|
plannerFailure,
|
|
@@ -47,6 +48,11 @@ export {
|
|
|
47
48
|
runnerSuccess,
|
|
48
49
|
} from '../core/migrations/plan-helpers';
|
|
49
50
|
export { INIT_ADDITIVE_POLICY } from '../core/migrations/policies';
|
|
51
|
+
export type {
|
|
52
|
+
SqlSchemaDiffFn,
|
|
53
|
+
SqlSchemaDiffInput,
|
|
54
|
+
SqlSchemaDiffResult,
|
|
55
|
+
} from '../core/migrations/schema-differ';
|
|
50
56
|
export type {
|
|
51
57
|
CodecControlHooks,
|
|
52
58
|
CreateSqlMigrationPlanOptions,
|
package/src/exports/diff.ts
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SQL relational schema-diff exports.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The generic node differ (`buildPostgresPlanDiff` / `buildSqlitePlanDiff`)
|
|
5
|
+
* drives both plan and verify; this module surfaces the shared
|
|
6
|
+
* semantic-satisfaction predicates and verify-verdict machinery that survive
|
|
7
|
+
* it. Pure — no database connection required.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
export type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '../core/diff/
|
|
13
|
-
export {
|
|
11
|
+
SemanticSatisfactionInput,
|
|
12
|
+
SemanticSatisfactionResult,
|
|
13
|
+
} from '../core/diff/diff-tree-normalization';
|
|
14
|
+
export {
|
|
15
|
+
neutralizeFlatExpectedFkSchemas,
|
|
16
|
+
normalizeFlatActualForDiff,
|
|
17
|
+
resolveSemanticSatisfaction,
|
|
18
|
+
} from '../core/diff/diff-tree-normalization';
|
|
19
|
+
export type {
|
|
20
|
+
SqlDiffVerdict,
|
|
21
|
+
SqlDiffVerdictInput,
|
|
22
|
+
StorageTypeVerdict,
|
|
23
|
+
StorageTypeVerdictInput,
|
|
24
|
+
VerifySqlSchemaByDiffInput,
|
|
25
|
+
} from '../core/diff/schema-verify';
|
|
26
|
+
export {
|
|
27
|
+
classifyDiffSubjectGranularity,
|
|
28
|
+
classifySqlDiffIssue,
|
|
29
|
+
computeSqlDiffVerdict,
|
|
30
|
+
computeStorageTypeVerdict,
|
|
31
|
+
verifySqlSchemaByDiff,
|
|
32
|
+
} from '../core/diff/schema-verify';
|
|
33
|
+
export type { NativeTypeNormalizer } from '../core/diff/sql-schema-diff';
|
|
14
34
|
export {
|
|
15
35
|
arraysEqual,
|
|
16
36
|
isIndexSatisfied,
|
|
17
37
|
isUniqueConstraintSatisfied,
|
|
18
|
-
} from '../core/diff/
|
|
38
|
+
} from '../core/diff/sql-schema-diff';
|