@prisma-next/target-postgres 0.12.0-dev.6 → 0.12.0-dev.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{codec-ids-DliyCWPY.d.mts → codec-ids-B1vOchLE.d.mts} +3 -2
- package/dist/codec-ids-B1vOchLE.d.mts.map +1 -0
- package/dist/{codec-ids-C5qzBqus.mjs → codec-ids-CTikp1if.mjs} +3 -2
- package/dist/codec-ids-CTikp1if.mjs.map +1 -0
- package/dist/codec-ids.d.mts +2 -2
- package/dist/codec-ids.mjs +2 -2
- package/dist/{codec-types-BF1DXTPs.d.mts → codec-types-CnFiNML4.d.mts} +8 -9
- package/dist/codec-types-CnFiNML4.d.mts.map +1 -0
- package/dist/codec-types.d.mts +2 -2
- package/dist/{codecs-DuP3d9Au.d.mts → codecs-CBpEv4s5.d.mts} +33 -35
- package/dist/codecs-CBpEv4s5.d.mts.map +1 -0
- package/dist/codecs.d.mts +1 -1
- package/dist/codecs.mjs +37 -2
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.d.mts +75 -0
- package/dist/contract-free.d.mts.map +1 -0
- package/dist/contract-free.mjs +139 -0
- package/dist/contract-free.mjs.map +1 -0
- package/dist/control.d.mts +1 -1
- package/dist/control.mjs +62 -36
- package/dist/control.mjs.map +1 -1
- package/dist/{data-transform-CRkv2T_U.mjs → data-transform-D25tLeYU.mjs} +1 -1
- package/dist/{data-transform-CRkv2T_U.mjs.map → data-transform-D25tLeYU.mjs.map} +1 -1
- package/dist/{data-transform-CAPmAdxS.d.mts → data-transform-lq3NGdIt.d.mts} +2 -2
- package/dist/{data-transform-CAPmAdxS.d.mts.map → data-transform-lq3NGdIt.d.mts.map} +1 -1
- package/dist/data-transform.d.mts +1 -1
- package/dist/data-transform.mjs +1 -1
- package/dist/ddl.d.mts +2 -0
- package/dist/ddl.mjs +2 -0
- package/dist/{default-normalizer-DaAhmzBV.mjs → default-normalizer-DyyCHQWs.mjs} +1 -1
- package/dist/{default-normalizer-DaAhmzBV.mjs.map → default-normalizer-DyyCHQWs.mjs.map} +1 -1
- package/dist/default-normalizer.mjs +1 -1
- package/dist/{descriptor-meta-Uu8QaClr.mjs → descriptor-meta-DKmj-IMN.mjs} +3 -2
- package/dist/descriptor-meta-DKmj-IMN.mjs.map +1 -0
- package/dist/{descriptor-meta-runtime-DMRX39kp.mjs → descriptor-meta-runtime-My8_s4cs.mjs} +2 -2
- package/dist/{descriptor-meta-runtime-DMRX39kp.mjs.map → descriptor-meta-runtime-My8_s4cs.mjs.map} +1 -1
- package/dist/{enum-planning-DRA9LaMU.mjs → enum-planning-BCyvlFHk.mjs} +0 -0
- package/dist/{enum-planning-DRA9LaMU.mjs.map → enum-planning-BCyvlFHk.mjs.map} +1 -1
- package/dist/enum-planning.d.mts +1 -1
- package/dist/enum-planning.mjs +1 -1
- package/dist/{errors-BbnITmAD.mjs → errors-CUk87ByX.mjs} +1 -1
- package/dist/{errors-BbnITmAD.mjs.map → errors-CUk87ByX.mjs.map} +1 -1
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/{issue-planner-BtaL6OfW.mjs → issue-planner-hxJaxYHv.mjs} +22 -23
- package/dist/issue-planner-hxJaxYHv.mjs.map +1 -0
- package/dist/issue-planner.d.mts +1 -1
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +3 -3
- package/dist/migration.mjs +3 -3
- package/dist/{native-type-normalizer-BNEQ9VDs.mjs → native-type-normalizer-Bc9XJzWC.mjs} +1 -1
- package/dist/{native-type-normalizer-BNEQ9VDs.mjs.map → native-type-normalizer-Bc9XJzWC.mjs.map} +1 -1
- package/dist/native-type-normalizer.mjs +1 -1
- package/dist/nodes-Dm1XR7UL.mjs +42 -0
- package/dist/nodes-Dm1XR7UL.mjs.map +1 -0
- package/dist/nodes-Dq0ALHOk.d.mts +38 -0
- package/dist/nodes-Dq0ALHOk.d.mts.map +1 -0
- package/dist/{op-factory-call-CDlImOF_.d.mts → op-factory-call-D47zfLOp.d.mts} +3 -3
- package/dist/op-factory-call-D47zfLOp.d.mts.map +1 -0
- package/dist/{op-factory-call-ewOd5q6L.mjs → op-factory-call-G9G02kxC.mjs} +2 -2
- package/dist/{op-factory-call-ewOd5q6L.mjs.map → op-factory-call-G9G02kxC.mjs.map} +1 -1
- package/dist/op-factory-call.d.mts +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/pack.d.mts +5 -6
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/planner-C5tapy2_.mjs +340 -0
- package/dist/planner-C5tapy2_.mjs.map +1 -0
- package/dist/{planner-ddl-builders-BNMfSE9r.mjs → planner-ddl-builders-DDyptTt5.mjs} +4 -28
- package/dist/planner-ddl-builders-DDyptTt5.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts +3 -4
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-ddl-builders.mjs +2 -2
- package/dist/{planner-identity-values-nhVj0hp-.mjs → planner-identity-values-BIpa5p2I.mjs} +1 -1
- package/dist/{planner-identity-values-nhVj0hp-.mjs.map → planner-identity-values-BIpa5p2I.mjs.map} +1 -1
- package/dist/planner-identity-values.mjs +1 -1
- package/dist/{planner-produced-postgres-migration-D_nsXbhl.mjs → planner-produced-postgres-migration-BCy50btZ.mjs} +4 -4
- package/dist/{planner-produced-postgres-migration-D_nsXbhl.mjs.map → planner-produced-postgres-migration-BCy50btZ.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-D02NOhVQ.d.mts → planner-produced-postgres-migration-CpsGhewL.d.mts} +3 -3
- package/dist/planner-produced-postgres-migration-CpsGhewL.d.mts.map +1 -0
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-schema-lookup-CGxxYfnD.mjs → planner-schema-lookup-CiVaAQP-.mjs} +1 -1
- package/dist/{planner-schema-lookup-CGxxYfnD.mjs.map → planner-schema-lookup-CiVaAQP-.mjs.map} +1 -1
- package/dist/planner-schema-lookup.mjs +1 -1
- package/dist/{planner-sql-checks-CfEiTXoQ.mjs → planner-sql-checks-DAdhnI2c.mjs} +41 -30
- package/dist/planner-sql-checks-DAdhnI2c.mjs.map +1 -0
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/{planner-target-details-a_wuOiYf.d.mts → planner-target-details-DyUHJ7MY.d.mts} +1 -1
- package/dist/{planner-target-details-a_wuOiYf.d.mts.map → planner-target-details-DyUHJ7MY.d.mts.map} +1 -1
- package/dist/planner-target-details.d.mts +2 -2
- package/dist/planner-type-resolution-836DExFN.mjs +20 -0
- package/dist/planner-type-resolution-836DExFN.mjs.map +1 -0
- package/dist/planner.d.mts +3 -2
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/{postgres-contract-serializer-BnOboPWs.mjs → postgres-contract-serializer-DYTyXjPf.mjs} +33 -24
- package/dist/postgres-contract-serializer-DYTyXjPf.mjs.map +1 -0
- package/dist/{postgres-enum-type-CSzsvXrO.d.mts → postgres-enum-type-BVn63a89.d.mts} +1 -1
- package/dist/{postgres-enum-type-CSzsvXrO.d.mts.map → postgres-enum-type-BVn63a89.d.mts.map} +1 -1
- package/dist/{postgres-enum-type-BMgyxNyy.mjs → postgres-enum-type-DPKqCBem.mjs} +1 -1
- package/dist/{postgres-enum-type-BMgyxNyy.mjs.map → postgres-enum-type-DPKqCBem.mjs.map} +1 -1
- package/dist/{postgres-migration-DRY8V-bQ.d.mts → postgres-migration--iqDr7rB.d.mts} +3 -3
- package/dist/{postgres-migration-DRY8V-bQ.d.mts.map → postgres-migration--iqDr7rB.d.mts.map} +1 -1
- package/dist/{postgres-migration-BatbEvU6.mjs → postgres-migration-DcymFlMG.mjs} +3 -3
- package/dist/{postgres-migration-BatbEvU6.mjs.map → postgres-migration-DcymFlMG.mjs.map} +1 -1
- package/dist/{postgres-schema-BxAuNFX0.mjs → postgres-schema-BuxCxbvB.mjs} +29 -14
- package/dist/postgres-schema-BuxCxbvB.mjs.map +1 -0
- package/dist/{render-ops-XhICjX_P.mjs → render-ops-Wb6SCGmj.mjs} +1 -1
- package/dist/{render-ops-XhICjX_P.mjs.map → render-ops-Wb6SCGmj.mjs.map} +1 -1
- package/dist/render-ops.d.mts +1 -1
- package/dist/render-ops.mjs +1 -1
- package/dist/{render-typescript-K125n-RZ.mjs → render-typescript-BShM6uyS.mjs} +1 -1
- package/dist/{render-typescript-K125n-RZ.mjs.map → render-typescript-BShM6uyS.mjs.map} +1 -1
- package/dist/render-typescript.mjs +1 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/{shared-Do_a5ymU.d.mts → shared-C3gXQyxj.d.mts} +2 -2
- package/dist/{shared-Do_a5ymU.d.mts.map → shared-C3gXQyxj.d.mts.map} +1 -1
- package/dist/{sql-utils-CggjWNij.mjs → sql-utils-DcfMz4MQ.mjs} +1 -1
- package/dist/{sql-utils-CggjWNij.mjs.map → sql-utils-DcfMz4MQ.mjs.map} +1 -1
- package/dist/sql-utils.mjs +1 -1
- package/dist/{tables-DoA39Yqo.mjs → tables-OLIoVjxf.mjs} +3 -3
- package/dist/{tables-DoA39Yqo.mjs.map → tables-OLIoVjxf.mjs.map} +1 -1
- package/dist/{types-O40IcFV9.d.mts → types-BDKkx8MA.d.mts} +1 -1
- package/dist/types-BDKkx8MA.d.mts.map +1 -0
- package/dist/types.d.mts +16 -11
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -2
- package/package.json +21 -20
- package/src/contract-free/columns.ts +49 -0
- package/src/contract-free/control-bootstrap.ts +55 -0
- package/src/contract-free/ddl.ts +32 -0
- package/src/core/ast/table-source.ts +23 -0
- package/src/core/codec-ids.ts +1 -0
- package/src/core/codecs.ts +44 -0
- package/src/core/ddl/nodes.ts +59 -0
- package/src/core/descriptor-meta.ts +1 -0
- package/src/core/migrations/control-policy.ts +234 -0
- package/src/core/migrations/issue-planner.ts +3 -3
- package/src/core/migrations/planner-ddl-builders.ts +0 -42
- package/src/core/migrations/planner-sql-checks.ts +9 -9
- package/src/core/migrations/planner-strategies.ts +16 -10
- package/src/core/migrations/planner.ts +55 -6
- package/src/core/migrations/runner.ts +78 -50
- package/src/core/postgres-contract-serializer.ts +52 -46
- package/src/core/postgres-schema.ts +43 -25
- package/src/exports/contract-free.ts +7 -0
- package/src/exports/ddl.ts +7 -0
- package/src/exports/planner-ddl-builders.ts +0 -1
- package/dist/codec-ids-C5qzBqus.mjs.map +0 -1
- package/dist/codec-ids-DliyCWPY.d.mts.map +0 -1
- package/dist/codec-types-BF1DXTPs.d.mts.map +0 -1
- package/dist/codecs-DuP3d9Au.d.mts.map +0 -1
- package/dist/descriptor-meta-Uu8QaClr.mjs.map +0 -1
- package/dist/issue-planner-BtaL6OfW.mjs.map +0 -1
- package/dist/op-factory-call-CDlImOF_.d.mts.map +0 -1
- package/dist/planner-Bjz5pnLa.mjs +0 -177
- package/dist/planner-Bjz5pnLa.mjs.map +0 -1
- package/dist/planner-ddl-builders-BNMfSE9r.mjs.map +0 -1
- package/dist/planner-produced-postgres-migration-D02NOhVQ.d.mts.map +0 -1
- package/dist/planner-sql-checks-CfEiTXoQ.mjs.map +0 -1
- package/dist/postgres-contract-serializer-BnOboPWs.mjs.map +0 -1
- package/dist/postgres-schema-BxAuNFX0.mjs.map +0 -1
- package/dist/statement-builders-DVI5IVAa.mjs +0 -131
- package/dist/statement-builders-DVI5IVAa.mjs.map +0 -1
- package/dist/statement-builders.d.mts +0 -51
- package/dist/statement-builders.d.mts.map +0 -1
- package/dist/statement-builders.mjs +0 -2
- package/dist/types-O40IcFV9.d.mts.map +0 -1
- package/src/core/migrations/statement-builders.ts +0 -183
- package/src/exports/statement-builders.ts +0 -8
|
@@ -20,11 +20,11 @@ import { resolveColumnTypeMetadata } from './planner-type-resolution';
|
|
|
20
20
|
* site.
|
|
21
21
|
*/
|
|
22
22
|
export function qualifyTableName(schema: string, table: string): string {
|
|
23
|
-
return postgresCreateNamespace({ id: schema }).qualifyTable(table);
|
|
23
|
+
return postgresCreateNamespace({ id: schema, entries: { table: {} } }).qualifyTable(table);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function toRegclassLiteral(schema: string, name: string): string {
|
|
27
|
-
return postgresCreateNamespace({ id: schema }).regclassLiteral(name);
|
|
27
|
+
return postgresCreateNamespace({ id: schema, entries: { table: {} } }).regclassLiteral(name);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -43,7 +43,7 @@ export function constraintExistsCheck({
|
|
|
43
43
|
table?: string;
|
|
44
44
|
exists?: boolean;
|
|
45
45
|
}): string {
|
|
46
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
46
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
47
47
|
const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';
|
|
48
48
|
const tableFilter = table
|
|
49
49
|
? `AND c.conrelid = to_regclass(${namespace.regclassLiteral(table)})`
|
|
@@ -68,7 +68,7 @@ export function columnExistsCheck({
|
|
|
68
68
|
column: string;
|
|
69
69
|
exists?: boolean;
|
|
70
70
|
}): string {
|
|
71
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
71
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
72
72
|
const existsClause = exists ? '' : 'NOT ';
|
|
73
73
|
return `SELECT ${existsClause}EXISTS (
|
|
74
74
|
SELECT 1
|
|
@@ -90,7 +90,7 @@ export function columnNullabilityCheck({
|
|
|
90
90
|
column: string;
|
|
91
91
|
nullable: boolean;
|
|
92
92
|
}): string {
|
|
93
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
93
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
94
94
|
const expected = nullable ? 'YES' : 'NO';
|
|
95
95
|
return `SELECT EXISTS (
|
|
96
96
|
SELECT 1
|
|
@@ -111,7 +111,7 @@ export function columnHasNoDefaultCheck(opts: {
|
|
|
111
111
|
table: string;
|
|
112
112
|
column: string;
|
|
113
113
|
}): string {
|
|
114
|
-
const namespace = postgresCreateNamespace({ id: opts.schema });
|
|
114
|
+
const namespace = postgresCreateNamespace({ id: opts.schema, entries: { table: {} } });
|
|
115
115
|
return `SELECT NOT EXISTS (
|
|
116
116
|
SELECT 1
|
|
117
117
|
FROM information_schema.columns
|
|
@@ -282,7 +282,7 @@ export function columnTypeCheck({
|
|
|
282
282
|
column: string;
|
|
283
283
|
expectedType: string;
|
|
284
284
|
}): string {
|
|
285
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
285
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
286
286
|
return `SELECT EXISTS (
|
|
287
287
|
SELECT 1
|
|
288
288
|
FROM pg_attribute a
|
|
@@ -307,7 +307,7 @@ export function columnDefaultExistsCheck({
|
|
|
307
307
|
column: string;
|
|
308
308
|
exists?: boolean;
|
|
309
309
|
}): string {
|
|
310
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
310
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
311
311
|
const nullCheck = exists ? 'IS NOT NULL' : 'IS NULL';
|
|
312
312
|
return `SELECT EXISTS (
|
|
313
313
|
SELECT 1
|
|
@@ -325,7 +325,7 @@ export function tableHasPrimaryKeyCheck(
|
|
|
325
325
|
exists: boolean,
|
|
326
326
|
constraintName?: string,
|
|
327
327
|
): string {
|
|
328
|
-
const namespace = postgresCreateNamespace({ id: schema });
|
|
328
|
+
const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
|
|
329
329
|
const comparison = exists ? '' : 'NOT ';
|
|
330
330
|
const constraintFilter = constraintName
|
|
331
331
|
? `AND c2.relname = '${escapeLiteral(constraintName)}'`
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
type StorageTypeInstance,
|
|
36
36
|
} from '@prisma-next/sql-contract/types';
|
|
37
37
|
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
38
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
38
39
|
import { PostgresEnumType } from '../postgres-enum-type';
|
|
39
40
|
import { isPostgresSchema } from '../postgres-schema';
|
|
40
41
|
import {
|
|
@@ -93,7 +94,7 @@ export function tableAt(
|
|
|
93
94
|
): StorageTable | undefined {
|
|
94
95
|
// Namespace.tables is typed as Record<string, IRNode> at the interface level;
|
|
95
96
|
// SQL family namespaces always hold StorageTable instances.
|
|
96
|
-
return storage.namespaces[namespaceId]?.
|
|
97
|
+
return storage.namespaces[namespaceId]?.entries.table[tableName] as StorageTable | undefined;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/**
|
|
@@ -134,8 +135,8 @@ const DEFAULT_ENUM_NAMESPACE_ID = 'public';
|
|
|
134
135
|
|
|
135
136
|
function namespaceHasEnum(storage: SqlStorage, namespaceId: string, typeName: string): boolean {
|
|
136
137
|
const ns = storage.namespaces[namespaceId];
|
|
137
|
-
if (!
|
|
138
|
-
return
|
|
138
|
+
if (!isPostgresSchema(ns)) return false;
|
|
139
|
+
return ns.entries.type[typeName] !== undefined;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
/**
|
|
@@ -166,7 +167,7 @@ function resolveColumnEnumNamespace(
|
|
|
166
167
|
|
|
167
168
|
/**
|
|
168
169
|
* Finds a type entry by explicit namespace coordinate. Namespace types (e.g.
|
|
169
|
-
* Postgres enums) live under `storage.namespaces[nsId].
|
|
170
|
+
* Postgres enums) live under `storage.namespaces[nsId].entries.type`. Returns the
|
|
170
171
|
* entry from the named namespace only — never scans other namespaces, so two
|
|
171
172
|
* namespaces that hold an enum with the same name resolve independently.
|
|
172
173
|
*/
|
|
@@ -176,8 +177,12 @@ function locateNamespaceType(
|
|
|
176
177
|
typeName: string,
|
|
177
178
|
): PostgresEnumStorageEntry | undefined {
|
|
178
179
|
const ns = storage.namespaces[namespaceId];
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
const raw = ns?.entries['type']?.[typeName];
|
|
181
|
+
if (raw === undefined) return undefined;
|
|
182
|
+
return blindCast<
|
|
183
|
+
PostgresEnumStorageEntry,
|
|
184
|
+
'postgres type slot carries PostgresEnumStorageEntry at the postgres target layer'
|
|
185
|
+
>(raw);
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
// ============================================================================
|
|
@@ -436,7 +441,7 @@ function enumRebuildCallRecipe(
|
|
|
436
441
|
// same-named enums in distinct namespaces keep their columns disjoint.
|
|
437
442
|
const columnRefs: { namespaceId: string; table: string; column: string }[] = [];
|
|
438
443
|
for (const [nsId, ns] of Object.entries(ctx.toContract.storage.namespaces)) {
|
|
439
|
-
for (const [tableName, tableNode] of Object.entries(ns.
|
|
444
|
+
for (const [tableName, tableNode] of Object.entries(ns.entries.table)) {
|
|
440
445
|
const table = tableNode as StorageTable;
|
|
441
446
|
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
442
447
|
if (
|
|
@@ -639,9 +644,10 @@ export const nativeEnumPlanCallStrategy: CallMigrationStrategy = (issues, ctx) =
|
|
|
639
644
|
function collectPostgresEnumTypes(storage: SqlStorage): ReadonlyMap<string, PostgresEnumType> {
|
|
640
645
|
const result = new Map<string, PostgresEnumType>();
|
|
641
646
|
for (const [nsId, ns] of Object.entries(storage.namespaces)) {
|
|
642
|
-
if (!(
|
|
643
|
-
const
|
|
644
|
-
|
|
647
|
+
if (!isPostgresSchema(ns)) continue;
|
|
648
|
+
for (const [name, instance] of Object.entries(ns.entries.type).sort(([a], [b]) =>
|
|
649
|
+
a.localeCompare(b),
|
|
650
|
+
)) {
|
|
645
651
|
if (instance instanceof PostgresEnumType) {
|
|
646
652
|
result.set(enumCompoundKey(nsId, name), instance);
|
|
647
653
|
}
|
|
@@ -2,10 +2,13 @@ import type { Contract } from '@prisma-next/contract/types';
|
|
|
2
2
|
import type {
|
|
3
3
|
MigrationOperationPolicy,
|
|
4
4
|
SqlMigrationPlannerPlanOptions,
|
|
5
|
+
SqlPlannerConflict,
|
|
5
6
|
SqlPlannerFailureResult,
|
|
6
7
|
} from '@prisma-next/family-sql/control';
|
|
7
8
|
import {
|
|
8
9
|
extractCodecControlHooks,
|
|
10
|
+
partitionCallsByControlPolicy,
|
|
11
|
+
partitionIssuesByControlPolicy,
|
|
9
12
|
planFieldEventOperations,
|
|
10
13
|
plannerFailure,
|
|
11
14
|
} from '@prisma-next/family-sql/control';
|
|
@@ -18,10 +21,18 @@ import type {
|
|
|
18
21
|
SchemaIssue,
|
|
19
22
|
} from '@prisma-next/framework-components/control';
|
|
20
23
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
24
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
21
25
|
import { parsePostgresDefault } from '../default-normalizer';
|
|
22
26
|
import { normalizeSchemaNativeType } from '../native-type-normalizer';
|
|
27
|
+
import {
|
|
28
|
+
formatPostgresControlPolicySubjectLabel,
|
|
29
|
+
resolvePostgresCallControlPolicySubject,
|
|
30
|
+
resolvePostgresIssueControlPolicySubject,
|
|
31
|
+
resolvePostgresIssueCreationFactoryName,
|
|
32
|
+
} from './control-policy';
|
|
23
33
|
import { createResolveExistingEnumValues } from './enum-planning';
|
|
24
34
|
import { planIssues } from './issue-planner';
|
|
35
|
+
import type { PostgresOpFactoryCall } from './op-factory-call';
|
|
25
36
|
import { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';
|
|
26
37
|
import { postgresPlannerStrategies } from './planner-strategies';
|
|
27
38
|
import { verifyPostgresNamespacePresence } from './verify-postgres-namespaces';
|
|
@@ -52,7 +63,11 @@ export function createPostgresMigrationPlanner(): PostgresMigrationPlanner {
|
|
|
52
63
|
* uniformly.
|
|
53
64
|
*/
|
|
54
65
|
export type PostgresPlanResult =
|
|
55
|
-
| {
|
|
66
|
+
| {
|
|
67
|
+
readonly kind: 'success';
|
|
68
|
+
readonly plan: TypeScriptRenderablePostgresMigration;
|
|
69
|
+
readonly warnings?: readonly SqlPlannerConflict[];
|
|
70
|
+
}
|
|
56
71
|
| SqlPlannerFailureResult;
|
|
57
72
|
|
|
58
73
|
/**
|
|
@@ -131,8 +146,25 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
131
146
|
const codecHooks = extractCodecControlHooks(options.frameworkComponents);
|
|
132
147
|
const storageTypes = options.contract.storage.types ?? {};
|
|
133
148
|
|
|
134
|
-
|
|
149
|
+
// Input-side control-policy partition. `external` / `observed` subjects
|
|
150
|
+
// — and non-creation issues for `tolerated` subjects — are dropped from
|
|
151
|
+
// the planner's input entirely; the planner never observes them, never
|
|
152
|
+
// diffs them, never generates DDL for them. Suppression warnings are
|
|
153
|
+
// built directly from the suppressed partition (one per subject), so the
|
|
154
|
+
// user-visible message survives even when the planner would have failed
|
|
155
|
+
// to model the subject's live shape.
|
|
156
|
+
const issuePartition = partitionIssuesByControlPolicy({
|
|
135
157
|
issues: schemaIssues,
|
|
158
|
+
contract: options.contract,
|
|
159
|
+
resolveControlPolicySubject: (issue) =>
|
|
160
|
+
resolvePostgresIssueControlPolicySubject(issue, options.contract),
|
|
161
|
+
resolveCreationFactoryName: resolvePostgresIssueCreationFactoryName,
|
|
162
|
+
formatSubjectLabel: (factoryName, subject) =>
|
|
163
|
+
formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const result = planIssues({
|
|
167
|
+
issues: issuePartition.plannable,
|
|
136
168
|
toContract: options.contract,
|
|
137
169
|
// `fromContract` is only supplied by `migration plan`. It is `null` for
|
|
138
170
|
// `db update` / `db init`, which means data-safety strategies needing
|
|
@@ -163,10 +195,26 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
163
195
|
newContract: options.contract,
|
|
164
196
|
codecHooks,
|
|
165
197
|
});
|
|
166
|
-
// Codec
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
198
|
+
// Codec hook ops are target-agnostic `OpFactoryCall`; Postgres planning
|
|
199
|
+
// lifts them at this integration boundary (see field-event-planner JSDoc).
|
|
200
|
+
const fieldEventPostgresCalls = blindCast<
|
|
201
|
+
readonly PostgresOpFactoryCall[],
|
|
202
|
+
'Codec hook ops conform to PostgresOpFactoryCall at the app emitter boundary'
|
|
203
|
+
>(fieldEventOps);
|
|
204
|
+
const fieldEventPartition = partitionCallsByControlPolicy({
|
|
205
|
+
calls: fieldEventPostgresCalls,
|
|
206
|
+
contract: options.contract,
|
|
207
|
+
resolveControlPolicySubject: (call) =>
|
|
208
|
+
resolvePostgresCallControlPolicySubject(call, options.contract),
|
|
209
|
+
resolveFactoryName: (call) => call.factoryName,
|
|
210
|
+
formatSubjectLabel: (factoryName, subject) =>
|
|
211
|
+
formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),
|
|
212
|
+
});
|
|
213
|
+
const calls = [...result.value.calls, ...fieldEventPartition.kept];
|
|
214
|
+
const warnings: SqlPlannerConflict[] = [
|
|
215
|
+
...issuePartition.warnings,
|
|
216
|
+
...fieldEventPartition.warnings,
|
|
217
|
+
];
|
|
170
218
|
|
|
171
219
|
return Object.freeze({
|
|
172
220
|
kind: 'success' as const,
|
|
@@ -178,6 +226,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
178
226
|
},
|
|
179
227
|
options.spaceId,
|
|
180
228
|
),
|
|
229
|
+
...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),
|
|
181
230
|
});
|
|
182
231
|
}
|
|
183
232
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
1
|
+
import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
3
|
MigrationOperationPolicy,
|
|
4
4
|
SqlControlFamilyInstance,
|
|
@@ -13,13 +13,12 @@ import type {
|
|
|
13
13
|
} from '@prisma-next/family-sql/control';
|
|
14
14
|
import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
|
|
15
15
|
import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
|
|
16
|
-
import type {
|
|
17
|
-
ControlDriverInstance,
|
|
18
|
-
MigrationRunnerResult,
|
|
19
|
-
} from '@prisma-next/framework-components/control';
|
|
16
|
+
import type { MigrationRunnerResult } from '@prisma-next/framework-components/control';
|
|
20
17
|
import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
|
|
21
18
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
19
|
+
import type { SqlControlDriverInstance, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
22
20
|
import { SqlQueryError } from '@prisma-next/sql-errors';
|
|
21
|
+
import type { LoweredStatement } from '@prisma-next/sql-relational-core/ast';
|
|
23
22
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
24
23
|
import type { Result } from '@prisma-next/utils/result';
|
|
25
24
|
import { notOk, ok, okVoid } from '@prisma-next/utils/result';
|
|
@@ -27,14 +26,6 @@ import { parsePostgresDefault } from '../default-normalizer';
|
|
|
27
26
|
import { normalizeSchemaNativeType } from '../native-type-normalizer';
|
|
28
27
|
import { createResolveExistingEnumValues } from './enum-planning';
|
|
29
28
|
import type { PostgresPlanTargetDetails } from './planner-target-details';
|
|
30
|
-
import {
|
|
31
|
-
buildLedgerInsertStatement,
|
|
32
|
-
buildMergeMarkerStatements,
|
|
33
|
-
ensureLedgerTableStatement,
|
|
34
|
-
ensureMarkerTableStatement,
|
|
35
|
-
ensurePrismaContractSchemaStatement,
|
|
36
|
-
type SqlStatement,
|
|
37
|
-
} from './statement-builders';
|
|
38
29
|
|
|
39
30
|
interface ApplyPlanSuccessValue {
|
|
40
31
|
readonly operationsExecuted: number;
|
|
@@ -107,7 +98,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
107
98
|
if (!policyCheck.ok) return policyCheck;
|
|
108
99
|
|
|
109
100
|
await this.acquireLock(driver, lockKey);
|
|
110
|
-
const ensureResult = await this.ensureControlTables(driver);
|
|
101
|
+
const ensureResult = await this.ensureControlTables(driver, options.destinationContract);
|
|
111
102
|
if (!ensureResult.ok) return ensureResult;
|
|
112
103
|
const existingMarker = await this.family.readMarker({ driver, space });
|
|
113
104
|
|
|
@@ -165,8 +156,9 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
165
156
|
isSelfEdge && applyValue.operationsExecuted === 0 && incomingIsSubsetOfExisting;
|
|
166
157
|
|
|
167
158
|
if (!isSelfEdgeNoOp) {
|
|
168
|
-
await this.upsertMarker(driver, options, existingMarker, space);
|
|
169
|
-
|
|
159
|
+
const markerResult = await this.upsertMarker(driver, options, existingMarker, space);
|
|
160
|
+
if (!markerResult.ok) return markerResult;
|
|
161
|
+
await this.recordLedgerEntries(driver, options, applyValue.executedOperations);
|
|
170
162
|
}
|
|
171
163
|
|
|
172
164
|
return runnerSuccess({
|
|
@@ -176,7 +168,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
176
168
|
}
|
|
177
169
|
|
|
178
170
|
async execute(options: {
|
|
179
|
-
readonly driver:
|
|
171
|
+
readonly driver: SqlControlDriverInstance<string>;
|
|
180
172
|
readonly perSpaceOptions: ReadonlyArray<
|
|
181
173
|
SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>
|
|
182
174
|
>;
|
|
@@ -282,18 +274,22 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
282
274
|
|
|
283
275
|
private async ensureControlTables(
|
|
284
276
|
driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
|
|
277
|
+
contract: Contract<SqlStorage>,
|
|
285
278
|
): Promise<Result<void, SqlMigrationRunnerFailure>> {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
279
|
+
const lowererContext = { contract };
|
|
280
|
+
const bootstrapQueries = this.family.bootstrapControlTableQueries();
|
|
281
|
+
const [schemaQuery, ...tableQueries] = bootstrapQueries;
|
|
282
|
+
if (schemaQuery === undefined) {
|
|
283
|
+
throw new Error('Postgres control-table bootstrap must include CREATE SCHEMA');
|
|
284
|
+
}
|
|
285
|
+
await this.executeStatement(driver, this.family.lowerAst(schemaQuery, lowererContext));
|
|
291
286
|
const legacyDetection = await this.detectLegacyMarkerShape(driver);
|
|
292
287
|
if (!legacyDetection.ok) {
|
|
293
288
|
return legacyDetection;
|
|
294
289
|
}
|
|
295
|
-
|
|
296
|
-
|
|
290
|
+
for (const query of tableQueries) {
|
|
291
|
+
await this.executeStatement(driver, this.family.lowerAst(query, lowererContext));
|
|
292
|
+
}
|
|
297
293
|
return okVoid();
|
|
298
294
|
}
|
|
299
295
|
|
|
@@ -594,43 +590,75 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
594
590
|
options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
|
|
595
591
|
existingMarker: ContractMarkerRecord | null,
|
|
596
592
|
space: string,
|
|
597
|
-
): Promise<void
|
|
598
|
-
const
|
|
599
|
-
const writeStatements = buildMergeMarkerStatements({
|
|
600
|
-
space,
|
|
593
|
+
): Promise<Result<void, SqlMigrationRunnerFailure>> {
|
|
594
|
+
const destination = {
|
|
601
595
|
storageHash: options.plan.destination.storageHash,
|
|
602
596
|
profileHash:
|
|
603
597
|
options.plan.destination.profileHash ??
|
|
604
598
|
options.destinationContract.profileHash ??
|
|
605
599
|
options.plan.destination.storageHash,
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
600
|
+
invariants: options.plan.providedInvariants ?? [],
|
|
601
|
+
};
|
|
602
|
+
if (!existingMarker) {
|
|
603
|
+
await this.family.initMarker({ driver, space, destination });
|
|
604
|
+
return okVoid();
|
|
605
|
+
}
|
|
606
|
+
const updated = await this.family.updateMarker({
|
|
607
|
+
driver,
|
|
608
|
+
space,
|
|
609
|
+
expectedFrom: existingMarker.storageHash,
|
|
610
|
+
destination,
|
|
610
611
|
});
|
|
611
|
-
|
|
612
|
-
|
|
612
|
+
if (!updated) {
|
|
613
|
+
return runnerFailure(
|
|
614
|
+
'MARKER_CAS_FAILURE',
|
|
615
|
+
'Marker was modified by another process during migration execution.',
|
|
616
|
+
{
|
|
617
|
+
meta: {
|
|
618
|
+
space,
|
|
619
|
+
expectedStorageHash: existingMarker.storageHash,
|
|
620
|
+
destinationStorageHash: options.plan.destination.storageHash,
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
return okVoid();
|
|
613
626
|
}
|
|
614
627
|
|
|
615
|
-
private async
|
|
628
|
+
private async recordLedgerEntries(
|
|
616
629
|
driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
|
|
617
630
|
options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
|
|
618
|
-
existingMarker: ContractMarkerRecord | null,
|
|
619
631
|
executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
|
|
620
632
|
): Promise<void> {
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
633
|
+
const plan = options.plan;
|
|
634
|
+
const space = plan.spaceId;
|
|
635
|
+
const edges = options.migrationEdges;
|
|
636
|
+
const totalEdgeOps = edges.reduce((sum, edge) => sum + edge.operationCount, 0);
|
|
637
|
+
if (totalEdgeOps !== plan.operations.length) {
|
|
638
|
+
throw new Error(
|
|
639
|
+
`Ledger write: plan.operations length (${plan.operations.length}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`,
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
// The ledger records the operations as executed — idempotency-skipped ops
|
|
643
|
+
// are substituted with skip records (empty `execute`) by `applyPlan`, so the
|
|
644
|
+
// journal reflects what actually ran rather than the raw plan.
|
|
645
|
+
let offset = 0;
|
|
646
|
+
for (const edge of edges) {
|
|
647
|
+
const edgeOps = executedOperations.slice(offset, offset + edge.operationCount);
|
|
648
|
+
offset += edge.operationCount;
|
|
649
|
+
await this.family.writeLedgerEntry({
|
|
650
|
+
driver,
|
|
651
|
+
space,
|
|
652
|
+
entry: {
|
|
653
|
+
edgeId: `${edge.from}->${edge.to}`,
|
|
654
|
+
from: edge.from,
|
|
655
|
+
to: edge.to,
|
|
656
|
+
migrationName: edge.dirName,
|
|
657
|
+
migrationHash: edge.migrationHash,
|
|
658
|
+
operations: edgeOps,
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
}
|
|
634
662
|
}
|
|
635
663
|
|
|
636
664
|
private async acquireLock(
|
|
@@ -660,7 +688,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
660
688
|
|
|
661
689
|
private async executeStatement(
|
|
662
690
|
driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
|
|
663
|
-
statement:
|
|
691
|
+
statement: LoweredStatement,
|
|
664
692
|
): Promise<void> {
|
|
665
693
|
if (statement.params.length > 0) {
|
|
666
694
|
await driver.query(statement.sql, statement.params);
|
|
@@ -14,12 +14,8 @@ import {
|
|
|
14
14
|
NamespaceBase,
|
|
15
15
|
UNBOUND_NAMESPACE_ID,
|
|
16
16
|
} from '@prisma-next/framework-components/ir';
|
|
17
|
-
import type {
|
|
18
|
-
|
|
19
|
-
SqlStorage,
|
|
20
|
-
SqlStorageTypeEntry,
|
|
21
|
-
StorageTable,
|
|
22
|
-
} from '@prisma-next/sql-contract/types';
|
|
17
|
+
import type { SqlNamespaceTablesInput, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
18
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
23
19
|
import type { JsonObject } from '@prisma-next/utils/json';
|
|
24
20
|
import type { Type } from 'arktype';
|
|
25
21
|
import { postgresAuthoringEntityTypes } from './authoring';
|
|
@@ -57,9 +53,8 @@ function collectEntityRegistryContributions(namespace: AuthoringEntityTypeNamesp
|
|
|
57
53
|
if (isAuthoringEntityTypeDescriptor(value)) {
|
|
58
54
|
if (isAuthoringEntityTypeFactoryOutput(value.output)) {
|
|
59
55
|
const { factory } = value.output;
|
|
60
|
-
entityTypeRegistry.set(
|
|
61
|
-
|
|
62
|
-
(raw) => factory(raw, POSTGRES_AUTHORING_CTX) as SqlStorageTypeEntry,
|
|
56
|
+
entityTypeRegistry.set(value.discriminator, (raw) =>
|
|
57
|
+
factory(raw, POSTGRES_AUTHORING_CTX),
|
|
63
58
|
);
|
|
64
59
|
}
|
|
65
60
|
if (value.validatorSchema !== undefined) {
|
|
@@ -91,22 +86,43 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
|
|
|
91
86
|
if (raw instanceof NamespaceBase) {
|
|
92
87
|
return raw;
|
|
93
88
|
}
|
|
94
|
-
const hydrated =
|
|
95
|
-
|
|
96
|
-
tables
|
|
97
|
-
|
|
98
|
-
};
|
|
99
|
-
|
|
89
|
+
const hydrated = blindCast<
|
|
90
|
+
SqlNamespaceTablesInput,
|
|
91
|
+
'super.hydrateSqlNamespaceEntry returns the tables form when raw is not a NamespaceBase'
|
|
92
|
+
>(super.hydrateSqlNamespaceEntry(nsId, raw));
|
|
93
|
+
const { id, entries } = hydrated;
|
|
94
|
+
|
|
95
|
+
// Extract the postgres-specific `type` slot directly from raw input.
|
|
96
|
+
// The family base handles the `table` slot; the postgres target owns `type`.
|
|
97
|
+
const rawRecord = raw as Record<string, unknown>;
|
|
98
|
+
const rawEntries = rawRecord['entries'];
|
|
99
|
+
let typeSlot: Record<string, PostgresEnumType> | undefined;
|
|
100
|
+
if (rawEntries !== null && typeof rawEntries === 'object' && !Array.isArray(rawEntries)) {
|
|
101
|
+
const rawTypeSlot = (rawEntries as Record<string, unknown>)['type'];
|
|
102
|
+
if (rawTypeSlot !== null && typeof rawTypeSlot === 'object' && !Array.isArray(rawTypeSlot)) {
|
|
103
|
+
const enumFactory = this.entityTypeRegistry.get('postgres-enum');
|
|
104
|
+
typeSlot = Object.fromEntries(
|
|
105
|
+
Object.entries(rawTypeSlot as Record<string, unknown>).map(([name, entry]) => [
|
|
106
|
+
name,
|
|
107
|
+
blindCast<PostgresEnumType, 'postgres-enum factory returns PostgresEnumType'>(
|
|
108
|
+
enumFactory !== undefined ? enumFactory(entry) : entry,
|
|
109
|
+
),
|
|
110
|
+
]),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
100
114
|
|
|
101
|
-
const emptyTables = Object.keys(
|
|
102
|
-
const
|
|
103
|
-
if (id === UNBOUND_NAMESPACE_ID && emptyTables &&
|
|
115
|
+
const emptyTables = Object.keys(entries.table).length === 0;
|
|
116
|
+
const emptyTypes = !typeSlot || Object.keys(typeSlot).length === 0;
|
|
117
|
+
if (id === UNBOUND_NAMESPACE_ID && emptyTables && emptyTypes) {
|
|
104
118
|
return PostgresSchema.unbound;
|
|
105
119
|
}
|
|
106
120
|
return new PostgresSchema({
|
|
107
121
|
id,
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
entries: {
|
|
123
|
+
table: entries.table,
|
|
124
|
+
type: typeSlot ?? {},
|
|
125
|
+
},
|
|
110
126
|
});
|
|
111
127
|
}
|
|
112
128
|
|
|
@@ -117,30 +133,18 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
|
|
|
117
133
|
if (isPostgresSchema(ns)) {
|
|
118
134
|
namespacesJson[nsId] = this.serializePostgresNamespace(ns, ns.id === UNBOUND_NAMESPACE_ID);
|
|
119
135
|
} else {
|
|
120
|
-
// Family-level SqlUnboundNamespace or other family-built SQL
|
|
121
|
-
// namespaces haven't been promoted to a PostgresSchema instance
|
|
122
|
-
// yet (e.g. they came straight from the TS builder before a target
|
|
123
|
-
// `createNamespace` factory ran). Serialise them as postgres-schema /
|
|
124
|
-
// postgres-unbound-schema so the round-trip through
|
|
125
|
-
// deserializeContract hydrates them back into PostgresSchema
|
|
126
|
-
// instances.
|
|
127
136
|
const isUnboundSlot = nsId === UNBOUND_NAMESPACE_ID;
|
|
128
|
-
const nsEnums = (ns as { readonly enum?: Readonly<Record<string, unknown>> }).enum ?? {};
|
|
129
137
|
namespacesJson[nsId] = {
|
|
130
138
|
id: nsId,
|
|
131
139
|
kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',
|
|
132
|
-
|
|
133
|
-
Object.
|
|
134
|
-
tableName,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
typeName,
|
|
141
|
-
this.serializeJsonValue(entry) as JsonObject,
|
|
142
|
-
]),
|
|
143
|
-
),
|
|
140
|
+
entries: {
|
|
141
|
+
table: Object.fromEntries(
|
|
142
|
+
Object.entries(ns.entries.table).map(([tableName, table]) => [
|
|
143
|
+
tableName,
|
|
144
|
+
this.serializeJsonValue(table) as JsonObject,
|
|
145
|
+
]),
|
|
146
|
+
),
|
|
147
|
+
},
|
|
144
148
|
};
|
|
145
149
|
}
|
|
146
150
|
}
|
|
@@ -163,18 +167,20 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
|
|
|
163
167
|
|
|
164
168
|
private serializePostgresNamespace(ns: PostgresSchema, isUnboundSlot: boolean): JsonObject {
|
|
165
169
|
const tablesOut: Record<string, JsonObject> = {};
|
|
166
|
-
for (const [tableName, table] of Object.entries(ns.
|
|
170
|
+
for (const [tableName, table] of Object.entries(ns.entries.table)) {
|
|
167
171
|
tablesOut[tableName] = this.serializeJsonValue(table) as JsonObject;
|
|
168
172
|
}
|
|
169
|
-
const
|
|
170
|
-
for (const [typeName, ty] of Object.entries(ns.
|
|
171
|
-
|
|
173
|
+
const typeOut: Record<string, JsonObject> = {};
|
|
174
|
+
for (const [typeName, ty] of Object.entries(ns.entries.type)) {
|
|
175
|
+
typeOut[typeName] = this.serializeJsonValue(ty) as JsonObject;
|
|
172
176
|
}
|
|
173
177
|
return {
|
|
174
178
|
id: ns.id,
|
|
175
179
|
kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
entries: {
|
|
181
|
+
table: tablesOut,
|
|
182
|
+
type: typeOut,
|
|
183
|
+
},
|
|
178
184
|
};
|
|
179
185
|
}
|
|
180
186
|
|