@prisma-next/family-sql 0.1.0-dev.19 → 0.1.0-dev.20
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 +10 -1
- package/dist/exports/{chunk-I7QWTBWS.js → chunk-6AMLAAA2.js} +58 -51
- package/dist/exports/chunk-6AMLAAA2.js.map +1 -0
- package/dist/exports/{chunk-ZAI6E4PG.js → chunk-NUALBK4N.js} +5 -4
- package/dist/exports/chunk-NUALBK4N.js.map +1 -0
- package/dist/exports/control.d.ts +12 -317
- package/dist/exports/control.js +2 -2
- package/dist/exports/control.js.map +1 -1
- package/dist/exports/instance-BDpyIYu5.d.ts +384 -0
- package/dist/exports/schema-verify.d.ts +29 -3
- package/dist/exports/schema-verify.js +3 -1
- package/dist/exports/test-utils.js +2 -2
- package/package.json +16 -16
- package/dist/exports/chunk-I7QWTBWS.js.map +0 -1
- package/dist/exports/chunk-ZAI6E4PG.js.map +0 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
|
|
2
|
+
import { ControlTargetDescriptor, ControlTargetInstance, MigrationOperationPolicy, MigrationPlannerSuccessResult, MigrationPlan, MigrationPlanOperation, MigrationPlannerFailureResult, MigrationPlannerConflict, ControlDriverInstance, OperationContext, MigrationRunnerSuccessValue, MigrationRunnerFailure, SchemaIssue, ControlExtensionDescriptor, ControlFamilyInstance, VerifyDatabaseResult, VerifyDatabaseSchemaResult, SignDatabaseResult, EmitContractResult } from '@prisma-next/core-control-plane/types';
|
|
3
|
+
import { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
4
|
+
import { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
5
|
+
import { Result } from '@prisma-next/utils/result';
|
|
6
|
+
import { ContractIR } from '@prisma-next/contract/ir';
|
|
7
|
+
import { TypesImportSpec } from '@prisma-next/contract/types';
|
|
8
|
+
import { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';
|
|
9
|
+
import { OperationRegistry } from '@prisma-next/operations';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* SQL-specific migration types.
|
|
13
|
+
*
|
|
14
|
+
* These types extend the canonical migration types from the framework control plane
|
|
15
|
+
* with SQL-specific fields for execution (precheck SQL, execute SQL, etc.).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
type AnyRecord = Readonly<Record<string, unknown>>;
|
|
19
|
+
/**
|
|
20
|
+
* A single database dependency declared by a framework component.
|
|
21
|
+
* Uses SqlMigrationPlanOperation so we inherit the existing precheck/execute/postcheck contract.
|
|
22
|
+
*
|
|
23
|
+
* Database dependencies allow components (extensions, adapters) to declare what database-side
|
|
24
|
+
* persistence structures they require (e.g., Postgres extensions, schemas, functions).
|
|
25
|
+
* The planner emits these as migration operations, and the verifier uses the pure verification
|
|
26
|
+
* hook to check satisfaction against the schema IR.
|
|
27
|
+
*/
|
|
28
|
+
interface ComponentDatabaseDependency<TTargetDetails = Record<string, never>> {
|
|
29
|
+
/** Stable identifier for the dependency (e.g. 'postgres.extension.vector') */
|
|
30
|
+
readonly id: string;
|
|
31
|
+
/** Human label for output (e.g. 'Enable vector extension') */
|
|
32
|
+
readonly label: string;
|
|
33
|
+
/**
|
|
34
|
+
* Operations that install/ensure the dependency.
|
|
35
|
+
* Use SqlMigrationPlanOperation so we inherit the existing precheck/execute/postcheck contract.
|
|
36
|
+
*/
|
|
37
|
+
readonly install: readonly SqlMigrationPlanOperation<TTargetDetails>[];
|
|
38
|
+
/**
|
|
39
|
+
* Pure verification hook: checks whether this dependency is already installed
|
|
40
|
+
* based on the in-memory schema IR (no DB I/O).
|
|
41
|
+
*
|
|
42
|
+
* This must return structured issues suitable for CLI and tree output, not just a boolean.
|
|
43
|
+
*/
|
|
44
|
+
readonly verifyDatabaseDependencyInstalled: (schema: SqlSchemaIR) => readonly SchemaIssue[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Database dependencies declared by a framework component.
|
|
48
|
+
*/
|
|
49
|
+
interface ComponentDatabaseDependencies<TTargetDetails = Record<string, never>> {
|
|
50
|
+
/**
|
|
51
|
+
* Dependencies required for db init.
|
|
52
|
+
* Future: update dependencies can be added later (e.g. widening/destructive).
|
|
53
|
+
*/
|
|
54
|
+
readonly init?: readonly ComponentDatabaseDependency<TTargetDetails>[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* SQL-specific extension descriptor with optional database dependencies.
|
|
58
|
+
* Extends the core ControlExtensionDescriptor with SQL-specific metadata.
|
|
59
|
+
*
|
|
60
|
+
* Database dependencies are attached to the descriptor (not the instance) because
|
|
61
|
+
* they are declarative metadata that planner/verifier need without constructing instances.
|
|
62
|
+
*/
|
|
63
|
+
interface SqlControlExtensionDescriptor<TTargetId extends string> extends ControlExtensionDescriptor<'sql', TTargetId> {
|
|
64
|
+
/** Optional database dependencies this extension requires. */
|
|
65
|
+
readonly databaseDependencies?: ComponentDatabaseDependencies<unknown>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A single step in a SQL migration operation (precheck, execute, or postcheck).
|
|
69
|
+
*/
|
|
70
|
+
interface SqlMigrationPlanOperationStep {
|
|
71
|
+
readonly description: string;
|
|
72
|
+
readonly sql: string;
|
|
73
|
+
readonly meta?: AnyRecord;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Target details for a SQL migration operation (table, column, index, etc.).
|
|
77
|
+
*/
|
|
78
|
+
interface SqlMigrationPlanOperationTarget<TTargetDetails> {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
readonly details?: TTargetDetails;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A single SQL migration operation with SQL-specific fields.
|
|
84
|
+
* Extends the core MigrationPlanOperation with SQL execution details.
|
|
85
|
+
*/
|
|
86
|
+
interface SqlMigrationPlanOperation<TTargetDetails = Record<string, never>> extends MigrationPlanOperation {
|
|
87
|
+
/** Optional detailed explanation of what this operation does and why. */
|
|
88
|
+
readonly summary?: string;
|
|
89
|
+
readonly target: SqlMigrationPlanOperationTarget<TTargetDetails>;
|
|
90
|
+
readonly precheck: readonly SqlMigrationPlanOperationStep[];
|
|
91
|
+
readonly execute: readonly SqlMigrationPlanOperationStep[];
|
|
92
|
+
readonly postcheck: readonly SqlMigrationPlanOperationStep[];
|
|
93
|
+
readonly meta?: AnyRecord;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Contract identity information for SQL migrations.
|
|
97
|
+
*/
|
|
98
|
+
interface SqlMigrationPlanContractInfo {
|
|
99
|
+
readonly coreHash: string;
|
|
100
|
+
readonly profileHash?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A SQL migration plan with SQL-specific fields.
|
|
104
|
+
* Extends the core MigrationPlan with origin tracking and metadata.
|
|
105
|
+
*/
|
|
106
|
+
interface SqlMigrationPlan<TTargetDetails = Record<string, never>> extends MigrationPlan {
|
|
107
|
+
/**
|
|
108
|
+
* Origin contract identity that the plan expects the database to currently be at.
|
|
109
|
+
* If omitted, the runner treats the origin as "no marker present" (empty database),
|
|
110
|
+
* and will only proceed if no marker exists (or if the marker already matches destination).
|
|
111
|
+
*/
|
|
112
|
+
readonly origin?: SqlMigrationPlanContractInfo | null;
|
|
113
|
+
/**
|
|
114
|
+
* Destination contract identity that the plan intends to reach.
|
|
115
|
+
*/
|
|
116
|
+
readonly destination: SqlMigrationPlanContractInfo;
|
|
117
|
+
readonly operations: readonly SqlMigrationPlanOperation<TTargetDetails>[];
|
|
118
|
+
readonly meta?: AnyRecord;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Specific conflict kinds for SQL migrations.
|
|
122
|
+
*/
|
|
123
|
+
type SqlPlannerConflictKind = 'typeMismatch' | 'nullabilityConflict' | 'indexIncompatible' | 'foreignKeyConflict' | 'missingButNonAdditive' | 'unsupportedExtension' | 'extensionMissing' | 'unsupportedOperation';
|
|
124
|
+
/**
|
|
125
|
+
* Location information for SQL planner conflicts.
|
|
126
|
+
*/
|
|
127
|
+
interface SqlPlannerConflictLocation {
|
|
128
|
+
readonly table?: string;
|
|
129
|
+
readonly column?: string;
|
|
130
|
+
readonly index?: string;
|
|
131
|
+
readonly constraint?: string;
|
|
132
|
+
readonly extension?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A SQL-specific planner conflict with additional location information.
|
|
136
|
+
* Extends the core MigrationPlannerConflict.
|
|
137
|
+
*/
|
|
138
|
+
interface SqlPlannerConflict extends MigrationPlannerConflict {
|
|
139
|
+
readonly kind: SqlPlannerConflictKind;
|
|
140
|
+
readonly location?: SqlPlannerConflictLocation;
|
|
141
|
+
readonly meta?: AnyRecord;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Successful SQL planner result with the migration plan.
|
|
145
|
+
*/
|
|
146
|
+
interface SqlPlannerSuccessResult<TTargetDetails> extends Omit<MigrationPlannerSuccessResult, 'plan'> {
|
|
147
|
+
readonly kind: 'success';
|
|
148
|
+
readonly plan: SqlMigrationPlan<TTargetDetails>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Failed SQL planner result with the list of conflicts.
|
|
152
|
+
*/
|
|
153
|
+
interface SqlPlannerFailureResult extends Omit<MigrationPlannerFailureResult, 'conflicts'> {
|
|
154
|
+
readonly kind: 'failure';
|
|
155
|
+
readonly conflicts: readonly SqlPlannerConflict[];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Union type for SQL planner results.
|
|
159
|
+
*/
|
|
160
|
+
type SqlPlannerResult<TTargetDetails = Record<string, never>> = SqlPlannerSuccessResult<TTargetDetails> | SqlPlannerFailureResult;
|
|
161
|
+
/**
|
|
162
|
+
* Options for SQL migration planner.
|
|
163
|
+
*/
|
|
164
|
+
interface SqlMigrationPlannerPlanOptions {
|
|
165
|
+
readonly contract: SqlContract<SqlStorage>;
|
|
166
|
+
readonly schema: SqlSchemaIR;
|
|
167
|
+
readonly policy: MigrationOperationPolicy;
|
|
168
|
+
readonly schemaName?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Active framework components participating in this composition.
|
|
171
|
+
* SQL targets can interpret this list to derive database dependencies.
|
|
172
|
+
* All components must have matching familyId ('sql') and targetId.
|
|
173
|
+
*/
|
|
174
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* SQL migration planner interface.
|
|
178
|
+
* Extends the core MigrationPlanner with SQL-specific types.
|
|
179
|
+
*/
|
|
180
|
+
interface SqlMigrationPlanner<TTargetDetails = Record<string, never>> {
|
|
181
|
+
plan(options: SqlMigrationPlannerPlanOptions): SqlPlannerResult<TTargetDetails>;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Callbacks for SQL migration runner execution.
|
|
185
|
+
*/
|
|
186
|
+
interface SqlMigrationRunnerExecuteCallbacks<TTargetDetails = Record<string, never>> {
|
|
187
|
+
onOperationStart?(operation: SqlMigrationPlanOperation<TTargetDetails>): void;
|
|
188
|
+
onOperationComplete?(operation: SqlMigrationPlanOperation<TTargetDetails>): void;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Options for SQL migration runner execution.
|
|
192
|
+
*/
|
|
193
|
+
interface SqlMigrationRunnerExecuteOptions<TTargetDetails = Record<string, never>> {
|
|
194
|
+
readonly plan: SqlMigrationPlan<TTargetDetails>;
|
|
195
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
196
|
+
/**
|
|
197
|
+
* Destination contract IR.
|
|
198
|
+
* Must correspond to `plan.destination` and is used for schema verification and marker/ledger writes.
|
|
199
|
+
*/
|
|
200
|
+
readonly destinationContract: SqlContract<SqlStorage>;
|
|
201
|
+
/**
|
|
202
|
+
* Execution-time policy that defines which operation classes are allowed.
|
|
203
|
+
* The runner validates each operation against this policy before execution.
|
|
204
|
+
*/
|
|
205
|
+
readonly policy: MigrationOperationPolicy;
|
|
206
|
+
readonly schemaName?: string;
|
|
207
|
+
readonly strictVerification?: boolean;
|
|
208
|
+
readonly callbacks?: SqlMigrationRunnerExecuteCallbacks<TTargetDetails>;
|
|
209
|
+
readonly context?: OperationContext;
|
|
210
|
+
/**
|
|
211
|
+
* Active framework components participating in this composition.
|
|
212
|
+
* SQL targets can interpret this list to derive database dependencies.
|
|
213
|
+
* All components must have matching familyId ('sql') and targetId.
|
|
214
|
+
*/
|
|
215
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Error codes for SQL migration runner failures.
|
|
219
|
+
*/
|
|
220
|
+
type SqlMigrationRunnerErrorCode = 'DESTINATION_CONTRACT_MISMATCH' | 'MARKER_ORIGIN_MISMATCH' | 'POLICY_VIOLATION' | 'PRECHECK_FAILED' | 'POSTCHECK_FAILED' | 'SCHEMA_VERIFY_FAILED' | 'EXECUTION_FAILED';
|
|
221
|
+
/**
|
|
222
|
+
* Detailed information about a SQL migration runner failure.
|
|
223
|
+
* Extends the core MigrationRunnerFailure with SQL-specific error codes.
|
|
224
|
+
*/
|
|
225
|
+
interface SqlMigrationRunnerFailure extends MigrationRunnerFailure {
|
|
226
|
+
readonly code: SqlMigrationRunnerErrorCode;
|
|
227
|
+
readonly meta?: AnyRecord;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Success value for SQL migration runner execution.
|
|
231
|
+
* Extends core type for type branding and potential SQL-specific extensions.
|
|
232
|
+
*/
|
|
233
|
+
interface SqlMigrationRunnerSuccessValue extends MigrationRunnerSuccessValue {
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Result type for SQL migration runner execution.
|
|
237
|
+
*/
|
|
238
|
+
type SqlMigrationRunnerResult = Result<SqlMigrationRunnerSuccessValue, SqlMigrationRunnerFailure>;
|
|
239
|
+
/**
|
|
240
|
+
* SQL migration runner interface.
|
|
241
|
+
* Extends the core MigrationRunner with SQL-specific types.
|
|
242
|
+
*/
|
|
243
|
+
interface SqlMigrationRunner<TTargetDetails = Record<string, never>> {
|
|
244
|
+
execute(options: SqlMigrationRunnerExecuteOptions<TTargetDetails>): Promise<SqlMigrationRunnerResult>;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* SQL control target descriptor with migration support.
|
|
248
|
+
* Extends the core ControlTargetDescriptor with SQL-specific migration methods.
|
|
249
|
+
*/
|
|
250
|
+
interface SqlControlTargetDescriptor<TTargetId extends string, TTargetDetails = Record<string, never>> extends ControlTargetDescriptor<'sql', TTargetId, ControlTargetInstance<'sql', TTargetId>, SqlControlFamilyInstance> {
|
|
251
|
+
/**
|
|
252
|
+
* Creates a SQL migration planner for this target.
|
|
253
|
+
* Direct method for SQL-specific usage.
|
|
254
|
+
*/
|
|
255
|
+
createPlanner(family: SqlControlFamilyInstance): SqlMigrationPlanner<TTargetDetails>;
|
|
256
|
+
/**
|
|
257
|
+
* Creates a SQL migration runner for this target.
|
|
258
|
+
* Direct method for SQL-specific usage.
|
|
259
|
+
*/
|
|
260
|
+
createRunner(family: SqlControlFamilyInstance): SqlMigrationRunner<TTargetDetails>;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Options for creating a SQL migration plan.
|
|
264
|
+
*/
|
|
265
|
+
interface CreateSqlMigrationPlanOptions<TTargetDetails> {
|
|
266
|
+
readonly targetId: string;
|
|
267
|
+
readonly origin?: SqlMigrationPlanContractInfo | null;
|
|
268
|
+
readonly destination: SqlMigrationPlanContractInfo;
|
|
269
|
+
readonly operations: readonly SqlMigrationPlanOperation<TTargetDetails>[];
|
|
270
|
+
readonly meta?: AnyRecord;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Type metadata for SQL storage types.
|
|
275
|
+
* Maps contract storage type IDs to native database types.
|
|
276
|
+
*/
|
|
277
|
+
interface SqlTypeMetadata {
|
|
278
|
+
readonly typeId: string;
|
|
279
|
+
readonly familyId: 'sql';
|
|
280
|
+
readonly targetId: string;
|
|
281
|
+
readonly nativeType?: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Registry mapping type IDs to their metadata.
|
|
285
|
+
* Keyed by contract storage type ID (e.g., 'pg/int4@1').
|
|
286
|
+
*/
|
|
287
|
+
type SqlTypeMetadataRegistry = Map<string, SqlTypeMetadata>;
|
|
288
|
+
/**
|
|
289
|
+
* State fields for SQL family instance that hold assembly data.
|
|
290
|
+
*/
|
|
291
|
+
interface SqlFamilyInstanceState {
|
|
292
|
+
readonly operationRegistry: OperationRegistry;
|
|
293
|
+
readonly codecTypeImports: ReadonlyArray<TypesImportSpec>;
|
|
294
|
+
readonly operationTypeImports: ReadonlyArray<TypesImportSpec>;
|
|
295
|
+
readonly extensionIds: ReadonlyArray<string>;
|
|
296
|
+
readonly typeMetadataRegistry: SqlTypeMetadataRegistry;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Options for schema verification.
|
|
300
|
+
*/
|
|
301
|
+
interface SchemaVerifyOptions {
|
|
302
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
303
|
+
readonly contractIR: unknown;
|
|
304
|
+
readonly strict: boolean;
|
|
305
|
+
readonly context?: OperationContext;
|
|
306
|
+
/**
|
|
307
|
+
* Active framework components participating in this composition.
|
|
308
|
+
* All components must have matching familyId ('sql') and targetId.
|
|
309
|
+
*/
|
|
310
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* SQL control family instance interface.
|
|
314
|
+
* Extends ControlFamilyInstance with SQL-specific domain actions.
|
|
315
|
+
*/
|
|
316
|
+
interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql'>, SqlFamilyInstanceState {
|
|
317
|
+
/**
|
|
318
|
+
* Validates a contract JSON and returns a validated ContractIR (without mappings).
|
|
319
|
+
* Mappings are runtime-only and should not be part of ContractIR.
|
|
320
|
+
*/
|
|
321
|
+
validateContractIR(contractJson: unknown): ContractIR;
|
|
322
|
+
/**
|
|
323
|
+
* Verifies the database marker against the contract.
|
|
324
|
+
* Compares target, coreHash, and profileHash.
|
|
325
|
+
*/
|
|
326
|
+
verify(options: {
|
|
327
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
328
|
+
readonly contractIR: unknown;
|
|
329
|
+
readonly expectedTargetId: string;
|
|
330
|
+
readonly contractPath: string;
|
|
331
|
+
readonly configPath?: string;
|
|
332
|
+
}): Promise<VerifyDatabaseResult>;
|
|
333
|
+
/**
|
|
334
|
+
* Verifies the database schema against the contract.
|
|
335
|
+
* Compares contract requirements against live database schema.
|
|
336
|
+
*/
|
|
337
|
+
schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult>;
|
|
338
|
+
/**
|
|
339
|
+
* Signs the database with the contract marker.
|
|
340
|
+
* Writes or updates the contract marker if schema verification passes.
|
|
341
|
+
* This operation is idempotent - if the marker already matches, no changes are made.
|
|
342
|
+
*/
|
|
343
|
+
sign(options: {
|
|
344
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
345
|
+
readonly contractIR: unknown;
|
|
346
|
+
readonly contractPath: string;
|
|
347
|
+
readonly configPath?: string;
|
|
348
|
+
}): Promise<SignDatabaseResult>;
|
|
349
|
+
/**
|
|
350
|
+
* Introspects the database schema and returns a family-specific schema IR.
|
|
351
|
+
*
|
|
352
|
+
* This is a read-only operation that returns a snapshot of the live database schema.
|
|
353
|
+
* The method is family-owned and delegates to target/adapter-specific introspectors
|
|
354
|
+
* to perform the actual schema introspection.
|
|
355
|
+
*
|
|
356
|
+
* @param options - Introspection options
|
|
357
|
+
* @param options.driver - Control plane driver for database connection
|
|
358
|
+
* @param options.contractIR - Optional contract IR for contract-guided introspection.
|
|
359
|
+
* When provided, families may use it for filtering, optimization, or validation
|
|
360
|
+
* during introspection. The contract IR does not change the meaning of "what exists"
|
|
361
|
+
* in the database - it only guides how introspection is performed.
|
|
362
|
+
* @returns Promise resolving to the family-specific Schema IR (e.g., `SqlSchemaIR` for SQL).
|
|
363
|
+
* The IR represents the complete schema snapshot at the time of introspection.
|
|
364
|
+
*/
|
|
365
|
+
introspect(options: {
|
|
366
|
+
readonly driver: ControlDriverInstance<'sql', string>;
|
|
367
|
+
readonly contractIR?: unknown;
|
|
368
|
+
}): Promise<SqlSchemaIR>;
|
|
369
|
+
/**
|
|
370
|
+
* Projects a SQL Schema IR into a core schema view for CLI visualization.
|
|
371
|
+
* Converts SqlSchemaIR (tables, columns, indexes, extensions) into a tree structure.
|
|
372
|
+
*/
|
|
373
|
+
toSchemaView(schema: SqlSchemaIR): CoreSchemaView;
|
|
374
|
+
/**
|
|
375
|
+
* Emits contract JSON and DTS as strings.
|
|
376
|
+
* Uses the instance's preassembled state (operation registry, type imports, extension IDs).
|
|
377
|
+
* Handles stripping mappings and validation internally.
|
|
378
|
+
*/
|
|
379
|
+
emitContract(options: {
|
|
380
|
+
readonly contractIR: ContractIR | unknown;
|
|
381
|
+
}): Promise<EmitContractResult>;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export type { AnyRecord as A, CreateSqlMigrationPlanOptions as C, SqlControlFamilyInstance as S, SqlControlTargetDescriptor as a, SqlMigrationPlan as b, SqlPlannerConflict as c, SqlPlannerFailureResult as d, SqlPlannerSuccessResult as e, SqlMigrationRunnerErrorCode as f, SqlMigrationRunnerFailure as g, SqlMigrationRunnerSuccessValue as h, SchemaVerifyOptions as i, ComponentDatabaseDependencies as j, ComponentDatabaseDependency as k, SqlControlExtensionDescriptor as l, SqlMigrationPlanContractInfo as m, SqlMigrationPlanner as n, SqlMigrationPlannerPlanOptions as o, SqlMigrationPlanOperation as p, SqlMigrationPlanOperationStep as q, SqlMigrationPlanOperationTarget as r, SqlMigrationRunner as s, SqlMigrationRunnerExecuteCallbacks as t, SqlMigrationRunnerExecuteOptions as u, SqlMigrationRunnerResult as v, SqlPlannerConflictKind as w, SqlPlannerConflictLocation as x, SqlPlannerResult as y };
|
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import { OperationContext, VerifyDatabaseSchemaResult } from '@prisma-next/core-control-plane/types';
|
|
2
|
-
import { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
1
|
+
import { SchemaIssue, SchemaVerificationNode, OperationContext, VerifyDatabaseSchemaResult } from '@prisma-next/core-control-plane/types';
|
|
3
2
|
import { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
3
|
+
import { k as ComponentDatabaseDependency } from './instance-BDpyIYu5.js';
|
|
4
|
+
import { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
|
|
5
|
+
import { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
6
|
+
import '@prisma-next/utils/result';
|
|
7
|
+
import '@prisma-next/contract/ir';
|
|
8
|
+
import '@prisma-next/contract/types';
|
|
9
|
+
import '@prisma-next/core-control-plane/schema-view';
|
|
10
|
+
import '@prisma-next/operations';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Pure verification helper functions for SQL schema verification.
|
|
14
|
+
* These functions verify schema IR against contract requirements.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Verifies database dependencies are installed using component-owned verification hooks.
|
|
19
|
+
* Each dependency provides a pure verifyDatabaseDependencyInstalled function that checks
|
|
20
|
+
* whether the dependency is satisfied based on the in-memory schema IR (no DB I/O).
|
|
21
|
+
*
|
|
22
|
+
* Returns verification nodes for the tree.
|
|
23
|
+
*/
|
|
24
|
+
declare function verifyDatabaseDependencies(dependencies: ReadonlyArray<ComponentDatabaseDependency<unknown>>, schema: SqlSchemaIR, issues: SchemaIssue[]): SchemaVerificationNode[];
|
|
4
25
|
|
|
5
26
|
/**
|
|
6
27
|
* Pure SQL schema verification function.
|
|
@@ -26,6 +47,11 @@ interface VerifySqlSchemaOptions {
|
|
|
26
47
|
readonly typeMetadataRegistry: ReadonlyMap<string, {
|
|
27
48
|
nativeType?: string;
|
|
28
49
|
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Active framework components participating in this composition.
|
|
52
|
+
* All components must have matching familyId ('sql') and targetId.
|
|
53
|
+
*/
|
|
54
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
29
55
|
}
|
|
30
56
|
/**
|
|
31
57
|
* Verifies that a SqlSchemaIR matches a SqlContract.
|
|
@@ -39,4 +65,4 @@ interface VerifySqlSchemaOptions {
|
|
|
39
65
|
*/
|
|
40
66
|
declare function verifySqlSchema(options: VerifySqlSchemaOptions): VerifyDatabaseSchemaResult;
|
|
41
67
|
|
|
42
|
-
export { type VerifySqlSchemaOptions, verifySqlSchema };
|
|
68
|
+
export { type VerifySqlSchemaOptions, verifyDatabaseDependencies, verifySqlSchema };
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
extractCodecTypeImportsFromPacks,
|
|
4
4
|
extractExtensionIdsFromPacks,
|
|
5
5
|
extractOperationTypeImportsFromPacks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NUALBK4N.js";
|
|
7
7
|
import "./chunk-2L5DCW2L.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-6AMLAAA2.js";
|
|
9
9
|
export {
|
|
10
10
|
assembleOperationRegistryFromPacks,
|
|
11
11
|
extractCodecTypeImportsFromPacks,
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/family-sql",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "SQL family descriptor for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.0.0",
|
|
9
|
-
"@prisma-next/
|
|
10
|
-
"@prisma-next/
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/
|
|
13
|
-
"@prisma-next/
|
|
14
|
-
"@prisma-next/
|
|
15
|
-
"@prisma-next/sql-contract
|
|
16
|
-
"@prisma-next/
|
|
17
|
-
"@prisma-next/sql-operations": "0.1.0-dev.
|
|
18
|
-
"@prisma-next/sql-
|
|
19
|
-
"@prisma-next/sql-
|
|
20
|
-
"@prisma-next/sql-
|
|
21
|
-
"@prisma-next/
|
|
22
|
-
"@prisma-next/
|
|
9
|
+
"@prisma-next/contract": "0.1.0-dev.20",
|
|
10
|
+
"@prisma-next/core-control-plane": "0.1.0-dev.20",
|
|
11
|
+
"@prisma-next/operations": "0.1.0-dev.20",
|
|
12
|
+
"@prisma-next/runtime-executor": "0.1.0-dev.20",
|
|
13
|
+
"@prisma-next/sql-contract-emitter": "0.1.0-dev.20",
|
|
14
|
+
"@prisma-next/sql-contract-ts": "0.1.0-dev.20",
|
|
15
|
+
"@prisma-next/sql-contract": "0.1.0-dev.20",
|
|
16
|
+
"@prisma-next/core-execution-plane": "0.1.0-dev.20",
|
|
17
|
+
"@prisma-next/sql-operations": "0.1.0-dev.20",
|
|
18
|
+
"@prisma-next/sql-relational-core": "0.1.0-dev.20",
|
|
19
|
+
"@prisma-next/sql-runtime": "0.1.0-dev.20",
|
|
20
|
+
"@prisma-next/sql-schema-ir": "0.1.0-dev.20",
|
|
21
|
+
"@prisma-next/utils": "0.1.0-dev.20",
|
|
22
|
+
"@prisma-next/cli": "0.1.0-dev.20"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"tsup": "^8.3.0",
|
|
26
26
|
"typescript": "^5.9.3",
|
|
27
27
|
"vite-tsconfig-paths": "^5.1.4",
|
|
28
28
|
"vitest": "^4.0.16",
|
|
29
|
-
"@prisma-next/driver-postgres": "0.1.0-dev.
|
|
29
|
+
"@prisma-next/driver-postgres": "0.1.0-dev.20",
|
|
30
30
|
"@prisma-next/test-utils": "0.0.1"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/schema-verify/verify-sql-schema.ts","../../src/core/schema-verify/verify-helpers.ts"],"sourcesContent":["/**\n * Pure SQL schema verification function.\n *\n * This module provides a pure function that verifies a SqlSchemaIR against\n * a SqlContract without requiring a database connection. It can be reused\n * by migration planners and other tools that need to compare schema states.\n */\n\nimport type {\n OperationContext,\n SchemaIssue,\n SchemaVerificationNode,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport {\n computeCounts,\n verifyExtensions,\n verifyForeignKeys,\n verifyIndexes,\n verifyPrimaryKey,\n verifyUniqueConstraints,\n} from './verify-helpers';\n\n/**\n * Options for the pure schema verification function.\n */\nexport interface VerifySqlSchemaOptions {\n /** The validated SQL contract to verify against */\n readonly contract: SqlContract<SqlStorage>;\n /** The schema IR from introspection (or another source) */\n readonly schema: SqlSchemaIR;\n /** Whether to run in strict mode (detects extra tables/columns) */\n readonly strict: boolean;\n /** Optional operation context for metadata */\n readonly context?: OperationContext;\n /** Type metadata registry for codec consistency warnings */\n readonly typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n}\n\n/**\n * Verifies that a SqlSchemaIR matches a SqlContract.\n *\n * This is a pure function that does NOT perform any database I/O.\n * It takes an already-introspected schema IR and compares it against\n * the contract requirements.\n *\n * @param options - Verification options\n * @returns VerifyDatabaseSchemaResult with verification tree and issues\n */\nexport function verifySqlSchema(options: VerifySqlSchemaOptions): VerifyDatabaseSchemaResult {\n const { contract, schema, strict, context, typeMetadataRegistry } = options;\n const startTime = Date.now();\n\n // Extract contract hashes and target\n const contractCoreHash = contract.coreHash;\n const contractProfileHash =\n 'profileHash' in contract && typeof contract.profileHash === 'string'\n ? contract.profileHash\n : undefined;\n const contractTarget = contract.target;\n\n // Compare contract vs schema IR\n const issues: SchemaIssue[] = [];\n const rootChildren: SchemaVerificationNode[] = [];\n\n // Compare tables\n const contractTables = contract.storage.tables;\n const schemaTables = schema.tables;\n\n for (const [tableName, contractTable] of Object.entries(contractTables)) {\n const schemaTable = schemaTables[tableName];\n const tablePath = `storage.tables.${tableName}`;\n\n if (!schemaTable) {\n // Missing table\n issues.push({\n kind: 'missing_table',\n table: tableName,\n message: `Table \"${tableName}\" is missing from database`,\n });\n rootChildren.push({\n status: 'fail',\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: tablePath,\n code: 'missing_table',\n message: `Table \"${tableName}\" is missing`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n continue;\n }\n\n // Table exists - compare columns, constraints, etc.\n const tableChildren: SchemaVerificationNode[] = [];\n const columnNodes: SchemaVerificationNode[] = [];\n\n // Compare columns\n for (const [columnName, contractColumn] of Object.entries(contractTable.columns)) {\n const schemaColumn = schemaTable.columns[columnName];\n const columnPath = `${tablePath}.columns.${columnName}`;\n\n if (!schemaColumn) {\n // Missing column\n issues.push({\n kind: 'missing_column',\n table: tableName,\n column: columnName,\n message: `Column \"${tableName}\".\"${columnName}\" is missing from database`,\n });\n columnNodes.push({\n status: 'fail',\n kind: 'column',\n name: `${columnName}: missing`,\n contractPath: columnPath,\n code: 'missing_column',\n message: `Column \"${columnName}\" is missing`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n continue;\n }\n\n // Column exists - compare type and nullability\n const columnChildren: SchemaVerificationNode[] = [];\n let columnStatus: 'pass' | 'warn' | 'fail' = 'pass';\n\n // Compare type using nativeType directly\n // Both contractColumn.nativeType and schemaColumn.nativeType are required by their types\n const contractNativeType = contractColumn.nativeType;\n const schemaNativeType = schemaColumn.nativeType;\n\n if (contractNativeType !== schemaNativeType) {\n // Compare native types directly\n issues.push({\n kind: 'type_mismatch',\n table: tableName,\n column: columnName,\n expected: contractNativeType,\n actual: schemaNativeType,\n message: `Column \"${tableName}\".\"${columnName}\" has type mismatch: expected \"${contractNativeType}\", got \"${schemaNativeType}\"`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'type',\n name: 'type',\n contractPath: `${columnPath}.nativeType`,\n code: 'type_mismatch',\n message: `Type mismatch: expected ${contractNativeType}, got ${schemaNativeType}`,\n expected: contractNativeType,\n actual: schemaNativeType,\n children: [],\n });\n columnStatus = 'fail';\n }\n\n // Optionally validate that codecId (if present) and nativeType agree with registry\n if (contractColumn.codecId) {\n const typeMetadata = typeMetadataRegistry.get(contractColumn.codecId);\n if (!typeMetadata) {\n // Warning: codecId not found in registry\n columnChildren.push({\n status: 'warn',\n kind: 'type',\n name: 'type_metadata_missing',\n contractPath: `${columnPath}.codecId`,\n code: 'type_metadata_missing',\n message: `codecId \"${contractColumn.codecId}\" not found in type metadata registry`,\n expected: contractColumn.codecId,\n actual: undefined,\n children: [],\n });\n } else if (typeMetadata.nativeType && typeMetadata.nativeType !== contractNativeType) {\n // Warning: codecId and nativeType don't agree with registry\n columnChildren.push({\n status: 'warn',\n kind: 'type',\n name: 'type_consistency',\n contractPath: `${columnPath}.codecId`,\n code: 'type_consistency_warning',\n message: `codecId \"${contractColumn.codecId}\" maps to nativeType \"${typeMetadata.nativeType}\" in registry, but contract has \"${contractNativeType}\"`,\n expected: typeMetadata.nativeType,\n actual: contractNativeType,\n children: [],\n });\n }\n }\n\n // Compare nullability\n if (contractColumn.nullable !== schemaColumn.nullable) {\n issues.push({\n kind: 'nullability_mismatch',\n table: tableName,\n column: columnName,\n expected: String(contractColumn.nullable),\n actual: String(schemaColumn.nullable),\n message: `Column \"${tableName}\".\"${columnName}\" has nullability mismatch: expected ${contractColumn.nullable ? 'nullable' : 'not null'}, got ${schemaColumn.nullable ? 'nullable' : 'not null'}`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'nullability',\n name: 'nullability',\n contractPath: `${columnPath}.nullable`,\n code: 'nullability_mismatch',\n message: `Nullability mismatch: expected ${contractColumn.nullable ? 'nullable' : 'not null'}, got ${schemaColumn.nullable ? 'nullable' : 'not null'}`,\n expected: contractColumn.nullable,\n actual: schemaColumn.nullable,\n children: [],\n });\n columnStatus = 'fail';\n }\n\n // Compute column status from children (fail > warn > pass)\n const computedColumnStatus = columnChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : columnChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Use computed status if we have children, otherwise use the manually set status\n const finalColumnStatus = columnChildren.length > 0 ? computedColumnStatus : columnStatus;\n\n // Build column node\n const nullableText = contractColumn.nullable ? 'nullable' : 'not nullable';\n const columnTypeDisplay = contractColumn.codecId\n ? `${contractNativeType} (${contractColumn.codecId})`\n : contractNativeType;\n // Collect failure messages from children to create a summary message\n const failureMessages = columnChildren\n .filter((child) => child.status === 'fail' && child.message)\n .map((child) => child.message)\n .filter((msg): msg is string => typeof msg === 'string' && msg.length > 0);\n const columnMessage =\n finalColumnStatus === 'fail' && failureMessages.length > 0\n ? failureMessages.join('; ')\n : '';\n // Extract code from first child if status indicates an issue\n const columnCode =\n (finalColumnStatus === 'fail' || finalColumnStatus === 'warn') && columnChildren[0]\n ? columnChildren[0].code\n : '';\n columnNodes.push({\n status: finalColumnStatus,\n kind: 'column',\n name: `${columnName}: ${columnTypeDisplay} (${nullableText})`,\n contractPath: columnPath,\n code: columnCode,\n message: columnMessage,\n expected: undefined,\n actual: undefined,\n children: columnChildren,\n });\n }\n\n // Group columns under a \"columns\" header if we have any columns\n if (columnNodes.length > 0) {\n const columnsStatus = columnNodes.some((c) => c.status === 'fail')\n ? 'fail'\n : columnNodes.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n tableChildren.push({\n status: columnsStatus,\n kind: 'columns',\n name: 'columns',\n contractPath: `${tablePath}.columns`,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: columnNodes,\n });\n }\n\n // Check for extra columns in strict mode\n if (strict) {\n for (const [columnName, { nativeType }] of Object.entries(schemaTable.columns)) {\n if (!contractTable.columns[columnName]) {\n issues.push({\n kind: 'extra_column',\n table: tableName,\n column: columnName,\n message: `Extra column \"${tableName}\".\"${columnName}\" found in database (not in contract)`,\n });\n columnNodes.push({\n status: 'fail',\n kind: 'column',\n name: `${columnName}: extra`,\n contractPath: `${tablePath}.columns.${columnName}`,\n code: 'extra_column',\n message: `Extra column \"${columnName}\" found`,\n expected: undefined,\n actual: nativeType,\n children: [],\n });\n }\n }\n }\n\n // Compare primary key\n if (contractTable.primaryKey) {\n const pkStatus = verifyPrimaryKey(\n contractTable.primaryKey,\n schemaTable.primaryKey,\n tableName,\n issues,\n );\n if (pkStatus === 'fail') {\n tableChildren.push({\n status: 'fail',\n kind: 'primaryKey',\n name: `primary key: ${contractTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: 'primary_key_mismatch',\n message: 'Primary key mismatch',\n expected: contractTable.primaryKey,\n actual: schemaTable.primaryKey,\n children: [],\n });\n } else {\n tableChildren.push({\n status: 'pass',\n kind: 'primaryKey',\n name: `primary key: ${contractTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n } else if (schemaTable.primaryKey && strict) {\n // Extra primary key in strict mode\n issues.push({\n kind: 'extra_primary_key',\n table: tableName,\n message: 'Extra primary key found in database (not in contract)',\n });\n tableChildren.push({\n status: 'fail',\n kind: 'primaryKey',\n name: `primary key: ${schemaTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: 'extra_primary_key',\n message: 'Extra primary key found',\n expected: undefined,\n actual: schemaTable.primaryKey,\n children: [],\n });\n }\n\n // Compare foreign keys\n const fkStatuses = verifyForeignKeys(\n contractTable.foreignKeys,\n schemaTable.foreignKeys,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...fkStatuses);\n\n // Compare unique constraints\n const uniqueStatuses = verifyUniqueConstraints(\n contractTable.uniques,\n schemaTable.uniques,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...uniqueStatuses);\n\n // Compare indexes\n const indexStatuses = verifyIndexes(\n contractTable.indexes,\n schemaTable.indexes,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...indexStatuses);\n\n // Build table node\n const tableStatus = tableChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : tableChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Collect failure messages from children to create a summary message\n const tableFailureMessages = tableChildren\n .filter((child) => child.status === 'fail' && child.message)\n .map((child) => child.message)\n .filter((msg): msg is string => typeof msg === 'string' && msg.length > 0);\n const tableMessage =\n tableStatus === 'fail' && tableFailureMessages.length > 0\n ? `${tableFailureMessages.length} issue${tableFailureMessages.length === 1 ? '' : 's'}`\n : '';\n const tableCode =\n tableStatus === 'fail' && tableChildren.length > 0 && tableChildren[0]\n ? tableChildren[0].code\n : '';\n rootChildren.push({\n status: tableStatus,\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: tablePath,\n code: tableCode,\n message: tableMessage,\n expected: undefined,\n actual: undefined,\n children: tableChildren,\n });\n }\n\n // Check for extra tables in strict mode\n if (strict) {\n for (const tableName of Object.keys(schemaTables)) {\n if (!contractTables[tableName]) {\n issues.push({\n kind: 'extra_table',\n table: tableName,\n message: `Extra table \"${tableName}\" found in database (not in contract)`,\n });\n rootChildren.push({\n status: 'fail',\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: `storage.tables.${tableName}`,\n code: 'extra_table',\n message: `Extra table \"${tableName}\" found`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n // Compare extensions\n const extensionStatuses = verifyExtensions(\n contract.extensions,\n schema.extensions,\n contractTarget,\n issues,\n strict,\n );\n rootChildren.push(...extensionStatuses);\n\n // Build root node\n const rootStatus = rootChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : rootChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n const root: SchemaVerificationNode = {\n status: rootStatus,\n kind: 'contract',\n name: 'contract',\n contractPath: '',\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: rootChildren,\n };\n\n // Compute counts\n const counts = computeCounts(root);\n\n // Set ok flag\n const ok = counts.fail === 0;\n\n // Set code\n const code = ok ? undefined : 'PN-SCHEMA-0001';\n\n // Set summary\n const summary = ok\n ? 'Database schema satisfies contract'\n : `Database schema does not satisfy contract (${counts.fail} failure${counts.fail === 1 ? '' : 's'})`;\n\n const totalTime = Date.now() - startTime;\n\n return {\n ok,\n ...ifDefined('code', code),\n summary,\n contract: {\n coreHash: contractCoreHash,\n ...ifDefined('profileHash', contractProfileHash),\n },\n target: {\n expected: contractTarget,\n actual: contractTarget,\n },\n schema: {\n issues,\n root,\n counts,\n },\n meta: {\n strict,\n ...ifDefined('contractPath', context?.contractPath),\n ...ifDefined('configPath', context?.configPath),\n },\n timings: {\n total: totalTime,\n },\n };\n}\n","/**\n * Pure verification helper functions for SQL schema verification.\n * These functions verify schema IR against contract requirements.\n */\n\nimport type { SchemaIssue, SchemaVerificationNode } from '@prisma-next/core-control-plane/types';\nimport type {\n ForeignKey,\n Index,\n PrimaryKey,\n UniqueConstraint,\n} from '@prisma-next/sql-contract/types';\nimport type { SqlForeignKeyIR, SqlIndexIR, SqlUniqueIR } from '@prisma-next/sql-schema-ir/types';\n\n/**\n * Compares two arrays of strings for equality (order-sensitive).\n */\nexport function arraysEqual(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Verifies primary key matches between contract and schema.\n * Returns 'pass' or 'fail'.\n */\nexport function verifyPrimaryKey(\n contractPK: PrimaryKey,\n schemaPK: PrimaryKey | undefined,\n tableName: string,\n issues: SchemaIssue[],\n): 'pass' | 'fail' {\n if (!schemaPK) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\n expected: contractPK.columns.join(', '),\n message: `Table \"${tableName}\" is missing primary key`,\n });\n return 'fail';\n }\n\n if (!arraysEqual(contractPK.columns, schemaPK.columns)) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\n expected: contractPK.columns.join(', '),\n actual: schemaPK.columns.join(', '),\n message: `Table \"${tableName}\" has primary key mismatch: expected columns [${contractPK.columns.join(', ')}], got [${schemaPK.columns.join(', ')}]`,\n });\n return 'fail';\n }\n\n // Compare name if both are modeled\n if (contractPK.name && schemaPK.name && contractPK.name !== schemaPK.name) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\n indexOrConstraint: contractPK.name,\n expected: contractPK.name,\n actual: schemaPK.name,\n message: `Table \"${tableName}\" has primary key name mismatch: expected \"${contractPK.name}\", got \"${schemaPK.name}\"`,\n });\n return 'fail';\n }\n\n return 'pass';\n}\n\n/**\n * Verifies foreign keys match between contract and schema.\n * Returns verification nodes for the tree.\n */\nexport function verifyForeignKeys(\n contractFKs: readonly ForeignKey[],\n schemaFKs: readonly SqlForeignKeyIR[],\n tableName: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract FK exists in schema\n for (const contractFK of contractFKs) {\n const fkPath = `${tablePath}.foreignKeys[${contractFK.columns.join(',')}]`;\n const matchingFK = schemaFKs.find((fk) => {\n return (\n arraysEqual(fk.columns, contractFK.columns) &&\n fk.referencedTable === contractFK.references.table &&\n arraysEqual(fk.referencedColumns, contractFK.references.columns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n expected: `${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n message: `Table \"${tableName}\" is missing foreign key: ${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.columns.join(', ')})`,\n contractPath: fkPath,\n code: 'foreign_key_mismatch',\n message: 'Foreign key missing',\n expected: contractFK,\n actual: undefined,\n children: [],\n });\n } else {\n // Compare name if both are modeled\n if (contractFK.name && matchingFK.name && contractFK.name !== matchingFK.name) {\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n indexOrConstraint: contractFK.name,\n expected: contractFK.name,\n actual: matchingFK.name,\n message: `Table \"${tableName}\" has foreign key name mismatch: expected \"${contractFK.name}\", got \"${matchingFK.name}\"`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.columns.join(', ')})`,\n contractPath: fkPath,\n code: 'foreign_key_mismatch',\n message: 'Foreign key name mismatch',\n expected: contractFK.name,\n actual: matchingFK.name,\n children: [],\n });\n } else {\n nodes.push({\n status: 'pass',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.columns.join(', ')})`,\n contractPath: fkPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n // Check for extra FKs in strict mode\n if (strict) {\n for (const schemaFK of schemaFKs) {\n const matchingFK = contractFKs.find((fk) => {\n return (\n arraysEqual(fk.columns, schemaFK.columns) &&\n fk.references.table === schemaFK.referencedTable &&\n arraysEqual(fk.references.columns, schemaFK.referencedColumns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'extra_foreign_key',\n table: tableName,\n message: `Extra foreign key found in database (not in contract): ${schemaFK.columns.join(', ')} -> ${schemaFK.referencedTable}(${schemaFK.referencedColumns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${schemaFK.columns.join(', ')})`,\n contractPath: `${tablePath}.foreignKeys[${schemaFK.columns.join(',')}]`,\n code: 'extra_foreign_key',\n message: 'Extra foreign key found',\n expected: undefined,\n actual: schemaFK,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Verifies unique constraints match between contract and schema.\n * Returns verification nodes for the tree.\n */\nexport function verifyUniqueConstraints(\n contractUniques: readonly UniqueConstraint[],\n schemaUniques: readonly SqlUniqueIR[],\n tableName: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract unique exists in schema\n for (const contractUnique of contractUniques) {\n const uniquePath = `${tablePath}.uniques[${contractUnique.columns.join(',')}]`;\n const matchingUnique = schemaUniques.find((u) =>\n arraysEqual(u.columns, contractUnique.columns),\n );\n\n if (!matchingUnique) {\n issues.push({\n kind: 'unique_constraint_mismatch',\n table: tableName,\n expected: contractUnique.columns.join(', '),\n message: `Table \"${tableName}\" is missing unique constraint: ${contractUnique.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'unique',\n name: `unique(${contractUnique.columns.join(', ')})`,\n contractPath: uniquePath,\n code: 'unique_constraint_mismatch',\n message: 'Unique constraint missing',\n expected: contractUnique,\n actual: undefined,\n children: [],\n });\n } else {\n // Compare name if both are modeled\n if (\n contractUnique.name &&\n matchingUnique.name &&\n contractUnique.name !== matchingUnique.name\n ) {\n issues.push({\n kind: 'unique_constraint_mismatch',\n table: tableName,\n indexOrConstraint: contractUnique.name,\n expected: contractUnique.name,\n actual: matchingUnique.name,\n message: `Table \"${tableName}\" has unique constraint name mismatch: expected \"${contractUnique.name}\", got \"${matchingUnique.name}\"`,\n });\n nodes.push({\n status: 'fail',\n kind: 'unique',\n name: `unique(${contractUnique.columns.join(', ')})`,\n contractPath: uniquePath,\n code: 'unique_constraint_mismatch',\n message: 'Unique constraint name mismatch',\n expected: contractUnique.name,\n actual: matchingUnique.name,\n children: [],\n });\n } else {\n nodes.push({\n status: 'pass',\n kind: 'unique',\n name: `unique(${contractUnique.columns.join(', ')})`,\n contractPath: uniquePath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n // Check for extra uniques in strict mode\n if (strict) {\n for (const schemaUnique of schemaUniques) {\n const matchingUnique = contractUniques.find((u) =>\n arraysEqual(u.columns, schemaUnique.columns),\n );\n\n if (!matchingUnique) {\n issues.push({\n kind: 'extra_unique_constraint',\n table: tableName,\n message: `Extra unique constraint found in database (not in contract): ${schemaUnique.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'unique',\n name: `unique(${schemaUnique.columns.join(', ')})`,\n contractPath: `${tablePath}.uniques[${schemaUnique.columns.join(',')}]`,\n code: 'extra_unique_constraint',\n message: 'Extra unique constraint found',\n expected: undefined,\n actual: schemaUnique,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Verifies indexes match between contract and schema.\n * Returns verification nodes for the tree.\n */\nexport function verifyIndexes(\n contractIndexes: readonly Index[],\n schemaIndexes: readonly SqlIndexIR[],\n tableName: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract index exists in schema\n for (const contractIndex of contractIndexes) {\n const indexPath = `${tablePath}.indexes[${contractIndex.columns.join(',')}]`;\n const matchingIndex = schemaIndexes.find(\n (idx) => arraysEqual(idx.columns, contractIndex.columns) && idx.unique === false,\n );\n\n if (!matchingIndex) {\n issues.push({\n kind: 'index_mismatch',\n table: tableName,\n expected: contractIndex.columns.join(', '),\n message: `Table \"${tableName}\" is missing index: ${contractIndex.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: `index(${contractIndex.columns.join(', ')})`,\n contractPath: indexPath,\n code: 'index_mismatch',\n message: 'Index missing',\n expected: contractIndex,\n actual: undefined,\n children: [],\n });\n } else {\n // Compare name if both are modeled\n if (contractIndex.name && matchingIndex.name && contractIndex.name !== matchingIndex.name) {\n issues.push({\n kind: 'index_mismatch',\n table: tableName,\n indexOrConstraint: contractIndex.name,\n expected: contractIndex.name,\n actual: matchingIndex.name,\n message: `Table \"${tableName}\" has index name mismatch: expected \"${contractIndex.name}\", got \"${matchingIndex.name}\"`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: `index(${contractIndex.columns.join(', ')})`,\n contractPath: indexPath,\n code: 'index_mismatch',\n message: 'Index name mismatch',\n expected: contractIndex.name,\n actual: matchingIndex.name,\n children: [],\n });\n } else {\n nodes.push({\n status: 'pass',\n kind: 'index',\n name: `index(${contractIndex.columns.join(', ')})`,\n contractPath: indexPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n // Check for extra indexes in strict mode\n if (strict) {\n for (const schemaIndex of schemaIndexes) {\n // Skip unique indexes (they're handled as unique constraints)\n if (schemaIndex.unique) {\n continue;\n }\n\n const matchingIndex = contractIndexes.find((idx) =>\n arraysEqual(idx.columns, schemaIndex.columns),\n );\n\n if (!matchingIndex) {\n issues.push({\n kind: 'extra_index',\n table: tableName,\n message: `Extra index found in database (not in contract): ${schemaIndex.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: `index(${schemaIndex.columns.join(', ')})`,\n contractPath: `${tablePath}.indexes[${schemaIndex.columns.join(',')}]`,\n code: 'extra_index',\n message: 'Extra index found',\n expected: undefined,\n actual: schemaIndex,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Verifies required extensions exist in schema.\n * Extracts extension names from contract.extensions (keys) and compares with schemaIR.extensions.\n * Filters out the target name (e.g., 'postgres') as it's not an extension.\n * Returns verification nodes for the tree.\n */\nexport function verifyExtensions(\n contractExtensions: Record<string, unknown> | undefined,\n schemaExtensions: readonly string[],\n contractTarget: string,\n issues: SchemaIssue[],\n _strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n if (!contractExtensions) {\n return nodes;\n }\n\n // Extract extension names from contract (keys of extensions object)\n // Filter out the target name - it's not an extension (e.g., 'postgres' is the target, not an extension)\n const contractExtensionNames = Object.keys(contractExtensions).filter(\n (name) => name !== contractTarget,\n );\n\n // Check each contract extension exists in schema\n // Extension names in contract may differ from database extension names\n // (e.g., contract has 'pgvector' but database has 'vector')\n // We need to match more flexibly - try exact match, then check if either contains the other\n for (const extName of contractExtensionNames) {\n const extPath = `extensions.${extName}`;\n // Normalize extension names for comparison (remove common prefixes like 'pg')\n const normalizedExtName = extName.toLowerCase().replace(/^pg/, '');\n const matchingExt = schemaExtensions.find((e) => {\n const normalizedE = e.toLowerCase();\n // Exact match\n if (normalizedE === normalizedExtName || normalizedE === extName.toLowerCase()) {\n return true;\n }\n // Check if one contains the other (e.g., 'pgvector' contains 'vector', 'vector' is in 'pgvector')\n if (normalizedE.includes(normalizedExtName) || normalizedExtName.includes(normalizedE)) {\n return true;\n }\n return false;\n });\n\n // Map extension names to descriptive labels\n const extensionLabels: Record<string, string> = {\n pg: 'database is postgres',\n pgvector: 'vector extension is enabled',\n vector: 'vector extension is enabled',\n };\n const extensionLabel = extensionLabels[extName] ?? `extension \"${extName}\" is enabled`;\n\n if (!matchingExt) {\n issues.push({\n kind: 'extension_missing',\n table: '',\n message: `Extension \"${extName}\" is missing from database`,\n });\n nodes.push({\n status: 'fail',\n kind: 'extension',\n name: extensionLabel,\n contractPath: extPath,\n code: 'extension_missing',\n message: `Extension \"${extName}\" is missing`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n } else {\n nodes.push({\n status: 'pass',\n kind: 'extension',\n name: extensionLabel,\n contractPath: extPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n\n // In strict mode, we don't check for extra extensions (they're allowed)\n // Extensions are additive - having extra extensions doesn't break the contract\n\n return nodes;\n}\n\n/**\n * Computes counts of pass/warn/fail nodes by traversing the tree.\n */\nexport function computeCounts(node: SchemaVerificationNode): {\n pass: number;\n warn: number;\n fail: number;\n totalNodes: number;\n} {\n let pass = 0;\n let warn = 0;\n let fail = 0;\n\n function traverse(n: SchemaVerificationNode): void {\n if (n.status === 'pass') {\n pass++;\n } else if (n.status === 'warn') {\n warn++;\n } else if (n.status === 'fail') {\n fail++;\n }\n\n if (n.children) {\n for (const child of n.children) {\n traverse(child);\n }\n }\n }\n\n traverse(node);\n\n return {\n pass,\n warn,\n fail,\n totalNodes: pass + warn + fail,\n };\n}\n"],"mappings":"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","names":[]}
|