@prisma-next/target-postgres 0.3.0-dev.34 → 0.3.0-dev.36
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 +5 -1
- package/dist/control.d.mts +16 -0
- package/dist/control.d.mts.map +1 -0
- package/dist/control.mjs +2453 -0
- package/dist/control.mjs.map +1 -0
- package/dist/descriptor-meta-DxB8oZzB.mjs +13 -0
- package/dist/descriptor-meta-DxB8oZzB.mjs.map +1 -0
- package/dist/pack.d.mts +7 -0
- package/dist/pack.d.mts.map +1 -0
- package/dist/pack.mjs +9 -0
- package/dist/pack.mjs.map +1 -0
- package/dist/runtime.d.mts +9 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +21 -0
- package/dist/runtime.mjs.map +1 -0
- package/package.json +28 -28
- package/src/core/migrations/planner.ts +172 -22
- package/src/core/migrations/runner.ts +27 -20
- package/src/core/migrations/statement-builders.ts +6 -6
- package/src/core/types.ts +5 -0
- package/src/exports/control.ts +1 -3
- package/src/exports/runtime.ts +7 -12
- package/dist/chunk-RKEXRSSI.js +0 -14
- package/dist/chunk-RKEXRSSI.js.map +0 -1
- package/dist/core/descriptor-meta.d.ts +0 -9
- package/dist/core/descriptor-meta.d.ts.map +0 -1
- package/dist/core/migrations/planner.d.ts +0 -14
- package/dist/core/migrations/planner.d.ts.map +0 -1
- package/dist/core/migrations/runner.d.ts +0 -8
- package/dist/core/migrations/runner.d.ts.map +0 -1
- package/dist/core/migrations/statement-builders.d.ts +0 -30
- package/dist/core/migrations/statement-builders.d.ts.map +0 -1
- package/dist/exports/control.d.ts +0 -8
- package/dist/exports/control.d.ts.map +0 -1
- package/dist/exports/control.js +0 -1260
- package/dist/exports/control.js.map +0 -1
- package/dist/exports/pack.d.ts +0 -4
- package/dist/exports/pack.d.ts.map +0 -1
- package/dist/exports/pack.js +0 -11
- package/dist/exports/pack.js.map +0 -1
- package/dist/exports/runtime.d.ts +0 -12
- package/dist/exports/runtime.d.ts.map +0 -1
- package/dist/exports/runtime.js +0 -19
- package/dist/exports/runtime.js.map +0 -1
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
escapeLiteral,
|
|
3
|
+
expandParameterizedNativeType,
|
|
4
|
+
normalizeSchemaNativeType,
|
|
5
|
+
parsePostgresDefault,
|
|
6
|
+
quoteIdentifier,
|
|
7
|
+
} from '@prisma-next/adapter-postgres/control';
|
|
1
8
|
import type { SchemaIssue } from '@prisma-next/core-control-plane/types';
|
|
2
9
|
import type {
|
|
10
|
+
CodecControlHooks,
|
|
3
11
|
MigrationOperationPolicy,
|
|
4
12
|
SqlMigrationPlanner,
|
|
5
13
|
SqlMigrationPlannerPlanOptions,
|
|
@@ -8,6 +16,7 @@ import type {
|
|
|
8
16
|
} from '@prisma-next/family-sql/control';
|
|
9
17
|
import {
|
|
10
18
|
createMigrationPlan,
|
|
19
|
+
extractCodecControlHooks,
|
|
11
20
|
plannerFailure,
|
|
12
21
|
plannerSuccess,
|
|
13
22
|
} from '@prisma-next/family-sql/control';
|
|
@@ -25,8 +34,10 @@ import type {
|
|
|
25
34
|
StorageTable,
|
|
26
35
|
} from '@prisma-next/sql-contract/types';
|
|
27
36
|
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
37
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
38
|
+
import type { PostgresColumnDefault } from '../types';
|
|
28
39
|
|
|
29
|
-
type OperationClass = 'extension' | 'table' | 'unique' | 'index' | 'foreignKey';
|
|
40
|
+
type OperationClass = 'extension' | 'type' | 'table' | 'unique' | 'index' | 'foreignKey';
|
|
30
41
|
|
|
31
42
|
type PlannerFrameworkComponents = SqlMigrationPlannerPlanOptions extends {
|
|
32
43
|
readonly frameworkComponents: infer T;
|
|
@@ -88,11 +99,21 @@ class PostgresMigrationPlanner implements SqlMigrationPlanner<PostgresPlanTarget
|
|
|
88
99
|
return plannerFailure(classification.conflicts);
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
// Extract codec control hooks once at entry point for reuse across all operations.
|
|
103
|
+
// This avoids repeated iteration over frameworkComponents for each method that needs hooks.
|
|
104
|
+
const codecHooks = extractCodecControlHooks(options.frameworkComponents);
|
|
105
|
+
|
|
91
106
|
const operations: SqlMigrationPlanOperation<PostgresPlanTargetDetails>[] = [];
|
|
92
107
|
|
|
108
|
+
const storageTypePlan = this.buildStorageTypeOperations(options, schemaName, codecHooks);
|
|
109
|
+
if (storageTypePlan.conflicts.length > 0) {
|
|
110
|
+
return plannerFailure(storageTypePlan.conflicts);
|
|
111
|
+
}
|
|
112
|
+
|
|
93
113
|
// Build extension operations from component-owned database dependencies
|
|
94
114
|
operations.push(
|
|
95
115
|
...this.buildDatabaseDependencyOperations(options),
|
|
116
|
+
...storageTypePlan.operations,
|
|
96
117
|
...this.buildTableOperations(options.contract.storage.tables, options.schema, schemaName),
|
|
97
118
|
...this.buildColumnOperations(options.contract.storage.tables, options.schema, schemaName),
|
|
98
119
|
...this.buildPrimaryKeyOperations(
|
|
@@ -113,8 +134,8 @@ class PostgresMigrationPlanner implements SqlMigrationPlanner<PostgresPlanTarget
|
|
|
113
134
|
targetId: 'postgres',
|
|
114
135
|
origin: null,
|
|
115
136
|
destination: {
|
|
116
|
-
|
|
117
|
-
...(
|
|
137
|
+
storageHash: options.contract.storageHash,
|
|
138
|
+
...ifDefined('profileHash', options.contract.profileHash),
|
|
118
139
|
},
|
|
119
140
|
operations,
|
|
120
141
|
});
|
|
@@ -171,6 +192,55 @@ class PostgresMigrationPlanner implements SqlMigrationPlanner<PostgresPlanTarget
|
|
|
171
192
|
|
|
172
193
|
return operations;
|
|
173
194
|
}
|
|
195
|
+
|
|
196
|
+
private buildStorageTypeOperations(
|
|
197
|
+
options: PlannerOptionsWithComponents,
|
|
198
|
+
schemaName: string,
|
|
199
|
+
codecHooks: Map<string, CodecControlHooks>,
|
|
200
|
+
): {
|
|
201
|
+
readonly operations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[];
|
|
202
|
+
readonly conflicts: readonly SqlPlannerConflict[];
|
|
203
|
+
} {
|
|
204
|
+
const operations: SqlMigrationPlanOperation<PostgresPlanTargetDetails>[] = [];
|
|
205
|
+
const conflicts: SqlPlannerConflict[] = [];
|
|
206
|
+
const storageTypes = options.contract.storage.types ?? {};
|
|
207
|
+
|
|
208
|
+
for (const [typeName, typeInstance] of sortedEntries(storageTypes)) {
|
|
209
|
+
const hook = codecHooks.get(typeInstance.codecId);
|
|
210
|
+
const planResult = hook?.planTypeOperations?.({
|
|
211
|
+
typeName,
|
|
212
|
+
typeInstance,
|
|
213
|
+
contract: options.contract,
|
|
214
|
+
schema: options.schema,
|
|
215
|
+
schemaName,
|
|
216
|
+
policy: options.policy,
|
|
217
|
+
});
|
|
218
|
+
if (!planResult) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
for (const operation of planResult.operations) {
|
|
222
|
+
if (!options.policy.allowedOperationClasses.includes(operation.operationClass)) {
|
|
223
|
+
conflicts.push({
|
|
224
|
+
kind: 'missingButNonAdditive',
|
|
225
|
+
summary: `Storage type "${typeName}" requires "${operation.operationClass}" operation "${operation.id}"`,
|
|
226
|
+
location: {
|
|
227
|
+
type: typeName,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
operations.push({
|
|
233
|
+
...operation,
|
|
234
|
+
target: {
|
|
235
|
+
id: operation.target.id,
|
|
236
|
+
details: this.buildTargetDetails('type', typeName, schemaName),
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return { operations, conflicts };
|
|
243
|
+
}
|
|
174
244
|
private collectDependencies(
|
|
175
245
|
options: PlannerOptionsWithComponents,
|
|
176
246
|
): ReadonlyArray<PlannerDatabaseDependency> {
|
|
@@ -263,15 +333,20 @@ class PostgresMigrationPlanner implements SqlMigrationPlanner<PostgresPlanTarget
|
|
|
263
333
|
): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {
|
|
264
334
|
const qualified = qualifyTableName(schema, tableName);
|
|
265
335
|
const notNull = column.nullable === false;
|
|
336
|
+
const hasDefault = column.default !== undefined;
|
|
337
|
+
// Only require empty table for NOT NULL columns WITHOUT defaults.
|
|
338
|
+
// PostgreSQL allows adding NOT NULL columns with defaults to non-empty tables
|
|
339
|
+
// because the default value is applied to existing rows.
|
|
340
|
+
const requiresEmptyTable = notNull && !hasDefault;
|
|
266
341
|
const precheck = [
|
|
267
342
|
{
|
|
268
343
|
description: `ensure column "${columnName}" is missing`,
|
|
269
344
|
sql: columnExistsCheck({ schema, table: tableName, column: columnName, exists: false }),
|
|
270
345
|
},
|
|
271
|
-
...(
|
|
346
|
+
...(requiresEmptyTable
|
|
272
347
|
? [
|
|
273
348
|
{
|
|
274
|
-
description: `ensure table "${tableName}" is empty before adding NOT NULL column`,
|
|
349
|
+
description: `ensure table "${tableName}" is empty before adding NOT NULL column without default`,
|
|
275
350
|
sql: tableIsEmptyCheck(qualified),
|
|
276
351
|
},
|
|
277
352
|
]
|
|
@@ -524,7 +599,7 @@ REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${forei
|
|
|
524
599
|
schema,
|
|
525
600
|
objectType,
|
|
526
601
|
name,
|
|
527
|
-
...(table
|
|
602
|
+
...ifDefined('table', table),
|
|
528
603
|
};
|
|
529
604
|
}
|
|
530
605
|
|
|
@@ -540,6 +615,8 @@ REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${forei
|
|
|
540
615
|
strict: false,
|
|
541
616
|
typeMetadataRegistry: new Map(),
|
|
542
617
|
frameworkComponents: options.frameworkComponents,
|
|
618
|
+
normalizeDefault: parsePostgresDefault,
|
|
619
|
+
normalizeNativeType: normalizeSchemaNativeType,
|
|
543
620
|
};
|
|
544
621
|
const verifyResult = verifySqlSchema(verifyOptions);
|
|
545
622
|
|
|
@@ -588,16 +665,16 @@ REFERENCES ${qualifyTableName(schemaName, foreignKey.references.table)} (${forei
|
|
|
588
665
|
const meta =
|
|
589
666
|
issue.expected || issue.actual
|
|
590
667
|
? Object.freeze({
|
|
591
|
-
...(
|
|
592
|
-
...(
|
|
668
|
+
...ifDefined('expected', issue.expected),
|
|
669
|
+
...ifDefined('actual', issue.actual),
|
|
593
670
|
})
|
|
594
671
|
: undefined;
|
|
595
672
|
|
|
596
673
|
return {
|
|
597
674
|
kind,
|
|
598
675
|
summary: issue.message,
|
|
599
|
-
...(location
|
|
600
|
-
...(meta
|
|
676
|
+
...ifDefined('location', location),
|
|
677
|
+
...ifDefined('meta', meta),
|
|
601
678
|
};
|
|
602
679
|
}
|
|
603
680
|
}
|
|
@@ -638,7 +715,8 @@ function buildCreateTableSql(qualifiedTableName: string, table: StorageTable): s
|
|
|
638
715
|
([columnName, column]: [string, StorageColumn]) => {
|
|
639
716
|
const parts = [
|
|
640
717
|
quoteIdentifier(columnName),
|
|
641
|
-
column
|
|
718
|
+
buildColumnTypeSql(column),
|
|
719
|
+
buildColumnDefaultSql(column.default),
|
|
642
720
|
column.nullable ? '' : 'NOT NULL',
|
|
643
721
|
].filter(Boolean);
|
|
644
722
|
return parts.join(' ');
|
|
@@ -656,6 +734,83 @@ function buildCreateTableSql(qualifiedTableName: string, table: StorageTable): s
|
|
|
656
734
|
return `CREATE TABLE ${qualifiedTableName} (\n ${allDefinitions.join(',\n ')}\n)`;
|
|
657
735
|
}
|
|
658
736
|
|
|
737
|
+
/**
|
|
738
|
+
* Builds the column type SQL, handling autoincrement as a special case.
|
|
739
|
+
* For autoincrement on int4/int8, we use SERIAL/BIGSERIAL types.
|
|
740
|
+
*/
|
|
741
|
+
function buildColumnTypeSql(column: StorageColumn): string {
|
|
742
|
+
const columnDefault = column.default;
|
|
743
|
+
|
|
744
|
+
// For autoincrement, use SERIAL/BIGSERIAL types instead of int4/int8
|
|
745
|
+
if (columnDefault?.kind === 'function' && columnDefault.expression === 'autoincrement()') {
|
|
746
|
+
if (column.nativeType === 'int4' || column.nativeType === 'integer') {
|
|
747
|
+
return 'SERIAL';
|
|
748
|
+
}
|
|
749
|
+
if (column.nativeType === 'int8' || column.nativeType === 'bigint') {
|
|
750
|
+
return 'BIGSERIAL';
|
|
751
|
+
}
|
|
752
|
+
if (column.nativeType === 'int2' || column.nativeType === 'smallint') {
|
|
753
|
+
return 'SMALLSERIAL';
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if (column.typeRef) {
|
|
758
|
+
return quoteIdentifier(column.nativeType);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return renderParameterizedTypeSql(column) ?? column.nativeType;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Renders parameterized type SQL for a column, returning null if no expansion is needed.
|
|
766
|
+
*
|
|
767
|
+
* Uses the shared expandParameterizedNativeType utility from the postgres adapter.
|
|
768
|
+
* Returns null when the column has no typeParams, allowing the caller to fall back
|
|
769
|
+
* to the base nativeType.
|
|
770
|
+
*/
|
|
771
|
+
function renderParameterizedTypeSql(column: StorageColumn): string | null {
|
|
772
|
+
if (!column.typeParams) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
const expanded = expandParameterizedNativeType({
|
|
777
|
+
nativeType: column.nativeType,
|
|
778
|
+
codecId: column.codecId,
|
|
779
|
+
typeParams: column.typeParams,
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
// If no expansion happened (returned the same base type), return null
|
|
783
|
+
// so caller can decide whether to use nativeType directly
|
|
784
|
+
return expanded !== column.nativeType ? expanded : null;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Builds the DEFAULT clause for a column definition.
|
|
789
|
+
* Returns empty string if no default is defined.
|
|
790
|
+
*
|
|
791
|
+
* Note: autoincrement is handled specially via SERIAL types, so we skip it here.
|
|
792
|
+
*/
|
|
793
|
+
function buildColumnDefaultSql(columnDefault: PostgresColumnDefault | undefined): string {
|
|
794
|
+
if (!columnDefault) {
|
|
795
|
+
return '';
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
switch (columnDefault.kind) {
|
|
799
|
+
case 'literal':
|
|
800
|
+
return `DEFAULT ${columnDefault.expression}`;
|
|
801
|
+
case 'function': {
|
|
802
|
+
// autoincrement is handled by SERIAL type, no explicit DEFAULT needed
|
|
803
|
+
if (columnDefault.expression === 'autoincrement()') {
|
|
804
|
+
return '';
|
|
805
|
+
}
|
|
806
|
+
return `DEFAULT ${columnDefault.expression}`;
|
|
807
|
+
}
|
|
808
|
+
case 'sequence':
|
|
809
|
+
// Sequence names use quoteIdentifier for safe identifier handling
|
|
810
|
+
return `DEFAULT nextval(${quoteIdentifier(columnDefault.name)}::regclass)`;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
659
814
|
function qualifyTableName(schema: string, table: string): string {
|
|
660
815
|
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
661
816
|
}
|
|
@@ -665,16 +820,6 @@ function toRegclassLiteral(schema: string, name: string): string {
|
|
|
665
820
|
return `'${escapeLiteral(regclass)}'`;
|
|
666
821
|
}
|
|
667
822
|
|
|
668
|
-
/** Escapes and quotes a SQL identifier (table, column, schema name). */
|
|
669
|
-
function quoteIdentifier(identifier: string): string {
|
|
670
|
-
// TypeScript enforces string type - no runtime check needed for internal callers
|
|
671
|
-
return `"${identifier.replace(/"/g, '""')}"`;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function escapeLiteral(value: string): string {
|
|
675
|
-
return value.replace(/'/g, "''");
|
|
676
|
-
}
|
|
677
|
-
|
|
678
823
|
function sortedEntries<V>(record: Readonly<Record<string, V>>): Array<[string, V]> {
|
|
679
824
|
return Object.entries(record).sort(([a], [b]) => a.localeCompare(b)) as Array<[string, V]>;
|
|
680
825
|
}
|
|
@@ -746,9 +891,12 @@ function buildAddColumnSql(
|
|
|
746
891
|
columnName: string,
|
|
747
892
|
column: StorageColumn,
|
|
748
893
|
): string {
|
|
894
|
+
const typeSql = buildColumnTypeSql(column);
|
|
895
|
+
const defaultSql = buildColumnDefaultSql(column.default);
|
|
749
896
|
const parts = [
|
|
750
897
|
`ALTER TABLE ${qualifiedTableName}`,
|
|
751
|
-
`ADD COLUMN ${quoteIdentifier(columnName)} ${
|
|
898
|
+
`ADD COLUMN ${quoteIdentifier(columnName)} ${typeSql}`,
|
|
899
|
+
defaultSql,
|
|
752
900
|
column.nullable ? '' : 'NOT NULL',
|
|
753
901
|
].filter(Boolean);
|
|
754
902
|
return parts.join(' ');
|
|
@@ -807,6 +955,8 @@ function hasForeignKey(table: SqlSchemaIR['tables'][string], fk: ForeignKey): bo
|
|
|
807
955
|
|
|
808
956
|
function isAdditiveIssue(issue: SchemaIssue): boolean {
|
|
809
957
|
switch (issue.kind) {
|
|
958
|
+
case 'type_missing':
|
|
959
|
+
case 'type_values_mismatch':
|
|
810
960
|
case 'missing_table':
|
|
811
961
|
case 'missing_column':
|
|
812
962
|
case 'extension_missing':
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeSchemaNativeType,
|
|
3
|
+
parsePostgresDefault,
|
|
4
|
+
} from '@prisma-next/adapter-postgres/control';
|
|
1
5
|
import type { ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
2
6
|
import type {
|
|
3
7
|
MigrationOperationPolicy,
|
|
@@ -14,6 +18,7 @@ import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
|
|
|
14
18
|
import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
|
|
15
19
|
import { readMarker } from '@prisma-next/family-sql/verify';
|
|
16
20
|
import { SqlQueryError } from '@prisma-next/sql-errors';
|
|
21
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
17
22
|
import type { Result } from '@prisma-next/utils/result';
|
|
18
23
|
import { ok, okVoid } from '@prisma-next/utils/result';
|
|
19
24
|
import type { PostgresPlanTargetDetails } from './planner';
|
|
@@ -141,6 +146,8 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
141
146
|
context: options.context ?? {},
|
|
142
147
|
typeMetadataRegistry: this.family.typeMetadataRegistry,
|
|
143
148
|
frameworkComponents: options.frameworkComponents,
|
|
149
|
+
normalizeDefault: parsePostgresDefault,
|
|
150
|
+
normalizeNativeType: normalizeSchemaNativeType,
|
|
144
151
|
});
|
|
145
152
|
if (!schemaVerifyResult.ok) {
|
|
146
153
|
return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
|
|
@@ -371,13 +378,13 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
371
378
|
return Object.freeze({
|
|
372
379
|
id: operation.id,
|
|
373
380
|
label: operation.label,
|
|
374
|
-
...(
|
|
381
|
+
...ifDefined('summary', operation.summary),
|
|
375
382
|
operationClass: operation.operationClass,
|
|
376
383
|
target: operation.target, // Already frozen from plan creation
|
|
377
384
|
precheck: Object.freeze([]),
|
|
378
385
|
execute: Object.freeze([]),
|
|
379
386
|
postcheck: frozenPostcheck,
|
|
380
|
-
...(operation.meta || mergedMeta ?
|
|
387
|
+
...ifDefined('meta', operation.meta || mergedMeta ? mergedMeta : undefined),
|
|
381
388
|
});
|
|
382
389
|
}
|
|
383
390
|
|
|
@@ -388,7 +395,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
388
395
|
if (!marker) {
|
|
389
396
|
return false;
|
|
390
397
|
}
|
|
391
|
-
if (marker.
|
|
398
|
+
if (marker.storageHash !== plan.destination.storageHash) {
|
|
392
399
|
return false;
|
|
393
400
|
}
|
|
394
401
|
if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {
|
|
@@ -435,10 +442,10 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
435
442
|
}
|
|
436
443
|
return runnerFailure(
|
|
437
444
|
'MARKER_ORIGIN_MISMATCH',
|
|
438
|
-
`Existing contract marker (${marker.
|
|
445
|
+
`Existing contract marker (${marker.storageHash}) does not match plan origin (no marker expected).`,
|
|
439
446
|
{
|
|
440
447
|
meta: {
|
|
441
|
-
|
|
448
|
+
markerStorageHash: marker.storageHash,
|
|
442
449
|
expectedOrigin: null,
|
|
443
450
|
},
|
|
444
451
|
},
|
|
@@ -448,22 +455,22 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
448
455
|
if (!marker) {
|
|
449
456
|
return runnerFailure(
|
|
450
457
|
'MARKER_ORIGIN_MISMATCH',
|
|
451
|
-
`Missing contract marker: expected origin
|
|
458
|
+
`Missing contract marker: expected origin storage hash ${origin.storageHash}.`,
|
|
452
459
|
{
|
|
453
460
|
meta: {
|
|
454
|
-
|
|
461
|
+
expectedOriginStorageHash: origin.storageHash,
|
|
455
462
|
},
|
|
456
463
|
},
|
|
457
464
|
);
|
|
458
465
|
}
|
|
459
|
-
if (marker.
|
|
466
|
+
if (marker.storageHash !== origin.storageHash) {
|
|
460
467
|
return runnerFailure(
|
|
461
468
|
'MARKER_ORIGIN_MISMATCH',
|
|
462
|
-
`Existing contract marker (${marker.
|
|
469
|
+
`Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`,
|
|
463
470
|
{
|
|
464
471
|
meta: {
|
|
465
|
-
|
|
466
|
-
|
|
472
|
+
markerStorageHash: marker.storageHash,
|
|
473
|
+
expectedOriginStorageHash: origin.storageHash,
|
|
467
474
|
},
|
|
468
475
|
},
|
|
469
476
|
);
|
|
@@ -487,14 +494,14 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
487
494
|
destination: SqlMigrationPlanContractInfo,
|
|
488
495
|
contract: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['destinationContract'],
|
|
489
496
|
): Result<void, SqlMigrationRunnerFailure> {
|
|
490
|
-
if (destination.
|
|
497
|
+
if (destination.storageHash !== contract.storageHash) {
|
|
491
498
|
return runnerFailure(
|
|
492
499
|
'DESTINATION_CONTRACT_MISMATCH',
|
|
493
|
-
`Plan destination
|
|
500
|
+
`Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storageHash}).`,
|
|
494
501
|
{
|
|
495
502
|
meta: {
|
|
496
|
-
|
|
497
|
-
|
|
503
|
+
planStorageHash: destination.storageHash,
|
|
504
|
+
contractStorageHash: contract.storageHash,
|
|
498
505
|
},
|
|
499
506
|
},
|
|
500
507
|
);
|
|
@@ -524,11 +531,11 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
524
531
|
existingMarker: ContractMarkerRecord | null,
|
|
525
532
|
): Promise<void> {
|
|
526
533
|
const writeStatements = buildWriteMarkerStatements({
|
|
527
|
-
|
|
534
|
+
storageHash: options.plan.destination.storageHash,
|
|
528
535
|
profileHash:
|
|
529
536
|
options.plan.destination.profileHash ??
|
|
530
537
|
options.destinationContract.profileHash ??
|
|
531
|
-
options.plan.destination.
|
|
538
|
+
options.plan.destination.storageHash,
|
|
532
539
|
contractJson: options.destinationContract,
|
|
533
540
|
canonicalVersion: null,
|
|
534
541
|
meta: {},
|
|
@@ -544,13 +551,13 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
544
551
|
executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
|
|
545
552
|
): Promise<void> {
|
|
546
553
|
const ledgerStatement = buildLedgerInsertStatement({
|
|
547
|
-
|
|
554
|
+
originStorageHash: existingMarker?.storageHash ?? null,
|
|
548
555
|
originProfileHash: existingMarker?.profileHash ?? null,
|
|
549
|
-
|
|
556
|
+
destinationStorageHash: options.plan.destination.storageHash,
|
|
550
557
|
destinationProfileHash:
|
|
551
558
|
options.plan.destination.profileHash ??
|
|
552
559
|
options.destinationContract.profileHash ??
|
|
553
|
-
options.plan.destination.
|
|
560
|
+
options.plan.destination.storageHash,
|
|
554
561
|
contractJsonBefore: existingMarker?.contractJson ?? null,
|
|
555
562
|
contractJsonAfter: options.destinationContract,
|
|
556
563
|
operations: executedOperations,
|
|
@@ -38,7 +38,7 @@ export const ensureLedgerTableStatement: SqlStatement = {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
export interface WriteMarkerInput {
|
|
41
|
-
readonly
|
|
41
|
+
readonly storageHash: string;
|
|
42
42
|
readonly profileHash: string;
|
|
43
43
|
readonly contractJson?: unknown;
|
|
44
44
|
readonly canonicalVersion?: number | null;
|
|
@@ -52,7 +52,7 @@ export function buildWriteMarkerStatements(input: WriteMarkerInput): {
|
|
|
52
52
|
} {
|
|
53
53
|
const params: readonly unknown[] = [
|
|
54
54
|
1,
|
|
55
|
-
input.
|
|
55
|
+
input.storageHash,
|
|
56
56
|
input.profileHash,
|
|
57
57
|
jsonParam(input.contractJson),
|
|
58
58
|
input.canonicalVersion ?? null,
|
|
@@ -99,9 +99,9 @@ export function buildWriteMarkerStatements(input: WriteMarkerInput): {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export interface LedgerInsertInput {
|
|
102
|
-
readonly
|
|
102
|
+
readonly originStorageHash?: string | null;
|
|
103
103
|
readonly originProfileHash?: string | null;
|
|
104
|
-
readonly
|
|
104
|
+
readonly destinationStorageHash: string;
|
|
105
105
|
readonly destinationProfileHash?: string | null;
|
|
106
106
|
readonly contractJsonBefore?: unknown;
|
|
107
107
|
readonly contractJsonAfter?: unknown;
|
|
@@ -128,9 +128,9 @@ export function buildLedgerInsertStatement(input: LedgerInsertInput): SqlStateme
|
|
|
128
128
|
$7::jsonb
|
|
129
129
|
)`,
|
|
130
130
|
params: [
|
|
131
|
-
input.
|
|
131
|
+
input.originStorageHash ?? null,
|
|
132
132
|
input.originProfileHash ?? null,
|
|
133
|
-
input.
|
|
133
|
+
input.destinationStorageHash,
|
|
134
134
|
input.destinationProfileHash ?? null,
|
|
135
135
|
jsonParam(input.contractJsonBefore),
|
|
136
136
|
jsonParam(input.contractJsonAfter),
|
package/src/exports/control.ts
CHANGED
|
@@ -12,12 +12,10 @@ import type { PostgresPlanTargetDetails } from '../core/migrations/planner';
|
|
|
12
12
|
import { createPostgresMigrationPlanner } from '../core/migrations/planner';
|
|
13
13
|
import { createPostgresMigrationRunner } from '../core/migrations/runner';
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Postgres target descriptor for CLI config.
|
|
17
|
-
*/
|
|
18
15
|
const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails> =
|
|
19
16
|
{
|
|
20
17
|
...postgresTargetDescriptorMeta,
|
|
18
|
+
operationSignatures: () => [],
|
|
21
19
|
/**
|
|
22
20
|
* Migrations capability for CLI to access planner/runner via core types.
|
|
23
21
|
* The SQL-specific planner/runner types are compatible with the generic
|
package/src/exports/runtime.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from '@prisma-next/core-execution-plane/types';
|
|
1
|
+
import type { RuntimeTargetInstance } from '@prisma-next/core-execution-plane/types';
|
|
2
|
+
import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
|
|
3
|
+
import type { SqlRuntimeTargetDescriptor } from '@prisma-next/sql-runtime';
|
|
5
4
|
import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
|
|
6
5
|
|
|
7
|
-
/**
|
|
8
|
-
* Postgres runtime target instance interface.
|
|
9
|
-
*/
|
|
10
6
|
export interface PostgresRuntimeTargetInstance extends RuntimeTargetInstance<'sql', 'postgres'> {}
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
* Postgres target descriptor for runtime plane.
|
|
14
|
-
*/
|
|
15
|
-
const postgresRuntimeTargetDescriptor: RuntimeTargetDescriptor<
|
|
16
|
-
'sql',
|
|
8
|
+
const postgresRuntimeTargetDescriptor: SqlRuntimeTargetDescriptor<
|
|
17
9
|
'postgres',
|
|
18
10
|
PostgresRuntimeTargetInstance
|
|
19
11
|
> = {
|
|
20
12
|
...postgresTargetDescriptorMeta,
|
|
13
|
+
codecs: () => createCodecRegistry(),
|
|
14
|
+
operationSignatures: () => [],
|
|
15
|
+
parameterizedCodecs: () => [],
|
|
21
16
|
create(): PostgresRuntimeTargetInstance {
|
|
22
17
|
return {
|
|
23
18
|
familyId: 'sql',
|
package/dist/chunk-RKEXRSSI.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// src/core/descriptor-meta.ts
|
|
2
|
-
var postgresTargetDescriptorMeta = {
|
|
3
|
-
kind: "target",
|
|
4
|
-
familyId: "sql",
|
|
5
|
-
targetId: "postgres",
|
|
6
|
-
id: "postgres",
|
|
7
|
-
version: "0.0.1",
|
|
8
|
-
capabilities: {}
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export {
|
|
12
|
-
postgresTargetDescriptorMeta
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=chunk-RKEXRSSI.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/descriptor-meta.ts"],"sourcesContent":["export const postgresTargetDescriptorMeta = {\n kind: 'target',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {},\n} as const;\n"],"mappings":";AAAO,IAAM,+BAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,cAAc,CAAC;AACjB;","names":[]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare const postgresTargetDescriptorMeta: {
|
|
2
|
-
readonly kind: "target";
|
|
3
|
-
readonly familyId: "sql";
|
|
4
|
-
readonly targetId: "postgres";
|
|
5
|
-
readonly id: "postgres";
|
|
6
|
-
readonly version: "0.0.1";
|
|
7
|
-
readonly capabilities: {};
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=descriptor-meta.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-meta.d.ts","sourceRoot":"","sources":["../../src/core/descriptor-meta.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B;;;;;;;CAO/B,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { SqlMigrationPlanner } from '@prisma-next/family-sql/control';
|
|
2
|
-
type OperationClass = 'extension' | 'table' | 'unique' | 'index' | 'foreignKey';
|
|
3
|
-
export interface PostgresPlanTargetDetails {
|
|
4
|
-
readonly schema: string;
|
|
5
|
-
readonly objectType: OperationClass;
|
|
6
|
-
readonly name: string;
|
|
7
|
-
readonly table?: string;
|
|
8
|
-
}
|
|
9
|
-
interface PlannerConfig {
|
|
10
|
-
readonly defaultSchema: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function createPostgresMigrationPlanner(config?: Partial<PlannerConfig>): SqlMigrationPlanner<PostgresPlanTargetDetails>;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=planner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/planner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,mBAAmB,EAIpB,MAAM,iCAAiC,CAAC;AAqBzC,KAAK,cAAc,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;AAuBhF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAMD,wBAAgB,8BAA8B,CAC5C,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,mBAAmB,CAAC,yBAAyB,CAAC,CAKhD"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { SqlControlFamilyInstance, SqlMigrationRunner } from '@prisma-next/family-sql/control';
|
|
2
|
-
import type { PostgresPlanTargetDetails } from './planner';
|
|
3
|
-
interface RunnerConfig {
|
|
4
|
-
readonly defaultSchema: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function createPostgresMigrationRunner(family: SqlControlFamilyInstance, config?: Partial<RunnerConfig>): SqlMigrationRunner<PostgresPlanTargetDetails>;
|
|
7
|
-
export {};
|
|
8
|
-
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,wBAAwB,EAIxB,kBAAkB,EAInB,MAAM,iCAAiC,CAAC;AAOzC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAU3D,UAAU,YAAY;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAoCD,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,wBAAwB,EAChC,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM,GACjC,kBAAkB,CAAC,yBAAyB,CAAC,CAE/C"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export interface SqlStatement {
|
|
2
|
-
readonly sql: string;
|
|
3
|
-
readonly params: readonly unknown[];
|
|
4
|
-
}
|
|
5
|
-
export declare const ensurePrismaContractSchemaStatement: SqlStatement;
|
|
6
|
-
export declare const ensureMarkerTableStatement: SqlStatement;
|
|
7
|
-
export declare const ensureLedgerTableStatement: SqlStatement;
|
|
8
|
-
export interface WriteMarkerInput {
|
|
9
|
-
readonly coreHash: string;
|
|
10
|
-
readonly profileHash: string;
|
|
11
|
-
readonly contractJson?: unknown;
|
|
12
|
-
readonly canonicalVersion?: number | null;
|
|
13
|
-
readonly appTag?: string | null;
|
|
14
|
-
readonly meta?: Record<string, unknown>;
|
|
15
|
-
}
|
|
16
|
-
export declare function buildWriteMarkerStatements(input: WriteMarkerInput): {
|
|
17
|
-
readonly insert: SqlStatement;
|
|
18
|
-
readonly update: SqlStatement;
|
|
19
|
-
};
|
|
20
|
-
export interface LedgerInsertInput {
|
|
21
|
-
readonly originCoreHash?: string | null;
|
|
22
|
-
readonly originProfileHash?: string | null;
|
|
23
|
-
readonly destinationCoreHash: string;
|
|
24
|
-
readonly destinationProfileHash?: string | null;
|
|
25
|
-
readonly contractJsonBefore?: unknown;
|
|
26
|
-
readonly contractJsonAfter?: unknown;
|
|
27
|
-
readonly operations: unknown;
|
|
28
|
-
}
|
|
29
|
-
export declare function buildLedgerInsertStatement(input: LedgerInsertInput): SqlStatement;
|
|
30
|
-
//# sourceMappingURL=statement-builders.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"statement-builders.d.ts","sourceRoot":"","sources":["../../../src/core/migrations/statement-builders.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;CACrC;AAED,eAAO,MAAM,mCAAmC,EAAE,YAGjD,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,YAYxC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,YAaxC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG;IACnE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B,CA+CA;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CA6BjF"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { SqlControlTargetDescriptor } from '@prisma-next/family-sql/control';
|
|
2
|
-
import type { PostgresPlanTargetDetails } from '../core/migrations/planner';
|
|
3
|
-
/**
|
|
4
|
-
* Postgres target descriptor for CLI config.
|
|
5
|
-
*/
|
|
6
|
-
declare const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails>;
|
|
7
|
-
export default postgresTargetDescriptor;
|
|
8
|
-
//# sourceMappingURL=control.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../src/exports/control.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,0BAA0B,EAC3B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAI5E;;GAEG;AACH,QAAA,MAAM,wBAAwB,EAAE,0BAA0B,CAAC,UAAU,EAAE,yBAAyB,CAoC7F,CAAC;AAEJ,eAAe,wBAAwB,CAAC"}
|