@prisma-next/family-sql 0.5.0-dev.9 → 0.5.0
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/README.md +2 -2
- package/dist/{authoring-type-constructors-BAR65pSK.mjs → authoring-type-constructors-F4JpCJl7.mjs} +14 -15
- package/dist/authoring-type-constructors-F4JpCJl7.mjs.map +1 -0
- package/dist/control-adapter.d.mts +26 -2
- package/dist/control-adapter.d.mts.map +1 -1
- package/dist/control-adapter.mjs +1 -1
- package/dist/control.d.mts +122 -40
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +1169 -24
- package/dist/control.mjs.map +1 -1
- package/dist/migration.d.mts +22 -24
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +25 -24
- package/dist/migration.mjs.map +1 -1
- package/dist/pack.d.mts +35 -23
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +3 -5
- package/dist/pack.mjs.map +1 -1
- package/dist/runtime.d.mts +19 -2
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +26 -4
- package/dist/runtime.mjs.map +1 -1
- package/dist/schema-verify.d.mts +2 -4
- package/dist/schema-verify.d.mts.map +1 -1
- package/dist/schema-verify.mjs +2 -3
- package/dist/test-utils.d.mts +2 -2
- package/dist/test-utils.mjs +2 -3
- package/dist/timestamp-now-generator-BWp8S2sa.mjs +86 -0
- package/dist/timestamp-now-generator-BWp8S2sa.mjs.map +1 -0
- package/dist/{types-C6K4mxDM.d.mts → types-BQBbcXg3.d.mts} +206 -28
- package/dist/types-BQBbcXg3.d.mts.map +1 -0
- package/dist/verify-pRYxnpiG.mjs +81 -0
- package/dist/verify-pRYxnpiG.mjs.map +1 -0
- package/dist/{verify-sql-schema-BBhkqEDo.d.mts → verify-sql-schema-CPHiuYHR.d.mts} +2 -3
- package/dist/verify-sql-schema-CPHiuYHR.d.mts.map +1 -0
- package/dist/{verify-sql-schema-Ovz7RXR5.mjs → verify-sql-schema-r1-2apHI.mjs} +18 -9
- package/dist/verify-sql-schema-r1-2apHI.mjs.map +1 -0
- package/dist/verify.d.mts +16 -21
- package/dist/verify.d.mts.map +1 -1
- package/dist/verify.mjs +2 -3
- package/package.json +23 -21
- package/src/core/authoring-field-presets.ts +35 -23
- package/src/core/control-adapter.ts +32 -0
- package/src/core/control-descriptor.ts +2 -1
- package/src/core/control-instance.ts +116 -18
- package/src/core/migrations/field-event-planner.ts +192 -0
- package/src/core/migrations/plan-helpers.ts +4 -0
- package/src/core/migrations/types.ts +200 -25
- package/src/core/operation-preview.ts +62 -0
- package/src/core/psl-contract-infer/default-mapping.ts +56 -0
- package/src/core/psl-contract-infer/name-transforms.ts +178 -0
- package/src/core/psl-contract-infer/postgres-default-mapping.ts +16 -0
- package/src/core/psl-contract-infer/postgres-type-map.ts +165 -0
- package/src/core/psl-contract-infer/printer-config.ts +55 -0
- package/src/core/psl-contract-infer/raw-default-parser.ts +91 -0
- package/src/core/psl-contract-infer/relation-inference.ts +196 -0
- package/src/core/psl-contract-infer/sql-schema-ir-to-psl-ast.ts +832 -0
- package/src/core/schema-verify/verify-helpers.ts +46 -6
- package/src/core/sql-migration.ts +25 -23
- package/src/core/timestamp-now-generator.ts +74 -0
- package/src/core/timestamp-now-runtime-generator.ts +24 -0
- package/src/core/verify.ts +46 -108
- package/src/exports/control.ts +11 -1
- package/src/exports/runtime.ts +2 -0
- package/src/exports/test-utils.ts +0 -1
- package/src/exports/verify.ts +1 -1
- package/dist/authoring-type-constructors-BAR65pSK.mjs.map +0 -1
- package/dist/types-C6K4mxDM.d.mts.map +0 -1
- package/dist/verify-4GshvY4p.mjs +0 -122
- package/dist/verify-4GshvY4p.mjs.map +0 -1
- package/dist/verify-sql-schema-BBhkqEDo.d.mts.map +0 -1
- package/dist/verify-sql-schema-Ovz7RXR5.mjs.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { ControlAdapterDescriptor, ControlDriverInstance, ControlExtensionDescriptor, ControlFamilyInstance, ControlStack,
|
|
1
|
+
import { ContractSpace, ControlAdapterDescriptor, ControlDriverInstance, ControlExtensionDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlannerConflict, MigrationPlannerFailureResult, MigrationPlannerSuccessResult, MigrationRunnerExecutionChecks, MigrationRunnerFailure, MigrationRunnerSuccessValue, OpFactoryCall, OperationContext, OperationPreview, OperationPreviewCapable, PslContractInferCapable, SchemaIssue, SchemaViewCapable, SignDatabaseResult, VerifyDatabaseResult, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
|
|
2
2
|
import { Result } from "@prisma-next/utils/result";
|
|
3
|
-
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
4
3
|
import { Contract } from "@prisma-next/contract/types";
|
|
4
|
+
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
5
5
|
import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
|
|
6
|
-
import { SqlStorage, StorageTypeInstance } from "@prisma-next/sql-contract/types";
|
|
6
|
+
import { SqlStorage, StorageColumn, StorageTable, StorageTypeInstance } from "@prisma-next/sql-contract/types";
|
|
7
7
|
import { TypesImportSpec } from "@prisma-next/framework-components/emission";
|
|
8
|
-
import {
|
|
8
|
+
import { PslDocumentAst } from "@prisma-next/framework-components/psl-ast";
|
|
9
|
+
import { SqlOperationDescriptors } from "@prisma-next/sql-operations";
|
|
9
10
|
|
|
10
11
|
//#region src/core/control-instance.d.ts
|
|
11
12
|
interface SqlTypeMetadata {
|
|
@@ -17,7 +18,6 @@ interface SqlTypeMetadata {
|
|
|
17
18
|
type SqlTypeMetadataRegistry = Map<string, SqlTypeMetadata>;
|
|
18
19
|
interface SqlFamilyInstanceState {
|
|
19
20
|
readonly codecTypeImports: ReadonlyArray<TypesImportSpec>;
|
|
20
|
-
readonly operationTypeImports: ReadonlyArray<TypesImportSpec>;
|
|
21
21
|
readonly extensionIds: ReadonlyArray<string>;
|
|
22
22
|
readonly typeMetadataRegistry: SqlTypeMetadataRegistry;
|
|
23
23
|
}
|
|
@@ -32,7 +32,7 @@ interface SchemaVerifyOptions {
|
|
|
32
32
|
*/
|
|
33
33
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
34
34
|
}
|
|
35
|
-
interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchemaIR>, SchemaViewCapable<SqlSchemaIR>, SqlFamilyInstanceState {
|
|
35
|
+
interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchemaIR>, SchemaViewCapable<SqlSchemaIR>, PslContractInferCapable<SqlSchemaIR>, OperationPreviewCapable, SqlFamilyInstanceState {
|
|
36
36
|
validateContract(contractJson: unknown): Contract;
|
|
37
37
|
verify(options: {
|
|
38
38
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
@@ -42,6 +42,21 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchem
|
|
|
42
42
|
readonly configPath?: string;
|
|
43
43
|
}): Promise<VerifyDatabaseResult>;
|
|
44
44
|
schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Verify a contract against an already-introspected schema slice.
|
|
47
|
+
*
|
|
48
|
+
* Used by the aggregate verifier to invoke per-member verification
|
|
49
|
+
* with the live schema pre-projected to the member's claimed slice
|
|
50
|
+
* via `projectSchemaToSpace`. Closes F23 — without per-member
|
|
51
|
+
* pre-projection, single-contract verifiers see other-space tables
|
|
52
|
+
* as `extras`.
|
|
53
|
+
*/
|
|
54
|
+
schemaVerifyAgainstSchema(options: {
|
|
55
|
+
readonly contract: unknown;
|
|
56
|
+
readonly schema: SqlSchemaIR;
|
|
57
|
+
readonly strict: boolean;
|
|
58
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
59
|
+
}): VerifyDatabaseSchemaResult;
|
|
45
60
|
sign(options: {
|
|
46
61
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
47
62
|
readonly contract: unknown;
|
|
@@ -52,6 +67,8 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchem
|
|
|
52
67
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
53
68
|
readonly contract?: unknown;
|
|
54
69
|
}): Promise<SqlSchemaIR>;
|
|
70
|
+
inferPslContract(schemaIR: SqlSchemaIR): PslDocumentAst;
|
|
71
|
+
toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview;
|
|
55
72
|
}
|
|
56
73
|
//#endregion
|
|
57
74
|
//#region src/core/migrations/types.d.ts
|
|
@@ -92,6 +109,39 @@ interface ResolveIdentityValueInput {
|
|
|
92
109
|
readonly codecId?: string;
|
|
93
110
|
readonly typeParams?: Record<string, unknown>;
|
|
94
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Per-field lifecycle event a codec hook can react to.
|
|
114
|
+
*
|
|
115
|
+
* Fired during app-space migration emission as the SQL family diffs the
|
|
116
|
+
* prior contract against the new contract.
|
|
117
|
+
*
|
|
118
|
+
* - `'added'` — the field is present in the new contract but not the prior.
|
|
119
|
+
* - `'dropped'` — the field is present in the prior contract but not the new.
|
|
120
|
+
* - `'altered'` — the field is present in both and any property other than
|
|
121
|
+
* `codecId` differs. Codec-id changes are a v1 non-goal:
|
|
122
|
+
* when only `codecId` differs, no `'altered'` event fires.
|
|
123
|
+
*/
|
|
124
|
+
type FieldEvent = 'added' | 'dropped' | 'altered';
|
|
125
|
+
/**
|
|
126
|
+
* Context passed to {@link CodecControlHooks.onFieldEvent}.
|
|
127
|
+
*
|
|
128
|
+
* `tableName` and `fieldName` are always populated; `priorTable` /
|
|
129
|
+
* `priorField` carry the prior contract's view of the table and column
|
|
130
|
+
* (present for `'dropped'` and `'altered'`); `newTable` / `newField`
|
|
131
|
+
* carry the new contract's view (present for `'added'` and `'altered'`).
|
|
132
|
+
*
|
|
133
|
+
* The hook only ever receives app-space contract IR — extension-space
|
|
134
|
+
* fields are scoped out by the API: the hook is wired at the
|
|
135
|
+
* application emitter only.
|
|
136
|
+
*/
|
|
137
|
+
interface FieldEventContext {
|
|
138
|
+
readonly tableName: string;
|
|
139
|
+
readonly fieldName: string;
|
|
140
|
+
readonly priorTable?: StorageTable;
|
|
141
|
+
readonly newTable?: StorageTable;
|
|
142
|
+
readonly priorField?: StorageColumn;
|
|
143
|
+
readonly newField?: StorageColumn;
|
|
144
|
+
}
|
|
95
145
|
interface CodecControlHooks<TTargetDetails = unknown> {
|
|
96
146
|
planTypeOperations?: (options: {
|
|
97
147
|
readonly typeName: string;
|
|
@@ -132,17 +182,52 @@ interface CodecControlHooks<TTargetDetails = unknown> {
|
|
|
132
182
|
* - undefined: no opinion; planner may use built-in fallbacks
|
|
133
183
|
*/
|
|
134
184
|
resolveIdentityValue?: (input: ResolveIdentityValueInput) => string | null | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* Reacts to per-field added / dropped / altered events as the app-space
|
|
187
|
+
* emitter diffs the prior contract against the new contract. Returned
|
|
188
|
+
* ops are inlined into the app-space migration's `ops.json` alongside
|
|
189
|
+
* the user's structural ops.
|
|
190
|
+
*
|
|
191
|
+
* Synchronous. Each returned op must carry its own `invariantId`. Hooks
|
|
192
|
+
* are dispatched per `(table, field)` based on the field's `codecId`
|
|
193
|
+
* (the new field's codec for `'added'` / `'altered'`; the prior field's
|
|
194
|
+
* codec for `'dropped'`).
|
|
195
|
+
*/
|
|
196
|
+
onFieldEvent?: (event: FieldEvent, ctx: FieldEventContext) => readonly OpFactoryCall[];
|
|
135
197
|
}
|
|
136
198
|
interface SqlControlExtensionDescriptor<TTargetId extends string> extends ControlExtensionDescriptor<'sql', TTargetId> {
|
|
137
199
|
readonly databaseDependencies?: ComponentDatabaseDependencies<unknown>;
|
|
138
|
-
readonly queryOperations?: () =>
|
|
200
|
+
readonly queryOperations?: () => SqlOperationDescriptors;
|
|
201
|
+
/**
|
|
202
|
+
* Schema-contributing extensions opt into the per-space planner / runner /
|
|
203
|
+
* verifier by setting this field. Extensions without it are codec-only or
|
|
204
|
+
* query-ops-only — today's behaviour preserved.
|
|
205
|
+
*
|
|
206
|
+
* The shape comes from `@prisma-next/framework-components/control`
|
|
207
|
+
* (`ContractSpace`) — contract-space identity is a framework concept,
|
|
208
|
+
* not a SQL-specific one. The SQL family specialises the generic to
|
|
209
|
+
* `Contract<SqlStorage>` so descriptor authors continue to see a
|
|
210
|
+
* typed contract value.
|
|
211
|
+
*
|
|
212
|
+
* @see specs/framework-mechanism.spec.md § 1.
|
|
213
|
+
*/
|
|
214
|
+
readonly contractSpace?: ContractSpace<Contract<SqlStorage>>;
|
|
139
215
|
}
|
|
140
216
|
interface SqlControlAdapterDescriptor<TTargetId extends string> extends ControlAdapterDescriptor<'sql', TTargetId> {
|
|
141
|
-
readonly queryOperations?: () =>
|
|
217
|
+
readonly queryOperations?: () => SqlOperationDescriptors;
|
|
142
218
|
}
|
|
143
219
|
interface SqlMigrationPlanOperationStep {
|
|
144
220
|
readonly description: string;
|
|
145
221
|
readonly sql: string;
|
|
222
|
+
/**
|
|
223
|
+
* Optional parameter values bound at execution time. The runner forwards
|
|
224
|
+
* these to `driver.query(sql, params ?? [])`, so step authors can use
|
|
225
|
+
* placeholder syntax (`$1`, `$2`, …) instead of inlining literals into
|
|
226
|
+
* the SQL string. Reuses the driver's parameter binder rather than
|
|
227
|
+
* rolling per-target literal serialization for every type the planner
|
|
228
|
+
* may emit.
|
|
229
|
+
*/
|
|
230
|
+
readonly params?: readonly unknown[];
|
|
146
231
|
readonly meta?: AnyRecord;
|
|
147
232
|
}
|
|
148
233
|
/**
|
|
@@ -168,21 +253,26 @@ interface SqlMigrationPlanOperation<TTargetDetails> extends MigrationPlanOperati
|
|
|
168
253
|
readonly postcheck: readonly SqlMigrationPlanOperationStep[];
|
|
169
254
|
readonly meta?: AnyRecord;
|
|
170
255
|
}
|
|
171
|
-
/**
|
|
172
|
-
* Union of all operation shapes a SQL-family migration may emit: schema-facing
|
|
173
|
-
* `SqlMigrationPlanOperation`s and family-agnostic `DataTransformOperation`s.
|
|
174
|
-
*
|
|
175
|
-
* Mirrors `AnyMongoMigrationOperation` in shape — the runner already handles
|
|
176
|
-
* both branches via `isDataTransformOperation`, and authored `migration.ts`
|
|
177
|
-
* files must be able to intermix `dataTransform(endContract, …)` calls with
|
|
178
|
-
* DDL factory calls (e.g. `setNotNull(…)`) in a single `operations` array.
|
|
179
|
-
*/
|
|
180
|
-
type AnySqlMigrationOperation<TTargetDetails> = SqlMigrationPlanOperation<TTargetDetails> | DataTransformOperation;
|
|
181
256
|
interface SqlMigrationPlanContractInfo {
|
|
182
257
|
readonly storageHash: string;
|
|
183
258
|
readonly profileHash?: string;
|
|
184
259
|
}
|
|
185
260
|
interface SqlMigrationPlan<TTargetDetails> extends MigrationPlan {
|
|
261
|
+
/**
|
|
262
|
+
* Contract space this plan applies to. The runner uses this to key the
|
|
263
|
+
* `prisma_contract.marker` row it writes/reads (`space = <spaceId>`),
|
|
264
|
+
* so per-extension plans hit per-extension marker rows instead of all
|
|
265
|
+
* collapsing onto the app's row.
|
|
266
|
+
*
|
|
267
|
+
* App-plan callers pass `APP_SPACE_ID` (`'app'`); per-extension plans
|
|
268
|
+
* pass the extension's space id. Required at every call site so the
|
|
269
|
+
* type system surfaces every place that needs to thread the value
|
|
270
|
+
* (rather than letting an `?? APP_SPACE_ID` fall-through silently
|
|
271
|
+
* collapse multi-space markers onto the `'app'` row).
|
|
272
|
+
*
|
|
273
|
+
* @see specs/framework-mechanism.spec.md § 2.
|
|
274
|
+
*/
|
|
275
|
+
readonly spaceId: string;
|
|
186
276
|
/**
|
|
187
277
|
* Origin contract identity that the plan expects the database to currently be at.
|
|
188
278
|
* If omitted or null, the runner skips origin validation entirely.
|
|
@@ -193,6 +283,15 @@ interface SqlMigrationPlan<TTargetDetails> extends MigrationPlan {
|
|
|
193
283
|
*/
|
|
194
284
|
readonly destination: SqlMigrationPlanContractInfo;
|
|
195
285
|
readonly operations: readonly SqlMigrationPlanOperation<TTargetDetails>[];
|
|
286
|
+
/**
|
|
287
|
+
* Sorted, deduplicated invariant ids declared by this plan's data-transform
|
|
288
|
+
* ops. Required at the SQL-family layer (the SQL runners consume this as
|
|
289
|
+
* the source of truth for marker writes and self-edge no-op checks); the
|
|
290
|
+
* framework-level {@link MigrationPlan.providedInvariants} stays optional
|
|
291
|
+
* because `db init` / `db update` plans don't have a corresponding
|
|
292
|
+
* migration manifest.
|
|
293
|
+
*/
|
|
294
|
+
readonly providedInvariants: readonly string[];
|
|
196
295
|
readonly meta?: AnyRecord;
|
|
197
296
|
}
|
|
198
297
|
type SqlPlannerConflictKind = 'typeMismatch' | 'nullabilityConflict' | 'indexIncompatible' | 'foreignKeyConflict' | 'missingButNonAdditive' | 'unsupportedOperation';
|
|
@@ -223,14 +322,29 @@ interface SqlMigrationPlannerPlanOptions {
|
|
|
223
322
|
readonly policy: MigrationOperationPolicy;
|
|
224
323
|
readonly schemaName?: string;
|
|
225
324
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
325
|
+
* Contract space the plan applies to. The planner stamps this onto
|
|
326
|
+
* the produced {@link SqlMigrationPlan.spaceId} so the runner keys
|
|
327
|
+
* the marker row by the right space. App-plan callers pass
|
|
328
|
+
* `APP_SPACE_ID`; per-extension callers pass the extension's space
|
|
329
|
+
* id.
|
|
330
|
+
*/
|
|
331
|
+
readonly spaceId: string;
|
|
332
|
+
/**
|
|
333
|
+
* The "from" contract (state the planner assumes the database starts at),
|
|
334
|
+
* or `null` for reconciliation flows that have no prior contract.
|
|
335
|
+
*
|
|
336
|
+
* Required at every call site so the structural fact "I have a prior
|
|
337
|
+
* contract / I don't" is visible in the type. `migration plan` supplies
|
|
338
|
+
* the previous bundle's `metadata.toContract`; `db update` / `db init`
|
|
339
|
+
* reconcile against the live schema and pass `null`. Strategies that
|
|
340
|
+
* need from/to column-shape comparisons (unsafe type change, nullability
|
|
230
341
|
* tightening) use this to decide whether to emit `dataTransform`
|
|
231
|
-
* placeholders
|
|
342
|
+
* placeholders; they short-circuit when it is `null`.
|
|
343
|
+
*
|
|
344
|
+
* Planners also derive the "from" identity they stamp onto the produced
|
|
345
|
+
* plan's `describe()` as `fromContract?.storage.storageHash ?? null`.
|
|
232
346
|
*/
|
|
233
|
-
readonly fromContract
|
|
347
|
+
readonly fromContract: Contract<SqlStorage> | null;
|
|
234
348
|
/**
|
|
235
349
|
* Active framework components participating in this composition.
|
|
236
350
|
* SQL targets can interpret this list to derive database dependencies.
|
|
@@ -248,6 +362,14 @@ interface SqlMigrationRunnerExecuteCallbacks<TTargetDetails> {
|
|
|
248
362
|
interface SqlMigrationRunnerExecuteOptions<TTargetDetails> {
|
|
249
363
|
readonly plan: SqlMigrationPlan<TTargetDetails>;
|
|
250
364
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
365
|
+
/**
|
|
366
|
+
* Logical contract space this plan applies to. When omitted the
|
|
367
|
+
* runner derives the space from {@link SqlMigrationPlan.spaceId};
|
|
368
|
+
* when supplied, the runner asserts it matches `plan.spaceId` so a
|
|
369
|
+
* caller cannot accidentally write the marker row for a different
|
|
370
|
+
* space than the plan was produced for.
|
|
371
|
+
*/
|
|
372
|
+
readonly space?: string;
|
|
251
373
|
/**
|
|
252
374
|
* Destination contract IR.
|
|
253
375
|
* Must correspond to `plan.destination` and is used for schema verification and marker/ledger writes.
|
|
@@ -274,7 +396,7 @@ interface SqlMigrationRunnerExecuteOptions<TTargetDetails> {
|
|
|
274
396
|
*/
|
|
275
397
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
276
398
|
}
|
|
277
|
-
type SqlMigrationRunnerErrorCode = 'DESTINATION_CONTRACT_MISMATCH' | 'MARKER_ORIGIN_MISMATCH' | 'POLICY_VIOLATION' | 'PRECHECK_FAILED' | 'POSTCHECK_FAILED' | 'SCHEMA_VERIFY_FAILED' | 'EXECUTION_FAILED';
|
|
399
|
+
type SqlMigrationRunnerErrorCode = 'DESTINATION_CONTRACT_MISMATCH' | 'LEGACY_MARKER_SHAPE' | 'MARKER_ORIGIN_MISMATCH' | 'POLICY_VIOLATION' | 'PRECHECK_FAILED' | 'POSTCHECK_FAILED' | 'SCHEMA_VERIFY_FAILED' | 'FOREIGN_KEY_VIOLATION' | 'EXECUTION_FAILED';
|
|
278
400
|
interface SqlMigrationRunnerFailure extends MigrationRunnerFailure {
|
|
279
401
|
readonly code: SqlMigrationRunnerErrorCode;
|
|
280
402
|
readonly meta?: AnyRecord;
|
|
@@ -282,20 +404,76 @@ interface SqlMigrationRunnerFailure extends MigrationRunnerFailure {
|
|
|
282
404
|
interface SqlMigrationRunnerSuccessValue extends MigrationRunnerSuccessValue {}
|
|
283
405
|
type SqlMigrationRunnerResult = Result<SqlMigrationRunnerSuccessValue, SqlMigrationRunnerFailure>;
|
|
284
406
|
interface SqlMigrationRunner<TTargetDetails> {
|
|
407
|
+
/**
|
|
408
|
+
* Apply a single migration plan, opening and managing its own
|
|
409
|
+
* transaction (and any target-specific connection-level setup, e.g.
|
|
410
|
+
* SQLite's `PRAGMA foreign_keys` toggle). Existing single-space
|
|
411
|
+
* callers route through here.
|
|
412
|
+
*/
|
|
285
413
|
execute(options: SqlMigrationRunnerExecuteOptions<TTargetDetails>): Promise<SqlMigrationRunnerResult>;
|
|
414
|
+
/**
|
|
415
|
+
* Apply a single migration plan against an already-open connection
|
|
416
|
+
* **without** opening a transaction. The caller is responsible for
|
|
417
|
+
* wrapping the call (and any siblings) in `BEGIN` / `COMMIT` /
|
|
418
|
+
* `ROLLBACK`. Used by the per-space runner wiring to fan out across
|
|
419
|
+
* contract spaces inside one outer transaction so a mid-apply
|
|
420
|
+
* failure rolls back every space's writes.
|
|
421
|
+
*
|
|
422
|
+
* Idempotent control-table setup (`prisma_contract.*`) and marker
|
|
423
|
+
* writes use `options.space` to address the per-space marker row.
|
|
424
|
+
*/
|
|
425
|
+
executeOnConnection(options: SqlMigrationRunnerExecuteOptions<TTargetDetails>): Promise<SqlMigrationRunnerResult>;
|
|
426
|
+
/**
|
|
427
|
+
* Apply per-space plans across multiple contract spaces inside a
|
|
428
|
+
* single outer transaction. The caller orders the input list
|
|
429
|
+
* (typically via the aggregate planner's `applyOrder`: extensions
|
|
430
|
+
* alphabetical, then app); the runner is responsible for opening
|
|
431
|
+
* / committing the outer
|
|
432
|
+
* transaction (and any target-specific connection-level setup such
|
|
433
|
+
* as the SQLite FK pragma toggle). A failure on any space rolls
|
|
434
|
+
* back every space's writes.
|
|
435
|
+
*
|
|
436
|
+
* Each space's `SqlMigrationRunnerExecuteOptions` must reference the
|
|
437
|
+
* same `driver` (the connection the outer transaction is open on).
|
|
438
|
+
* Per-space marker writes use `options.space` to address the row.
|
|
439
|
+
*/
|
|
440
|
+
executeAcrossSpaces(options: {
|
|
441
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
442
|
+
readonly perSpaceOptions: ReadonlyArray<SqlMigrationRunnerExecuteOptions<TTargetDetails>>;
|
|
443
|
+
}): Promise<MultiSpaceRunnerResult>;
|
|
286
444
|
}
|
|
445
|
+
interface MultiSpaceRunnerSuccessValue {
|
|
446
|
+
readonly perSpaceResults: ReadonlyArray<{
|
|
447
|
+
readonly space: string;
|
|
448
|
+
readonly value: SqlMigrationRunnerSuccessValue;
|
|
449
|
+
}>;
|
|
450
|
+
}
|
|
451
|
+
interface MultiSpaceRunnerFailure extends SqlMigrationRunnerFailure {
|
|
452
|
+
readonly failingSpace: string;
|
|
453
|
+
}
|
|
454
|
+
type MultiSpaceRunnerResult = Result<MultiSpaceRunnerSuccessValue, MultiSpaceRunnerFailure>;
|
|
287
455
|
interface SqlControlTargetDescriptor<TTargetId extends string, TTargetDetails> extends MigratableTargetDescriptor<'sql', TTargetId, SqlControlFamilyInstance> {
|
|
288
|
-
readonly queryOperations?: () =>
|
|
456
|
+
readonly queryOperations?: () => SqlOperationDescriptors;
|
|
289
457
|
createPlanner(family: SqlControlFamilyInstance): SqlMigrationPlanner<TTargetDetails>;
|
|
290
458
|
createRunner(family: SqlControlFamilyInstance): SqlMigrationRunner<TTargetDetails>;
|
|
291
459
|
}
|
|
292
460
|
interface CreateSqlMigrationPlanOptions<TTargetDetails> {
|
|
293
461
|
readonly targetId: string;
|
|
462
|
+
/**
|
|
463
|
+
* Contract space this plan applies to. Mirrors {@link SqlMigrationPlan.spaceId}.
|
|
464
|
+
*/
|
|
465
|
+
readonly spaceId: string;
|
|
294
466
|
readonly origin?: SqlMigrationPlanContractInfo | null;
|
|
295
467
|
readonly destination: SqlMigrationPlanContractInfo;
|
|
296
468
|
readonly operations: readonly SqlMigrationPlanOperation<TTargetDetails>[];
|
|
469
|
+
/**
|
|
470
|
+
* Sorted, deduplicated invariant ids for this plan; mirrors the required
|
|
471
|
+
* field on {@link SqlMigrationPlan}. Callers without a migration manifest
|
|
472
|
+
* (`db init`, `db update`, planner-built plans) pass `[]`.
|
|
473
|
+
*/
|
|
474
|
+
readonly providedInvariants: readonly string[];
|
|
297
475
|
readonly meta?: AnyRecord;
|
|
298
476
|
}
|
|
299
477
|
//#endregion
|
|
300
|
-
export {
|
|
301
|
-
//# sourceMappingURL=types-
|
|
478
|
+
export { SqlPlanTargetDetails as A, SchemaVerifyOptions as B, SqlMigrationRunner as C, SqlMigrationRunnerFailure as D, SqlMigrationRunnerExecuteOptions as E, SqlPlannerResult as F, SqlPlannerSuccessResult as I, StorageTypePlanResult as L, SqlPlannerConflictKind as M, SqlPlannerConflictLocation as N, SqlMigrationRunnerResult as O, SqlPlannerFailureResult as P, collectInitDependencies as R, SqlMigrationPlannerPlanOptions as S, SqlMigrationRunnerExecuteCallbacks as T, SqlControlFamilyInstance as V, SqlMigrationPlanContractInfo as _, CreateSqlMigrationPlanOptions as a, SqlMigrationPlanOperationTarget as b, FieldEventContext as c, MultiSpaceRunnerSuccessValue as d, ResolveIdentityValueInput as f, SqlMigrationPlan as g, SqlControlTargetDescriptor as h, ComponentDatabaseDependency as i, SqlPlannerConflict as j, SqlMigrationRunnerSuccessValue as k, MultiSpaceRunnerFailure as l, SqlControlExtensionDescriptor as m, CodecControlHooks as n, ExpandNativeTypeInput as o, SqlControlAdapterDescriptor as p, ComponentDatabaseDependencies as r, FieldEvent as s, AnyRecord as t, MultiSpaceRunnerResult as u, SqlMigrationPlanOperation as v, SqlMigrationRunnerErrorCode as w, SqlMigrationPlanner as x, SqlMigrationPlanOperationStep as y, isDatabaseDependencyProvider as z };
|
|
479
|
+
//# sourceMappingURL=types-BQBbcXg3.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-BQBbcXg3.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/migrations/types.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
//#region src/core/verify.ts
|
|
3
|
+
const MetaSchema = type({ "[string]": "unknown" });
|
|
4
|
+
function parseMeta(meta) {
|
|
5
|
+
if (meta === null || meta === void 0) return {};
|
|
6
|
+
let parsed;
|
|
7
|
+
if (typeof meta === "string") try {
|
|
8
|
+
parsed = JSON.parse(meta);
|
|
9
|
+
} catch {
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
else parsed = meta;
|
|
13
|
+
const result = MetaSchema(parsed);
|
|
14
|
+
if (result instanceof type.errors) return {};
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* SQLite stores `contract_json` as TEXT, so the wire shape is a JSON string;
|
|
19
|
+
* Postgres uses `jsonb` and returns an already-parsed value. Normalize both
|
|
20
|
+
* here so `ContractMarkerRecord.contractJson` is always the structured form.
|
|
21
|
+
*/
|
|
22
|
+
function parseContractJson(value) {
|
|
23
|
+
if (value === null || value === void 0) return null;
|
|
24
|
+
if (typeof value !== "string") return value;
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(value);
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const ContractMarkerRowSchema = type({
|
|
32
|
+
core_hash: "string",
|
|
33
|
+
profile_hash: "string",
|
|
34
|
+
"contract_json?": "unknown | null",
|
|
35
|
+
"canonical_version?": "number | null",
|
|
36
|
+
"updated_at?": "Date | string",
|
|
37
|
+
"app_tag?": "string | null",
|
|
38
|
+
"meta?": "unknown | null",
|
|
39
|
+
invariants: type("string").array()
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Parses a contract marker row from database query result.
|
|
43
|
+
* This is SQL-specific parsing logic (handles SQL row structure with snake_case columns).
|
|
44
|
+
*/
|
|
45
|
+
function parseContractMarkerRow(row) {
|
|
46
|
+
const result = ContractMarkerRowSchema(row);
|
|
47
|
+
if (result instanceof type.errors) {
|
|
48
|
+
const messages = result.map((p) => p.message).join("; ");
|
|
49
|
+
throw new Error(`Invalid contract marker row: ${messages}`);
|
|
50
|
+
}
|
|
51
|
+
const updatedAt = result.updated_at ? result.updated_at instanceof Date ? result.updated_at : new Date(result.updated_at) : /* @__PURE__ */ new Date();
|
|
52
|
+
return {
|
|
53
|
+
storageHash: result.core_hash,
|
|
54
|
+
profileHash: result.profile_hash,
|
|
55
|
+
contractJson: parseContractJson(result.contract_json),
|
|
56
|
+
canonicalVersion: result.canonical_version ?? null,
|
|
57
|
+
updatedAt,
|
|
58
|
+
appTag: result.app_tag ?? null,
|
|
59
|
+
meta: parseMeta(result.meta),
|
|
60
|
+
invariants: result.invariants
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Collects supported codec type IDs from adapter and extension manifests.
|
|
65
|
+
* Returns a sorted, unique array of type IDs that are declared in the manifests.
|
|
66
|
+
* This enables coverage checks by comparing contract column types against supported types.
|
|
67
|
+
*
|
|
68
|
+
* Note: This extracts type IDs from manifest type imports, not from runtime codec registries.
|
|
69
|
+
* The manifests declare which codec types are available, but the actual type IDs
|
|
70
|
+
* are defined in the codec-types TypeScript modules that are imported.
|
|
71
|
+
*
|
|
72
|
+
* For MVP, we return an empty array since extracting type IDs from TypeScript modules
|
|
73
|
+
* would require runtime evaluation or static analysis. This can be enhanced later.
|
|
74
|
+
*/
|
|
75
|
+
function collectSupportedCodecTypeIds(descriptors) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { parseContractMarkerRow as n, collectSupportedCodecTypeIds as t };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=verify-pRYxnpiG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-pRYxnpiG.mjs","names":[],"sources":["../src/core/verify.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { type } from 'arktype';\n\nconst MetaSchema = type({ '[string]': 'unknown' });\n\nfunction parseMeta(meta: unknown): Record<string, unknown> {\n if (meta === null || meta === undefined) {\n return {};\n }\n\n let parsed: unknown;\n if (typeof meta === 'string') {\n try {\n parsed = JSON.parse(meta);\n } catch {\n return {};\n }\n } else {\n parsed = meta;\n }\n\n const result = MetaSchema(parsed);\n if (result instanceof type.errors) {\n return {};\n }\n\n return result as Record<string, unknown>;\n}\n\n/**\n * SQLite stores `contract_json` as TEXT, so the wire shape is a JSON string;\n * Postgres uses `jsonb` and returns an already-parsed value. Normalize both\n * here so `ContractMarkerRecord.contractJson` is always the structured form.\n */\nfunction parseContractJson(value: unknown): unknown {\n if (value === null || value === undefined) return null;\n if (typeof value !== 'string') return value;\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n}\n\n/**\n * Wire shape of a `prisma_contract.marker` row as it comes out of a SQL\n * driver. Snake-cased to match the on-disk column names. Shared by every\n * SQL target's `readMarker` so each runner doesn't redeclare it inline.\n */\nexport type ContractMarkerRow = {\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n // SQLite stores arrays as JSON-TEXT, so this is `string` on the wire from\n // a SQLite driver and `string[]` from a Postgres driver. Targets normalize\n // before passing to `parseContractMarkerRow`.\n invariants: unknown;\n};\n\nconst ContractMarkerRowSchema = type({\n core_hash: 'string',\n profile_hash: 'string',\n 'contract_json?': 'unknown | null',\n 'canonical_version?': 'number | null',\n 'updated_at?': 'Date | string',\n 'app_tag?': 'string | null',\n 'meta?': 'unknown | null',\n invariants: type('string').array(),\n});\n\n/**\n * Parses a contract marker row from database query result.\n * This is SQL-specific parsing logic (handles SQL row structure with snake_case columns).\n */\nexport function parseContractMarkerRow(row: unknown): ContractMarkerRecord {\n const result = ContractMarkerRowSchema(row);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Invalid contract marker row: ${messages}`);\n }\n\n const updatedAt = result.updated_at\n ? result.updated_at instanceof Date\n ? result.updated_at\n : new Date(result.updated_at)\n : new Date();\n\n return {\n storageHash: result.core_hash,\n profileHash: result.profile_hash,\n contractJson: parseContractJson(result.contract_json),\n canonicalVersion: result.canonical_version ?? null,\n updatedAt,\n appTag: result.app_tag ?? null,\n meta: parseMeta(result.meta),\n invariants: result.invariants,\n };\n}\n\n/**\n * Collects supported codec type IDs from adapter and extension manifests.\n * Returns a sorted, unique array of type IDs that are declared in the manifests.\n * This enables coverage checks by comparing contract column types against supported types.\n *\n * Note: This extracts type IDs from manifest type imports, not from runtime codec registries.\n * The manifests declare which codec types are available, but the actual type IDs\n * are defined in the codec-types TypeScript modules that are imported.\n *\n * For MVP, we return an empty array since extracting type IDs from TypeScript modules\n * would require runtime evaluation or static analysis. This can be enhanced later.\n */\nexport function collectSupportedCodecTypeIds(\n descriptors: ReadonlyArray<{ readonly id: string }>,\n): readonly string[] {\n // For MVP, return empty array\n // Future enhancement: Extract type IDs from codec-types modules via static analysis\n // or require manifests to explicitly list supported type IDs\n void descriptors;\n return [];\n}\n"],"mappings":";;AAGA,MAAM,aAAa,KAAK,EAAE,YAAY,WAAW,CAAC;AAElD,SAAS,UAAU,MAAwC;CACzD,IAAI,SAAS,QAAQ,SAAS,KAAA,GAC5B,OAAO,EAAE;CAGX,IAAI;CACJ,IAAI,OAAO,SAAS,UAClB,IAAI;EACF,SAAS,KAAK,MAAM,KAAK;SACnB;EACN,OAAO,EAAE;;MAGX,SAAS;CAGX,MAAM,SAAS,WAAW,OAAO;CACjC,IAAI,kBAAkB,KAAK,QACzB,OAAO,EAAE;CAGX,OAAO;;;;;;;AAQT,SAAS,kBAAkB,OAAyB;CAClD,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;CAClD,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI;EACF,OAAO,KAAK,MAAM,MAAM;SAClB;EACN,OAAO;;;AAuBX,MAAM,0BAA0B,KAAK;CACnC,WAAW;CACX,cAAc;CACd,kBAAkB;CAClB,sBAAsB;CACtB,eAAe;CACf,YAAY;CACZ,SAAS;CACT,YAAY,KAAK,SAAS,CAAC,OAAO;CACnC,CAAC;;;;;AAMF,SAAgB,uBAAuB,KAAoC;CACzE,MAAM,SAAS,wBAAwB,IAAI;CAC3C,IAAI,kBAAkB,KAAK,QAAQ;EACjC,MAAM,WAAW,OAAO,KAAK,MAA2B,EAAE,QAAQ,CAAC,KAAK,KAAK;EAC7E,MAAM,IAAI,MAAM,gCAAgC,WAAW;;CAG7D,MAAM,YAAY,OAAO,aACrB,OAAO,sBAAsB,OAC3B,OAAO,aACP,IAAI,KAAK,OAAO,WAAW,mBAC7B,IAAI,MAAM;CAEd,OAAO;EACL,aAAa,OAAO;EACpB,aAAa,OAAO;EACpB,cAAc,kBAAkB,OAAO,cAAc;EACrD,kBAAkB,OAAO,qBAAqB;EAC9C;EACA,QAAQ,OAAO,WAAW;EAC1B,MAAM,UAAU,OAAO,KAAK;EAC5B,YAAY,OAAO;EACpB;;;;;;;;;;;;;;AAeH,SAAgB,6BACd,aACmB;CAKnB,OAAO,EAAE"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { OperationContext, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
|
|
2
|
-
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
3
2
|
import { ColumnDefault, Contract } from "@prisma-next/contract/types";
|
|
3
|
+
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
4
4
|
import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
|
|
5
5
|
import { SqlStorage } from "@prisma-next/sql-contract/types";
|
|
6
6
|
|
|
7
7
|
//#region src/core/schema-verify/verify-sql-schema.d.ts
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* Function type for normalizing raw database default expressions into ColumnDefault.
|
|
11
10
|
* Target-specific implementations handle database dialect differences.
|
|
@@ -64,4 +63,4 @@ interface VerifySqlSchemaOptions {
|
|
|
64
63
|
declare function verifySqlSchema(options: VerifySqlSchemaOptions): VerifyDatabaseSchemaResult;
|
|
65
64
|
//#endregion
|
|
66
65
|
export { verifySqlSchema as i, NativeTypeNormalizer as n, VerifySqlSchemaOptions as r, DefaultNormalizer as t };
|
|
67
|
-
//# sourceMappingURL=verify-sql-schema-
|
|
66
|
+
//# sourceMappingURL=verify-sql-schema-CPHiuYHR.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-sql-schema-CPHiuYHR.d.mts","names":[],"sources":["../src/core/schema-verify/verify-sql-schema.ts"],"mappings":";;;;;;;;;;;KAuCY,iBAAA,IACV,UAAA,UACA,UAAA,aACG,aAAA;;;;;AAYL;KALY,oBAAA,IAAwB,UAAA;;;;UAKnB,sBAAA;EAQI;EAAA,SANV,QAAA,EAAU,QAAA,CAAS,UAAA;EAagB;EAAA,SAXnC,MAAA,EAAQ,WAAA;EAiBW;EAAA,SAfnB,MAAA;EAqB0C;EAAA,SAnB1C,OAAA,GAAU,gBAAA;EANV;EAAA,SAQA,oBAAA,EAAsB,WAAA;IAAsB,UAAA;EAAA;EANpC;;;;EAAA,SAWR,mBAAA,EAAqB,aAAA,CAAc,8BAAA;EALb;;;;;EAAA,SAWtB,gBAAA,GAAmB,iBAAA;EAAA;;;;;EAAA,SAMnB,mBAAA,GAAsB,oBAAA;AAAA;;;;;;;;;;;iBAajB,eAAA,CAAgB,OAAA,EAAS,sBAAA,GAAyB,0BAAA"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { assertUniqueCodecOwner } from "@prisma-next/framework-components/control";
|
|
2
2
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
3
|
-
|
|
4
3
|
//#region src/core/assembly.ts
|
|
5
4
|
function hasCodecControlHooks(descriptor) {
|
|
6
5
|
if (typeof descriptor !== "object" || descriptor === null) return false;
|
|
@@ -28,7 +27,6 @@ function extractCodecControlHooks(descriptors) {
|
|
|
28
27
|
}
|
|
29
28
|
return hooks;
|
|
30
29
|
}
|
|
31
|
-
|
|
32
30
|
//#endregion
|
|
33
31
|
//#region src/core/migrations/types.ts
|
|
34
32
|
function isDatabaseDependencyProvider(value) {
|
|
@@ -44,9 +42,21 @@ function collectInitDependencies(components) {
|
|
|
44
42
|
}
|
|
45
43
|
return result;
|
|
46
44
|
}
|
|
47
|
-
|
|
48
45
|
//#endregion
|
|
49
46
|
//#region src/core/schema-verify/verify-helpers.ts
|
|
47
|
+
function indexOptionsLooselyEqual(a, b) {
|
|
48
|
+
const aKeys = a ? Object.keys(a).sort() : [];
|
|
49
|
+
const bKeys = b ? Object.keys(b).sort() : [];
|
|
50
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
51
|
+
for (let i = 0; i < aKeys.length; i += 1) if (aKeys[i] !== bKeys[i]) return false;
|
|
52
|
+
if (aKeys.length === 0) return true;
|
|
53
|
+
for (const key of aKeys) if (String(a[key]) !== String(b[key])) return false;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
function indexExtrasMatch(contractIndex, schemaIndex) {
|
|
57
|
+
if ((contractIndex.type ?? null) !== (schemaIndex.type ?? null)) return false;
|
|
58
|
+
return indexOptionsLooselyEqual(contractIndex.options, schemaIndex.options);
|
|
59
|
+
}
|
|
50
60
|
/**
|
|
51
61
|
* Compares two arrays of strings for equality (order-sensitive).
|
|
52
62
|
*/
|
|
@@ -296,8 +306,8 @@ function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName,
|
|
|
296
306
|
const nodes = [];
|
|
297
307
|
for (const contractIndex of contractIndexes) {
|
|
298
308
|
const indexPath = `${tablePath}.indexes[${contractIndex.columns.join(",")}]`;
|
|
299
|
-
const matchingIndex = schemaIndexes.find((idx) => arraysEqual(idx.columns, contractIndex.columns));
|
|
300
|
-
const matchingUniqueConstraint = !matchingIndex && schemaUniques.find((u) => arraysEqual(u.columns, contractIndex.columns));
|
|
309
|
+
const matchingIndex = schemaIndexes.find((idx) => arraysEqual(idx.columns, contractIndex.columns) && indexExtrasMatch(contractIndex, idx));
|
|
310
|
+
const matchingUniqueConstraint = !matchingIndex && contractIndex.type === void 0 && contractIndex.options === void 0 && schemaUniques.find((u) => arraysEqual(u.columns, contractIndex.columns));
|
|
301
311
|
if (!matchingIndex && !matchingUniqueConstraint) {
|
|
302
312
|
issues.push({
|
|
303
313
|
kind: "index_mismatch",
|
|
@@ -330,7 +340,7 @@ function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName,
|
|
|
330
340
|
}
|
|
331
341
|
if (strict) for (const schemaIndex of schemaIndexes) {
|
|
332
342
|
if (schemaIndex.unique) continue;
|
|
333
|
-
if (!contractIndexes.find((idx) => arraysEqual(idx.columns, schemaIndex.columns))) {
|
|
343
|
+
if (!contractIndexes.find((idx) => arraysEqual(idx.columns, schemaIndex.columns) && indexExtrasMatch(idx, schemaIndex))) {
|
|
334
344
|
issues.push({
|
|
335
345
|
kind: "extra_index",
|
|
336
346
|
table: tableName,
|
|
@@ -453,7 +463,6 @@ function getReferentialActionMismatches(contractFK, schemaFK) {
|
|
|
453
463
|
function normalizeReferentialAction(action) {
|
|
454
464
|
return action === "noAction" ? void 0 : action;
|
|
455
465
|
}
|
|
456
|
-
|
|
457
466
|
//#endregion
|
|
458
467
|
//#region src/core/schema-verify/verify-sql-schema.ts
|
|
459
468
|
/**
|
|
@@ -1123,7 +1132,7 @@ function formatLiteralValue(value) {
|
|
|
1123
1132
|
if (typeof value === "string") return value;
|
|
1124
1133
|
return JSON.stringify(value);
|
|
1125
1134
|
}
|
|
1126
|
-
|
|
1127
1135
|
//#endregion
|
|
1128
1136
|
export { verifyDatabaseDependencies as a, extractCodecControlHooks as c, isUniqueConstraintSatisfied as i, arraysEqual as n, collectInitDependencies as o, isIndexSatisfied as r, isDatabaseDependencyProvider as s, verifySqlSchema as t };
|
|
1129
|
-
|
|
1137
|
+
|
|
1138
|
+
//# sourceMappingURL=verify-sql-schema-r1-2apHI.mjs.map
|