@prisma-next/target-postgres 0.3.0-pr.99.6 → 0.4.0-dev.2

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.
Files changed (66) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +17 -8
  3. package/dist/control.d.mts +19 -0
  4. package/dist/control.d.mts.map +1 -0
  5. package/dist/control.mjs +5382 -0
  6. package/dist/control.mjs.map +1 -0
  7. package/dist/descriptor-meta-CAf16lsJ.mjs +32 -0
  8. package/dist/descriptor-meta-CAf16lsJ.mjs.map +1 -0
  9. package/dist/migration-builders.d.mts +88 -0
  10. package/dist/migration-builders.d.mts.map +1 -0
  11. package/dist/migration-builders.mjs +3 -0
  12. package/dist/operation-descriptors-CxymFSgK.mjs +52 -0
  13. package/dist/operation-descriptors-CxymFSgK.mjs.map +1 -0
  14. package/dist/pack.d.mts +45 -0
  15. package/dist/pack.d.mts.map +1 -0
  16. package/dist/pack.mjs +9 -0
  17. package/dist/pack.mjs.map +1 -0
  18. package/dist/runtime.d.mts +9 -0
  19. package/dist/runtime.d.mts.map +1 -0
  20. package/dist/runtime.mjs +20 -0
  21. package/dist/runtime.mjs.map +1 -0
  22. package/package.json +31 -29
  23. package/src/core/authoring.ts +15 -0
  24. package/src/core/descriptor-meta.ts +5 -0
  25. package/src/core/migrations/descriptor-planner.ts +466 -0
  26. package/src/core/migrations/operation-descriptors.ts +166 -0
  27. package/src/core/migrations/operation-resolver.ts +929 -0
  28. package/src/core/migrations/planner-ddl-builders.ts +256 -0
  29. package/src/core/migrations/planner-identity-values.ts +135 -0
  30. package/src/core/migrations/planner-recipes.ts +91 -0
  31. package/src/core/migrations/planner-reconciliation.ts +798 -0
  32. package/src/core/migrations/planner-schema-lookup.ts +54 -0
  33. package/src/core/migrations/planner-sql-checks.ts +322 -0
  34. package/src/core/migrations/planner-strategies.ts +262 -0
  35. package/src/core/migrations/planner-target-details.ts +38 -0
  36. package/src/core/migrations/planner-type-resolution.ts +26 -0
  37. package/src/core/migrations/planner.ts +410 -460
  38. package/src/core/migrations/runner.ts +134 -38
  39. package/src/core/migrations/statement-builders.ts +6 -6
  40. package/src/core/types.ts +5 -0
  41. package/src/exports/control.ts +182 -12
  42. package/src/exports/migration-builders.ts +56 -0
  43. package/src/exports/pack.ts +7 -3
  44. package/src/exports/runtime.ts +6 -12
  45. package/dist/chunk-RKEXRSSI.js +0 -14
  46. package/dist/chunk-RKEXRSSI.js.map +0 -1
  47. package/dist/core/descriptor-meta.d.ts +0 -9
  48. package/dist/core/descriptor-meta.d.ts.map +0 -1
  49. package/dist/core/migrations/planner.d.ts +0 -14
  50. package/dist/core/migrations/planner.d.ts.map +0 -1
  51. package/dist/core/migrations/runner.d.ts +0 -8
  52. package/dist/core/migrations/runner.d.ts.map +0 -1
  53. package/dist/core/migrations/statement-builders.d.ts +0 -30
  54. package/dist/core/migrations/statement-builders.d.ts.map +0 -1
  55. package/dist/exports/control.d.ts +0 -8
  56. package/dist/exports/control.d.ts.map +0 -1
  57. package/dist/exports/control.js +0 -1260
  58. package/dist/exports/control.js.map +0 -1
  59. package/dist/exports/pack.d.ts +0 -4
  60. package/dist/exports/pack.d.ts.map +0 -1
  61. package/dist/exports/pack.js +0 -11
  62. package/dist/exports/pack.js.map +0 -1
  63. package/dist/exports/runtime.d.ts +0 -12
  64. package/dist/exports/runtime.d.ts.map +0 -1
  65. package/dist/exports/runtime.js +0 -19
  66. package/dist/exports/runtime.js.map +0 -1
@@ -1,1260 +0,0 @@
1
- import {
2
- postgresTargetDescriptorMeta
3
- } from "../chunk-RKEXRSSI.js";
4
-
5
- // src/core/migrations/planner.ts
6
- import {
7
- createMigrationPlan,
8
- plannerFailure,
9
- plannerSuccess
10
- } from "@prisma-next/family-sql/control";
11
- import {
12
- arraysEqual,
13
- isIndexSatisfied,
14
- isUniqueConstraintSatisfied,
15
- verifySqlSchema
16
- } from "@prisma-next/family-sql/schema-verify";
17
- var DEFAULT_PLANNER_CONFIG = {
18
- defaultSchema: "public"
19
- };
20
- function createPostgresMigrationPlanner(config = {}) {
21
- return new PostgresMigrationPlanner({
22
- ...DEFAULT_PLANNER_CONFIG,
23
- ...config
24
- });
25
- }
26
- var PostgresMigrationPlanner = class {
27
- constructor(config) {
28
- this.config = config;
29
- }
30
- plan(options) {
31
- const schemaName = options.schemaName ?? this.config.defaultSchema;
32
- const policyResult = this.ensureAdditivePolicy(options.policy);
33
- if (policyResult) {
34
- return policyResult;
35
- }
36
- const classification = this.classifySchema(options);
37
- if (classification.kind === "conflict") {
38
- return plannerFailure(classification.conflicts);
39
- }
40
- const operations = [];
41
- operations.push(
42
- ...this.buildDatabaseDependencyOperations(options),
43
- ...this.buildTableOperations(options.contract.storage.tables, options.schema, schemaName),
44
- ...this.buildColumnOperations(options.contract.storage.tables, options.schema, schemaName),
45
- ...this.buildPrimaryKeyOperations(
46
- options.contract.storage.tables,
47
- options.schema,
48
- schemaName
49
- ),
50
- ...this.buildUniqueOperations(options.contract.storage.tables, options.schema, schemaName),
51
- ...this.buildIndexOperations(options.contract.storage.tables, options.schema, schemaName),
52
- ...this.buildForeignKeyOperations(
53
- options.contract.storage.tables,
54
- options.schema,
55
- schemaName
56
- )
57
- );
58
- const plan = createMigrationPlan({
59
- targetId: "postgres",
60
- origin: null,
61
- destination: {
62
- coreHash: options.contract.coreHash,
63
- ...options.contract.profileHash ? { profileHash: options.contract.profileHash } : {}
64
- },
65
- operations
66
- });
67
- return plannerSuccess(plan);
68
- }
69
- ensureAdditivePolicy(policy) {
70
- if (!policy.allowedOperationClasses.includes("additive")) {
71
- return plannerFailure([
72
- {
73
- kind: "unsupportedOperation",
74
- summary: "Init planner requires additive operations be allowed",
75
- why: 'The init planner only emits additive operations. Update the policy to include "additive".'
76
- }
77
- ]);
78
- }
79
- return null;
80
- }
81
- /**
82
- * Builds migration operations from component-owned database dependencies.
83
- * These operations install database-side persistence structures declared by components.
84
- */
85
- buildDatabaseDependencyOperations(options) {
86
- const dependencies = this.collectDependencies(options);
87
- const operations = [];
88
- const seenDependencyIds = /* @__PURE__ */ new Set();
89
- const seenOperationIds = /* @__PURE__ */ new Set();
90
- for (const dependency of dependencies) {
91
- if (seenDependencyIds.has(dependency.id)) {
92
- continue;
93
- }
94
- seenDependencyIds.add(dependency.id);
95
- const issues = dependency.verifyDatabaseDependencyInstalled(options.schema);
96
- if (issues.length === 0) {
97
- continue;
98
- }
99
- for (const installOp of dependency.install) {
100
- if (seenOperationIds.has(installOp.id)) {
101
- continue;
102
- }
103
- seenOperationIds.add(installOp.id);
104
- operations.push(installOp);
105
- }
106
- }
107
- return operations;
108
- }
109
- collectDependencies(options) {
110
- const components = options.frameworkComponents;
111
- if (components.length === 0) {
112
- return [];
113
- }
114
- const deps = [];
115
- for (const component of components) {
116
- if (!isSqlDependencyProvider(component)) {
117
- continue;
118
- }
119
- const initDeps = component.databaseDependencies?.init;
120
- if (initDeps && initDeps.length > 0) {
121
- deps.push(...initDeps);
122
- }
123
- }
124
- return sortDependencies(deps);
125
- }
126
- buildTableOperations(tables, schema, schemaName) {
127
- const operations = [];
128
- for (const [tableName, table] of sortedEntries(tables)) {
129
- if (schema.tables[tableName]) {
130
- continue;
131
- }
132
- const qualified = qualifyTableName(schemaName, tableName);
133
- operations.push({
134
- id: `table.${tableName}`,
135
- label: `Create table ${tableName}`,
136
- summary: `Creates table ${tableName} with required columns`,
137
- operationClass: "additive",
138
- target: {
139
- id: "postgres",
140
- details: this.buildTargetDetails("table", tableName, schemaName)
141
- },
142
- precheck: [
143
- {
144
- description: `ensure table "${tableName}" does not exist`,
145
- sql: `SELECT to_regclass(${toRegclassLiteral(schemaName, tableName)}) IS NULL`
146
- }
147
- ],
148
- execute: [
149
- {
150
- description: `create table "${tableName}"`,
151
- sql: buildCreateTableSql(qualified, table)
152
- }
153
- ],
154
- postcheck: [
155
- {
156
- description: `verify table "${tableName}" exists`,
157
- sql: `SELECT to_regclass(${toRegclassLiteral(schemaName, tableName)}) IS NOT NULL`
158
- }
159
- ]
160
- });
161
- }
162
- return operations;
163
- }
164
- buildColumnOperations(tables, schema, schemaName) {
165
- const operations = [];
166
- for (const [tableName, table] of sortedEntries(tables)) {
167
- const schemaTable = schema.tables[tableName];
168
- if (!schemaTable) {
169
- continue;
170
- }
171
- for (const [columnName, column] of sortedEntries(table.columns)) {
172
- if (schemaTable.columns[columnName]) {
173
- continue;
174
- }
175
- operations.push(this.buildAddColumnOperation(schemaName, tableName, columnName, column));
176
- }
177
- }
178
- return operations;
179
- }
180
- buildAddColumnOperation(schema, tableName, columnName, column) {
181
- const qualified = qualifyTableName(schema, tableName);
182
- const notNull = column.nullable === false;
183
- const precheck = [
184
- {
185
- description: `ensure column "${columnName}" is missing`,
186
- sql: columnExistsCheck({ schema, table: tableName, column: columnName, exists: false })
187
- },
188
- ...notNull ? [
189
- {
190
- description: `ensure table "${tableName}" is empty before adding NOT NULL column`,
191
- sql: tableIsEmptyCheck(qualified)
192
- }
193
- ] : []
194
- ];
195
- const execute = [
196
- {
197
- description: `add column "${columnName}"`,
198
- sql: buildAddColumnSql(qualified, columnName, column)
199
- }
200
- ];
201
- const postcheck = [
202
- {
203
- description: `verify column "${columnName}" exists`,
204
- sql: columnExistsCheck({ schema, table: tableName, column: columnName })
205
- },
206
- ...notNull ? [
207
- {
208
- description: `verify column "${columnName}" is NOT NULL`,
209
- sql: columnIsNotNullCheck({ schema, table: tableName, column: columnName })
210
- }
211
- ] : []
212
- ];
213
- return {
214
- id: `column.${tableName}.${columnName}`,
215
- label: `Add column ${columnName} to ${tableName}`,
216
- summary: `Adds column ${columnName} to table ${tableName}`,
217
- operationClass: "additive",
218
- target: {
219
- id: "postgres",
220
- details: this.buildTargetDetails("table", tableName, schema)
221
- },
222
- precheck,
223
- execute,
224
- postcheck
225
- };
226
- }
227
- buildPrimaryKeyOperations(tables, schema, schemaName) {
228
- const operations = [];
229
- for (const [tableName, table] of sortedEntries(tables)) {
230
- if (!table.primaryKey) {
231
- continue;
232
- }
233
- const schemaTable = schema.tables[tableName];
234
- if (!schemaTable || schemaTable.primaryKey) {
235
- continue;
236
- }
237
- const constraintName = table.primaryKey.name ?? `${tableName}_pkey`;
238
- operations.push({
239
- id: `primaryKey.${tableName}.${constraintName}`,
240
- label: `Add primary key ${constraintName} on ${tableName}`,
241
- summary: `Adds primary key ${constraintName} on ${tableName}`,
242
- operationClass: "additive",
243
- target: {
244
- id: "postgres",
245
- details: this.buildTargetDetails("table", tableName, schemaName)
246
- },
247
- precheck: [
248
- {
249
- description: `ensure primary key does not exist on "${tableName}"`,
250
- sql: tableHasPrimaryKeyCheck(schemaName, tableName, false)
251
- }
252
- ],
253
- execute: [
254
- {
255
- description: `add primary key "${constraintName}"`,
256
- sql: `ALTER TABLE ${qualifyTableName(schemaName, tableName)}
257
- ADD CONSTRAINT ${quoteIdentifier(constraintName)}
258
- PRIMARY KEY (${table.primaryKey.columns.map(quoteIdentifier).join(", ")})`
259
- }
260
- ],
261
- postcheck: [
262
- {
263
- description: `verify primary key "${constraintName}" exists`,
264
- sql: tableHasPrimaryKeyCheck(schemaName, tableName, true, constraintName)
265
- }
266
- ]
267
- });
268
- }
269
- return operations;
270
- }
271
- buildUniqueOperations(tables, schema, schemaName) {
272
- const operations = [];
273
- for (const [tableName, table] of sortedEntries(tables)) {
274
- const schemaTable = schema.tables[tableName];
275
- for (const unique of table.uniques) {
276
- if (schemaTable && hasUniqueConstraint(schemaTable, unique.columns)) {
277
- continue;
278
- }
279
- const constraintName = unique.name ?? `${tableName}_${unique.columns.join("_")}_key`;
280
- operations.push({
281
- id: `unique.${tableName}.${constraintName}`,
282
- label: `Add unique constraint ${constraintName} on ${tableName}`,
283
- summary: `Adds unique constraint ${constraintName} on ${tableName}`,
284
- operationClass: "additive",
285
- target: {
286
- id: "postgres",
287
- details: this.buildTargetDetails("unique", constraintName, schemaName, tableName)
288
- },
289
- precheck: [
290
- {
291
- description: `ensure unique constraint "${constraintName}" is missing`,
292
- sql: constraintExistsCheck({ constraintName, schema: schemaName, exists: false })
293
- }
294
- ],
295
- execute: [
296
- {
297
- description: `add unique constraint "${constraintName}"`,
298
- sql: `ALTER TABLE ${qualifyTableName(schemaName, tableName)}
299
- ADD CONSTRAINT ${quoteIdentifier(constraintName)}
300
- UNIQUE (${unique.columns.map(quoteIdentifier).join(", ")})`
301
- }
302
- ],
303
- postcheck: [
304
- {
305
- description: `verify unique constraint "${constraintName}" exists`,
306
- sql: constraintExistsCheck({ constraintName, schema: schemaName })
307
- }
308
- ]
309
- });
310
- }
311
- }
312
- return operations;
313
- }
314
- buildIndexOperations(tables, schema, schemaName) {
315
- const operations = [];
316
- for (const [tableName, table] of sortedEntries(tables)) {
317
- const schemaTable = schema.tables[tableName];
318
- for (const index of table.indexes) {
319
- if (schemaTable && hasIndex(schemaTable, index.columns)) {
320
- continue;
321
- }
322
- const indexName = index.name ?? `${tableName}_${index.columns.join("_")}_idx`;
323
- operations.push({
324
- id: `index.${tableName}.${indexName}`,
325
- label: `Create index ${indexName} on ${tableName}`,
326
- summary: `Creates index ${indexName} on ${tableName}`,
327
- operationClass: "additive",
328
- target: {
329
- id: "postgres",
330
- details: this.buildTargetDetails("index", indexName, schemaName, tableName)
331
- },
332
- precheck: [
333
- {
334
- description: `ensure index "${indexName}" is missing`,
335
- sql: `SELECT to_regclass(${toRegclassLiteral(schemaName, indexName)}) IS NULL`
336
- }
337
- ],
338
- execute: [
339
- {
340
- description: `create index "${indexName}"`,
341
- sql: `CREATE INDEX ${quoteIdentifier(indexName)} ON ${qualifyTableName(
342
- schemaName,
343
- tableName
344
- )} (${index.columns.map(quoteIdentifier).join(", ")})`
345
- }
346
- ],
347
- postcheck: [
348
- {
349
- description: `verify index "${indexName}" exists`,
350
- sql: `SELECT to_regclass(${toRegclassLiteral(schemaName, indexName)}) IS NOT NULL`
351
- }
352
- ]
353
- });
354
- }
355
- }
356
- return operations;
357
- }
358
- buildForeignKeyOperations(tables, schema, schemaName) {
359
- const operations = [];
360
- for (const [tableName, table] of sortedEntries(tables)) {
361
- const schemaTable = schema.tables[tableName];
362
- for (const foreignKey of table.foreignKeys) {
363
- if (schemaTable && hasForeignKey(schemaTable, foreignKey)) {
364
- continue;
365
- }
366
- const fkName = foreignKey.name ?? `${tableName}_${foreignKey.columns.join("_")}_fkey`;
367
- operations.push({
368
- id: `foreignKey.${tableName}.${fkName}`,
369
- label: `Add foreign key ${fkName} on ${tableName}`,
370
- summary: `Adds foreign key ${fkName} referencing ${foreignKey.references.table}`,
371
- operationClass: "additive",
372
- target: {
373
- id: "postgres",
374
- details: this.buildTargetDetails("foreignKey", fkName, schemaName, tableName)
375
- },
376
- precheck: [
377
- {
378
- description: `ensure foreign key "${fkName}" is missing`,
379
- sql: constraintExistsCheck({
380
- constraintName: fkName,
381
- schema: schemaName,
382
- exists: false
383
- })
384
- }
385
- ],
386
- execute: [
387
- {
388
- description: `add foreign key "${fkName}"`,
389
- sql: `ALTER TABLE ${qualifyTableName(schemaName, tableName)}
390
- ADD CONSTRAINT ${quoteIdentifier(fkName)}
391
- FOREIGN KEY (${foreignKey.columns.map(quoteIdentifier).join(", ")})
392
- REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${foreignKey.references.columns.map(quoteIdentifier).join(", ")})`
393
- }
394
- ],
395
- postcheck: [
396
- {
397
- description: `verify foreign key "${fkName}" exists`,
398
- sql: constraintExistsCheck({ constraintName: fkName, schema: schemaName })
399
- }
400
- ]
401
- });
402
- }
403
- }
404
- return operations;
405
- }
406
- buildTargetDetails(objectType, name, schema, table) {
407
- return {
408
- schema,
409
- objectType,
410
- name,
411
- ...table ? { table } : {}
412
- };
413
- }
414
- classifySchema(options) {
415
- const verifyOptions = {
416
- contract: options.contract,
417
- schema: options.schema,
418
- strict: false,
419
- typeMetadataRegistry: /* @__PURE__ */ new Map(),
420
- frameworkComponents: options.frameworkComponents
421
- };
422
- const verifyResult = verifySqlSchema(verifyOptions);
423
- const conflicts = this.extractConflicts(verifyResult.schema.issues);
424
- if (conflicts.length > 0) {
425
- return { kind: "conflict", conflicts };
426
- }
427
- return { kind: "ok" };
428
- }
429
- extractConflicts(issues) {
430
- const conflicts = [];
431
- for (const issue of issues) {
432
- if (isAdditiveIssue(issue)) {
433
- continue;
434
- }
435
- const conflict = this.convertIssueToConflict(issue);
436
- if (conflict) {
437
- conflicts.push(conflict);
438
- }
439
- }
440
- return conflicts.sort(conflictComparator);
441
- }
442
- convertIssueToConflict(issue) {
443
- switch (issue.kind) {
444
- case "type_mismatch":
445
- return this.buildConflict("typeMismatch", issue);
446
- case "nullability_mismatch":
447
- return this.buildConflict("nullabilityConflict", issue);
448
- case "primary_key_mismatch":
449
- return this.buildConflict("indexIncompatible", issue);
450
- case "unique_constraint_mismatch":
451
- return this.buildConflict("indexIncompatible", issue);
452
- case "index_mismatch":
453
- return this.buildConflict("indexIncompatible", issue);
454
- case "foreign_key_mismatch":
455
- return this.buildConflict("foreignKeyConflict", issue);
456
- default:
457
- return null;
458
- }
459
- }
460
- buildConflict(kind, issue) {
461
- const location = buildConflictLocation(issue);
462
- const meta = issue.expected || issue.actual ? Object.freeze({
463
- ...issue.expected ? { expected: issue.expected } : {},
464
- ...issue.actual ? { actual: issue.actual } : {}
465
- }) : void 0;
466
- return {
467
- kind,
468
- summary: issue.message,
469
- ...location ? { location } : {},
470
- ...meta ? { meta } : {}
471
- };
472
- }
473
- };
474
- function isSqlDependencyProvider(component) {
475
- if (typeof component !== "object" || component === null) {
476
- return false;
477
- }
478
- const record = component;
479
- if (Object.hasOwn(record, "familyId") && record["familyId"] !== "sql") {
480
- return false;
481
- }
482
- if (!Object.hasOwn(record, "databaseDependencies")) {
483
- return false;
484
- }
485
- const deps = record["databaseDependencies"];
486
- return deps === void 0 || typeof deps === "object" && deps !== null;
487
- }
488
- function sortDependencies(dependencies) {
489
- if (dependencies.length <= 1) {
490
- return dependencies;
491
- }
492
- return [...dependencies].sort((a, b) => a.id.localeCompare(b.id));
493
- }
494
- function buildCreateTableSql(qualifiedTableName, table) {
495
- const columnDefinitions = Object.entries(table.columns).map(
496
- ([columnName, column]) => {
497
- const parts = [
498
- quoteIdentifier(columnName),
499
- column.nativeType,
500
- column.nullable ? "" : "NOT NULL"
501
- ].filter(Boolean);
502
- return parts.join(" ");
503
- }
504
- );
505
- const constraintDefinitions = [];
506
- if (table.primaryKey) {
507
- constraintDefinitions.push(
508
- `PRIMARY KEY (${table.primaryKey.columns.map(quoteIdentifier).join(", ")})`
509
- );
510
- }
511
- const allDefinitions = [...columnDefinitions, ...constraintDefinitions];
512
- return `CREATE TABLE ${qualifiedTableName} (
513
- ${allDefinitions.join(",\n ")}
514
- )`;
515
- }
516
- function qualifyTableName(schema, table) {
517
- return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
518
- }
519
- function toRegclassLiteral(schema, name) {
520
- const regclass = `${quoteIdentifier(schema)}.${quoteIdentifier(name)}`;
521
- return `'${escapeLiteral(regclass)}'`;
522
- }
523
- function quoteIdentifier(identifier) {
524
- return `"${identifier.replace(/"/g, '""')}"`;
525
- }
526
- function escapeLiteral(value) {
527
- return value.replace(/'/g, "''");
528
- }
529
- function sortedEntries(record) {
530
- return Object.entries(record).sort(([a], [b]) => a.localeCompare(b));
531
- }
532
- function constraintExistsCheck({
533
- constraintName,
534
- schema,
535
- exists = true
536
- }) {
537
- const existsClause = exists ? "EXISTS" : "NOT EXISTS";
538
- return `SELECT ${existsClause} (
539
- SELECT 1 FROM pg_constraint c
540
- JOIN pg_namespace n ON c.connamespace = n.oid
541
- WHERE c.conname = '${escapeLiteral(constraintName)}'
542
- AND n.nspname = '${escapeLiteral(schema)}'
543
- )`;
544
- }
545
- function columnExistsCheck({
546
- schema,
547
- table,
548
- column,
549
- exists = true
550
- }) {
551
- const existsClause = exists ? "" : "NOT ";
552
- return `SELECT ${existsClause}EXISTS (
553
- SELECT 1
554
- FROM information_schema.columns
555
- WHERE table_schema = '${escapeLiteral(schema)}'
556
- AND table_name = '${escapeLiteral(table)}'
557
- AND column_name = '${escapeLiteral(column)}'
558
- )`;
559
- }
560
- function columnIsNotNullCheck({
561
- schema,
562
- table,
563
- column
564
- }) {
565
- return `SELECT EXISTS (
566
- SELECT 1
567
- FROM information_schema.columns
568
- WHERE table_schema = '${escapeLiteral(schema)}'
569
- AND table_name = '${escapeLiteral(table)}'
570
- AND column_name = '${escapeLiteral(column)}'
571
- AND is_nullable = 'NO'
572
- )`;
573
- }
574
- function tableIsEmptyCheck(qualifiedTableName) {
575
- return `SELECT NOT EXISTS (SELECT 1 FROM ${qualifiedTableName} LIMIT 1)`;
576
- }
577
- function buildAddColumnSql(qualifiedTableName, columnName, column) {
578
- const parts = [
579
- `ALTER TABLE ${qualifiedTableName}`,
580
- `ADD COLUMN ${quoteIdentifier(columnName)} ${column.nativeType}`,
581
- column.nullable ? "" : "NOT NULL"
582
- ].filter(Boolean);
583
- return parts.join(" ");
584
- }
585
- function tableHasPrimaryKeyCheck(schema, table, exists, constraintName) {
586
- const comparison = exists ? "" : "NOT ";
587
- const constraintFilter = constraintName ? `AND c2.relname = '${escapeLiteral(constraintName)}'` : "";
588
- return `SELECT ${comparison}EXISTS (
589
- SELECT 1
590
- FROM pg_index i
591
- JOIN pg_class c ON c.oid = i.indrelid
592
- JOIN pg_namespace n ON n.oid = c.relnamespace
593
- LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
594
- WHERE n.nspname = '${escapeLiteral(schema)}'
595
- AND c.relname = '${escapeLiteral(table)}'
596
- AND i.indisprimary
597
- ${constraintFilter}
598
- )`;
599
- }
600
- function hasUniqueConstraint(table, columns) {
601
- return isUniqueConstraintSatisfied(table.uniques, table.indexes, columns);
602
- }
603
- function hasIndex(table, columns) {
604
- return isIndexSatisfied(table.indexes, table.uniques, columns);
605
- }
606
- function hasForeignKey(table, fk) {
607
- return table.foreignKeys.some(
608
- (candidate) => arraysEqual(candidate.columns, fk.columns) && candidate.referencedTable === fk.references.table && arraysEqual(candidate.referencedColumns, fk.references.columns)
609
- );
610
- }
611
- function isAdditiveIssue(issue) {
612
- switch (issue.kind) {
613
- case "missing_table":
614
- case "missing_column":
615
- case "extension_missing":
616
- return true;
617
- case "primary_key_mismatch":
618
- return issue.actual === void 0;
619
- case "unique_constraint_mismatch":
620
- case "index_mismatch":
621
- case "foreign_key_mismatch":
622
- return issue.indexOrConstraint === void 0;
623
- default:
624
- return false;
625
- }
626
- }
627
- function buildConflictLocation(issue) {
628
- const location = {};
629
- if (issue.table) {
630
- location.table = issue.table;
631
- }
632
- if (issue.column) {
633
- location.column = issue.column;
634
- }
635
- if (issue.indexOrConstraint) {
636
- location.constraint = issue.indexOrConstraint;
637
- }
638
- return Object.keys(location).length > 0 ? location : void 0;
639
- }
640
- function conflictComparator(a, b) {
641
- if (a.kind !== b.kind) {
642
- return a.kind < b.kind ? -1 : 1;
643
- }
644
- const aLocation = a.location ?? {};
645
- const bLocation = b.location ?? {};
646
- const tableCompare = compareStrings(aLocation.table, bLocation.table);
647
- if (tableCompare !== 0) {
648
- return tableCompare;
649
- }
650
- const columnCompare = compareStrings(aLocation.column, bLocation.column);
651
- if (columnCompare !== 0) {
652
- return columnCompare;
653
- }
654
- const constraintCompare = compareStrings(aLocation.constraint, bLocation.constraint);
655
- if (constraintCompare !== 0) {
656
- return constraintCompare;
657
- }
658
- return compareStrings(a.summary, b.summary);
659
- }
660
- function compareStrings(a, b) {
661
- if (a === b) {
662
- return 0;
663
- }
664
- if (a === void 0) {
665
- return -1;
666
- }
667
- if (b === void 0) {
668
- return 1;
669
- }
670
- return a < b ? -1 : 1;
671
- }
672
-
673
- // src/core/migrations/runner.ts
674
- import { runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
675
- import { verifySqlSchema as verifySqlSchema2 } from "@prisma-next/family-sql/schema-verify";
676
- import { readMarker } from "@prisma-next/family-sql/verify";
677
- import { SqlQueryError } from "@prisma-next/sql-errors";
678
- import { ok, okVoid } from "@prisma-next/utils/result";
679
-
680
- // src/core/migrations/statement-builders.ts
681
- var ensurePrismaContractSchemaStatement = {
682
- sql: "create schema if not exists prisma_contract",
683
- params: []
684
- };
685
- var ensureMarkerTableStatement = {
686
- sql: `create table if not exists prisma_contract.marker (
687
- id smallint primary key default 1,
688
- core_hash text not null,
689
- profile_hash text not null,
690
- contract_json jsonb,
691
- canonical_version int,
692
- updated_at timestamptz not null default now(),
693
- app_tag text,
694
- meta jsonb not null default '{}'
695
- )`,
696
- params: []
697
- };
698
- var ensureLedgerTableStatement = {
699
- sql: `create table if not exists prisma_contract.ledger (
700
- id bigserial primary key,
701
- created_at timestamptz not null default now(),
702
- origin_core_hash text,
703
- origin_profile_hash text,
704
- destination_core_hash text not null,
705
- destination_profile_hash text,
706
- contract_json_before jsonb,
707
- contract_json_after jsonb,
708
- operations jsonb not null
709
- )`,
710
- params: []
711
- };
712
- function buildWriteMarkerStatements(input) {
713
- const params = [
714
- 1,
715
- input.coreHash,
716
- input.profileHash,
717
- jsonParam(input.contractJson),
718
- input.canonicalVersion ?? null,
719
- input.appTag ?? null,
720
- jsonParam(input.meta ?? {})
721
- ];
722
- return {
723
- insert: {
724
- sql: `insert into prisma_contract.marker (
725
- id,
726
- core_hash,
727
- profile_hash,
728
- contract_json,
729
- canonical_version,
730
- updated_at,
731
- app_tag,
732
- meta
733
- ) values (
734
- $1,
735
- $2,
736
- $3,
737
- $4::jsonb,
738
- $5,
739
- now(),
740
- $6,
741
- $7::jsonb
742
- )`,
743
- params
744
- },
745
- update: {
746
- sql: `update prisma_contract.marker set
747
- core_hash = $2,
748
- profile_hash = $3,
749
- contract_json = $4::jsonb,
750
- canonical_version = $5,
751
- updated_at = now(),
752
- app_tag = $6,
753
- meta = $7::jsonb
754
- where id = $1`,
755
- params
756
- }
757
- };
758
- }
759
- function buildLedgerInsertStatement(input) {
760
- return {
761
- sql: `insert into prisma_contract.ledger (
762
- origin_core_hash,
763
- origin_profile_hash,
764
- destination_core_hash,
765
- destination_profile_hash,
766
- contract_json_before,
767
- contract_json_after,
768
- operations
769
- ) values (
770
- $1,
771
- $2,
772
- $3,
773
- $4,
774
- $5::jsonb,
775
- $6::jsonb,
776
- $7::jsonb
777
- )`,
778
- params: [
779
- input.originCoreHash ?? null,
780
- input.originProfileHash ?? null,
781
- input.destinationCoreHash,
782
- input.destinationProfileHash ?? null,
783
- jsonParam(input.contractJsonBefore),
784
- jsonParam(input.contractJsonAfter),
785
- jsonParam(input.operations)
786
- ]
787
- };
788
- }
789
- function jsonParam(value) {
790
- return JSON.stringify(value ?? null);
791
- }
792
-
793
- // src/core/migrations/runner.ts
794
- var DEFAULT_CONFIG = {
795
- defaultSchema: "public"
796
- };
797
- var LOCK_DOMAIN = "prisma_next.contract.marker";
798
- function cloneAndFreezeRecord(value) {
799
- const cloned = {};
800
- for (const [key, val] of Object.entries(value)) {
801
- if (val === null || val === void 0) {
802
- cloned[key] = val;
803
- } else if (Array.isArray(val)) {
804
- cloned[key] = Object.freeze([...val]);
805
- } else if (typeof val === "object") {
806
- cloned[key] = cloneAndFreezeRecord(val);
807
- } else {
808
- cloned[key] = val;
809
- }
810
- }
811
- return Object.freeze(cloned);
812
- }
813
- function createPostgresMigrationRunner(family, config = {}) {
814
- return new PostgresMigrationRunner(family, { ...DEFAULT_CONFIG, ...config });
815
- }
816
- var PostgresMigrationRunner = class {
817
- constructor(family, config) {
818
- this.family = family;
819
- this.config = config;
820
- }
821
- async execute(options) {
822
- const schema = options.schemaName ?? this.config.defaultSchema;
823
- const driver = options.driver;
824
- const lockKey = `${LOCK_DOMAIN}:${schema}`;
825
- const destinationCheck = this.ensurePlanMatchesDestinationContract(
826
- options.plan.destination,
827
- options.destinationContract
828
- );
829
- if (!destinationCheck.ok) {
830
- return destinationCheck;
831
- }
832
- const policyCheck = this.enforcePolicyCompatibility(options.policy, options.plan.operations);
833
- if (!policyCheck.ok) {
834
- return policyCheck;
835
- }
836
- await this.beginTransaction(driver);
837
- let committed = false;
838
- try {
839
- await this.acquireLock(driver, lockKey);
840
- await this.ensureControlTables(driver);
841
- const existingMarker = await readMarker(driver);
842
- const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);
843
- if (!markerCheck.ok) {
844
- return markerCheck;
845
- }
846
- const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);
847
- let applyValue;
848
- if (markerAtDestination) {
849
- applyValue = { operationsExecuted: 0, executedOperations: [] };
850
- } else {
851
- const applyResult = await this.applyPlan(driver, options);
852
- if (!applyResult.ok) {
853
- return applyResult;
854
- }
855
- applyValue = applyResult.value;
856
- }
857
- const schemaIR = await this.family.introspect({
858
- driver,
859
- contractIR: options.destinationContract
860
- });
861
- const schemaVerifyResult = verifySqlSchema2({
862
- contract: options.destinationContract,
863
- schema: schemaIR,
864
- strict: options.strictVerification ?? true,
865
- context: options.context ?? {},
866
- typeMetadataRegistry: this.family.typeMetadataRegistry,
867
- frameworkComponents: options.frameworkComponents
868
- });
869
- if (!schemaVerifyResult.ok) {
870
- return runnerFailure("SCHEMA_VERIFY_FAILED", schemaVerifyResult.summary, {
871
- why: "The resulting database schema does not satisfy the destination contract.",
872
- meta: {
873
- issues: schemaVerifyResult.schema.issues
874
- }
875
- });
876
- }
877
- await this.upsertMarker(driver, options, existingMarker);
878
- await this.recordLedgerEntry(driver, options, existingMarker, applyValue.executedOperations);
879
- await this.commitTransaction(driver);
880
- committed = true;
881
- return runnerSuccess({
882
- operationsPlanned: options.plan.operations.length,
883
- operationsExecuted: applyValue.operationsExecuted
884
- });
885
- } finally {
886
- if (!committed) {
887
- await this.rollbackTransaction(driver);
888
- }
889
- }
890
- }
891
- async applyPlan(driver, options) {
892
- const checks = options.executionChecks;
893
- const runPrechecks = checks?.prechecks !== false;
894
- const runPostchecks = checks?.postchecks !== false;
895
- const runIdempotency = checks?.idempotencyChecks !== false;
896
- let operationsExecuted = 0;
897
- const executedOperations = [];
898
- for (const operation of options.plan.operations) {
899
- options.callbacks?.onOperationStart?.(operation);
900
- try {
901
- if (runPostchecks && runIdempotency) {
902
- const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(
903
- driver,
904
- operation.postcheck
905
- );
906
- if (postcheckAlreadySatisfied) {
907
- executedOperations.push(this.createPostcheckPreSatisfiedSkipRecord(operation));
908
- continue;
909
- }
910
- }
911
- if (runPrechecks) {
912
- const precheckResult = await this.runExpectationSteps(
913
- driver,
914
- operation.precheck,
915
- operation,
916
- "precheck"
917
- );
918
- if (!precheckResult.ok) {
919
- return precheckResult;
920
- }
921
- }
922
- const executeResult = await this.runExecuteSteps(driver, operation.execute, operation);
923
- if (!executeResult.ok) {
924
- return executeResult;
925
- }
926
- if (runPostchecks) {
927
- const postcheckResult = await this.runExpectationSteps(
928
- driver,
929
- operation.postcheck,
930
- operation,
931
- "postcheck"
932
- );
933
- if (!postcheckResult.ok) {
934
- return postcheckResult;
935
- }
936
- }
937
- executedOperations.push(operation);
938
- operationsExecuted += 1;
939
- } finally {
940
- options.callbacks?.onOperationComplete?.(operation);
941
- }
942
- }
943
- return ok({ operationsExecuted, executedOperations });
944
- }
945
- async ensureControlTables(driver) {
946
- await this.executeStatement(driver, ensurePrismaContractSchemaStatement);
947
- await this.executeStatement(driver, ensureMarkerTableStatement);
948
- await this.executeStatement(driver, ensureLedgerTableStatement);
949
- }
950
- async runExpectationSteps(driver, steps, operation, phase) {
951
- for (const step of steps) {
952
- const result = await driver.query(step.sql);
953
- if (!this.stepResultIsTrue(result.rows)) {
954
- const code = phase === "precheck" ? "PRECHECK_FAILED" : "POSTCHECK_FAILED";
955
- return runnerFailure(
956
- code,
957
- `Operation ${operation.id} failed during ${phase}: ${step.description}`,
958
- {
959
- meta: {
960
- operationId: operation.id,
961
- phase,
962
- stepDescription: step.description
963
- }
964
- }
965
- );
966
- }
967
- }
968
- return okVoid();
969
- }
970
- async runExecuteSteps(driver, steps, operation) {
971
- for (const step of steps) {
972
- try {
973
- await driver.query(step.sql);
974
- } catch (error) {
975
- if (SqlQueryError.is(error)) {
976
- return runnerFailure(
977
- "EXECUTION_FAILED",
978
- `Operation ${operation.id} failed during execution: ${step.description}`,
979
- {
980
- why: error.message,
981
- meta: {
982
- operationId: operation.id,
983
- stepDescription: step.description,
984
- sql: step.sql,
985
- sqlState: error.sqlState,
986
- constraint: error.constraint,
987
- table: error.table,
988
- column: error.column,
989
- detail: error.detail
990
- }
991
- }
992
- );
993
- }
994
- throw error;
995
- }
996
- }
997
- return okVoid();
998
- }
999
- stepResultIsTrue(rows) {
1000
- if (!rows || rows.length === 0) {
1001
- return false;
1002
- }
1003
- const firstRow = rows[0];
1004
- const firstValue = firstRow ? Object.values(firstRow)[0] : void 0;
1005
- if (typeof firstValue === "boolean") {
1006
- return firstValue;
1007
- }
1008
- if (typeof firstValue === "number") {
1009
- return firstValue !== 0;
1010
- }
1011
- if (typeof firstValue === "string") {
1012
- const lower = firstValue.toLowerCase();
1013
- if (lower === "t" || lower === "true" || lower === "1") {
1014
- return true;
1015
- }
1016
- if (lower === "f" || lower === "false" || lower === "0") {
1017
- return false;
1018
- }
1019
- return firstValue.length > 0;
1020
- }
1021
- return Boolean(firstValue);
1022
- }
1023
- async expectationsAreSatisfied(driver, steps) {
1024
- if (steps.length === 0) {
1025
- return false;
1026
- }
1027
- for (const step of steps) {
1028
- const result = await driver.query(step.sql);
1029
- if (!this.stepResultIsTrue(result.rows)) {
1030
- return false;
1031
- }
1032
- }
1033
- return true;
1034
- }
1035
- createPostcheckPreSatisfiedSkipRecord(operation) {
1036
- const clonedMeta = operation.meta ? cloneAndFreezeRecord(operation.meta) : void 0;
1037
- const runnerMeta = Object.freeze({
1038
- skipped: true,
1039
- reason: "postcheck_pre_satisfied"
1040
- });
1041
- const mergedMeta = Object.freeze({
1042
- ...clonedMeta ?? {},
1043
- runner: runnerMeta
1044
- });
1045
- const frozenPostcheck = Object.freeze([...operation.postcheck]);
1046
- return Object.freeze({
1047
- id: operation.id,
1048
- label: operation.label,
1049
- ...operation.summary ? { summary: operation.summary } : {},
1050
- operationClass: operation.operationClass,
1051
- target: operation.target,
1052
- // Already frozen from plan creation
1053
- precheck: Object.freeze([]),
1054
- execute: Object.freeze([]),
1055
- postcheck: frozenPostcheck,
1056
- ...operation.meta || mergedMeta ? { meta: mergedMeta } : {}
1057
- });
1058
- }
1059
- markerMatchesDestination(marker, plan) {
1060
- if (!marker) {
1061
- return false;
1062
- }
1063
- if (marker.coreHash !== plan.destination.coreHash) {
1064
- return false;
1065
- }
1066
- if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {
1067
- return false;
1068
- }
1069
- return true;
1070
- }
1071
- enforcePolicyCompatibility(policy, operations) {
1072
- const allowedClasses = new Set(policy.allowedOperationClasses);
1073
- for (const operation of operations) {
1074
- if (!allowedClasses.has(operation.operationClass)) {
1075
- return runnerFailure(
1076
- "POLICY_VIOLATION",
1077
- `Operation ${operation.id} has class "${operation.operationClass}" which is not allowed by policy.`,
1078
- {
1079
- why: `Policy only allows: ${policy.allowedOperationClasses.join(", ")}.`,
1080
- meta: {
1081
- operationId: operation.id,
1082
- operationClass: operation.operationClass,
1083
- allowedClasses: policy.allowedOperationClasses
1084
- }
1085
- }
1086
- );
1087
- }
1088
- }
1089
- return okVoid();
1090
- }
1091
- ensureMarkerCompatibility(marker, plan) {
1092
- const origin = plan.origin ?? null;
1093
- if (!origin) {
1094
- if (!marker) {
1095
- return okVoid();
1096
- }
1097
- if (this.markerMatchesDestination(marker, plan)) {
1098
- return okVoid();
1099
- }
1100
- return runnerFailure(
1101
- "MARKER_ORIGIN_MISMATCH",
1102
- `Existing contract marker (${marker.coreHash}) does not match plan origin (no marker expected).`,
1103
- {
1104
- meta: {
1105
- markerCoreHash: marker.coreHash,
1106
- expectedOrigin: null
1107
- }
1108
- }
1109
- );
1110
- }
1111
- if (!marker) {
1112
- return runnerFailure(
1113
- "MARKER_ORIGIN_MISMATCH",
1114
- `Missing contract marker: expected origin core hash ${origin.coreHash}.`,
1115
- {
1116
- meta: {
1117
- expectedOriginCoreHash: origin.coreHash
1118
- }
1119
- }
1120
- );
1121
- }
1122
- if (marker.coreHash !== origin.coreHash) {
1123
- return runnerFailure(
1124
- "MARKER_ORIGIN_MISMATCH",
1125
- `Existing contract marker (${marker.coreHash}) does not match plan origin (${origin.coreHash}).`,
1126
- {
1127
- meta: {
1128
- markerCoreHash: marker.coreHash,
1129
- expectedOriginCoreHash: origin.coreHash
1130
- }
1131
- }
1132
- );
1133
- }
1134
- if (origin.profileHash && marker.profileHash !== origin.profileHash) {
1135
- return runnerFailure(
1136
- "MARKER_ORIGIN_MISMATCH",
1137
- `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,
1138
- {
1139
- meta: {
1140
- markerProfileHash: marker.profileHash,
1141
- expectedOriginProfileHash: origin.profileHash
1142
- }
1143
- }
1144
- );
1145
- }
1146
- return okVoid();
1147
- }
1148
- ensurePlanMatchesDestinationContract(destination, contract) {
1149
- if (destination.coreHash !== contract.coreHash) {
1150
- return runnerFailure(
1151
- "DESTINATION_CONTRACT_MISMATCH",
1152
- `Plan destination core hash (${destination.coreHash}) does not match provided contract core hash (${contract.coreHash}).`,
1153
- {
1154
- meta: {
1155
- planCoreHash: destination.coreHash,
1156
- contractCoreHash: contract.coreHash
1157
- }
1158
- }
1159
- );
1160
- }
1161
- if (destination.profileHash && contract.profileHash && destination.profileHash !== contract.profileHash) {
1162
- return runnerFailure(
1163
- "DESTINATION_CONTRACT_MISMATCH",
1164
- `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,
1165
- {
1166
- meta: {
1167
- planProfileHash: destination.profileHash,
1168
- contractProfileHash: contract.profileHash
1169
- }
1170
- }
1171
- );
1172
- }
1173
- return okVoid();
1174
- }
1175
- async upsertMarker(driver, options, existingMarker) {
1176
- const writeStatements = buildWriteMarkerStatements({
1177
- coreHash: options.plan.destination.coreHash,
1178
- profileHash: options.plan.destination.profileHash ?? options.destinationContract.profileHash ?? options.plan.destination.coreHash,
1179
- contractJson: options.destinationContract,
1180
- canonicalVersion: null,
1181
- meta: {}
1182
- });
1183
- const statement = existingMarker ? writeStatements.update : writeStatements.insert;
1184
- await this.executeStatement(driver, statement);
1185
- }
1186
- async recordLedgerEntry(driver, options, existingMarker, executedOperations) {
1187
- const ledgerStatement = buildLedgerInsertStatement({
1188
- originCoreHash: existingMarker?.coreHash ?? null,
1189
- originProfileHash: existingMarker?.profileHash ?? null,
1190
- destinationCoreHash: options.plan.destination.coreHash,
1191
- destinationProfileHash: options.plan.destination.profileHash ?? options.destinationContract.profileHash ?? options.plan.destination.coreHash,
1192
- contractJsonBefore: existingMarker?.contractJson ?? null,
1193
- contractJsonAfter: options.destinationContract,
1194
- operations: executedOperations
1195
- });
1196
- await this.executeStatement(driver, ledgerStatement);
1197
- }
1198
- async acquireLock(driver, key) {
1199
- await driver.query("select pg_advisory_xact_lock(hashtext($1))", [key]);
1200
- }
1201
- async beginTransaction(driver) {
1202
- await driver.query("BEGIN");
1203
- }
1204
- async commitTransaction(driver) {
1205
- await driver.query("COMMIT");
1206
- }
1207
- async rollbackTransaction(driver) {
1208
- await driver.query("ROLLBACK");
1209
- }
1210
- async executeStatement(driver, statement) {
1211
- if (statement.params.length > 0) {
1212
- await driver.query(statement.sql, statement.params);
1213
- return;
1214
- }
1215
- await driver.query(statement.sql);
1216
- }
1217
- };
1218
-
1219
- // src/exports/control.ts
1220
- var postgresTargetDescriptor = {
1221
- ...postgresTargetDescriptorMeta,
1222
- /**
1223
- * Migrations capability for CLI to access planner/runner via core types.
1224
- * The SQL-specific planner/runner types are compatible with the generic
1225
- * MigrationPlanner/MigrationRunner interfaces at runtime.
1226
- */
1227
- migrations: {
1228
- createPlanner(_family) {
1229
- return createPostgresMigrationPlanner();
1230
- },
1231
- createRunner(family) {
1232
- return createPostgresMigrationRunner(family);
1233
- }
1234
- },
1235
- create() {
1236
- return {
1237
- familyId: "sql",
1238
- targetId: "postgres"
1239
- };
1240
- },
1241
- /**
1242
- * Direct method for SQL-specific usage.
1243
- * @deprecated Use migrations.createPlanner() for CLI compatibility.
1244
- */
1245
- createPlanner(_family) {
1246
- return createPostgresMigrationPlanner();
1247
- },
1248
- /**
1249
- * Direct method for SQL-specific usage.
1250
- * @deprecated Use migrations.createRunner() for CLI compatibility.
1251
- */
1252
- createRunner(family) {
1253
- return createPostgresMigrationRunner(family);
1254
- }
1255
- };
1256
- var control_default = postgresTargetDescriptor;
1257
- export {
1258
- control_default as default
1259
- };
1260
- //# sourceMappingURL=control.js.map