@prisma-next/target-postgres 0.14.0-dev.39 → 0.14.0-dev.40
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/{authoring-CZmSQriw.mjs → authoring-BX1WHIdN.mjs} +2 -2
- package/dist/authoring-BX1WHIdN.mjs.map +1 -0
- package/dist/contract-free.mjs +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +633 -16
- package/dist/control.mjs.map +1 -1
- package/dist/{ddl-CGf6UABz.mjs → ddl-BmLIe1z_.mjs} +2 -2
- package/dist/{ddl-CGf6UABz.mjs.map → ddl-BmLIe1z_.mjs.map} +1 -1
- package/dist/{descriptor-meta-Du6olWQI.mjs → descriptor-meta-tjatyhtZ.mjs} +3 -3
- package/dist/{descriptor-meta-Du6olWQI.mjs.map → descriptor-meta-tjatyhtZ.mjs.map} +1 -1
- package/dist/{issue-planner-C-CwZd8D.mjs → issue-planner-DbFvaAgu.mjs} +5 -5
- package/dist/issue-planner-DbFvaAgu.mjs.map +1 -0
- package/dist/issue-planner.d.mts +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +2 -2
- package/dist/migration.mjs +2 -2
- package/dist/{op-factory-call-DPJR7tJc.d.mts → op-factory-call-CJWUxyUW.d.mts} +2 -2
- package/dist/{op-factory-call-DPJR7tJc.d.mts.map → op-factory-call-CJWUxyUW.d.mts.map} +1 -1
- package/dist/{op-factory-call-DArx_1HM.mjs → op-factory-call-t65c4jyY.mjs} +3 -3
- package/dist/op-factory-call-t65c4jyY.mjs.map +1 -0
- package/dist/op-factory-call.d.mts +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/pack.d.mts +2 -2
- package/dist/pack.mjs +1 -1
- package/dist/{planner-BQ7lSqbm.mjs → planner-CG2pLHk-.mjs} +310 -126
- package/dist/planner-CG2pLHk-.mjs.map +1 -0
- package/dist/{planner-produced-postgres-migration-3ppG0t3i.mjs → planner-produced-postgres-migration-BolD0Mvc.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-3ppG0t3i.mjs.map → planner-produced-postgres-migration-BolD0Mvc.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-BauTSigX.d.mts → planner-produced-postgres-migration-Cz9--XOT.d.mts} +2 -2
- package/dist/{planner-produced-postgres-migration-BauTSigX.d.mts.map → planner-produced-postgres-migration-Cz9--XOT.d.mts.map} +1 -1
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-sql-checks-CyjaoKhm.mjs → planner-sql-checks-DE9c4519.mjs} +2 -2
- package/dist/{planner-sql-checks-CyjaoKhm.mjs.map → planner-sql-checks-DE9c4519.mjs.map} +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/planner.d.mts +73 -22
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +2 -2
- package/dist/{postgres-contract-view-CoRZewAp.mjs → postgres-contract-view-BegduLr6.mjs} +3 -3
- package/dist/{postgres-contract-view-CoRZewAp.mjs.map → postgres-contract-view-BegduLr6.mjs.map} +1 -1
- package/dist/postgres-database-schema-node-os8ogEap.d.mts +183 -0
- package/dist/postgres-database-schema-node-os8ogEap.d.mts.map +1 -0
- package/dist/{postgres-migration-BVjq0iFW.mjs → postgres-migration-BfMmK6tv.mjs} +3 -3
- package/dist/{postgres-migration-BVjq0iFW.mjs.map → postgres-migration-BfMmK6tv.mjs.map} +1 -1
- package/dist/{postgres-migration-UtGCjw5j.d.mts → postgres-migration-D7kNVWVG.d.mts} +2 -2
- package/dist/{postgres-migration-UtGCjw5j.d.mts.map → postgres-migration-D7kNVWVG.d.mts.map} +1 -1
- package/dist/{postgres-rls-policy-12wAEQhs.d.mts → postgres-rls-policy--CSddvMR.d.mts} +8 -16
- package/dist/postgres-rls-policy--CSddvMR.d.mts.map +1 -0
- package/dist/{postgres-schema-DLcc3W2-.mjs → postgres-schema-BLIHBEfX.mjs} +34 -64
- package/dist/postgres-schema-BLIHBEfX.mjs.map +1 -0
- package/dist/{postgres-schema-DJUEkWg-.d.mts → postgres-schema-BywoeKlt.d.mts} +9 -10
- package/dist/postgres-schema-BywoeKlt.d.mts.map +1 -0
- package/dist/postgres-table-schema-node-1nNc8XDT.mjs +248 -0
- package/dist/postgres-table-schema-node-1nNc8XDT.mjs.map +1 -0
- package/dist/resolve-ddl-schema-CL1RR1mx.mjs +20 -0
- package/dist/resolve-ddl-schema-CL1RR1mx.mjs.map +1 -0
- package/dist/runtime.mjs +1 -1
- package/dist/schema-ir-annotations.d.mts +9 -3
- package/dist/schema-ir-annotations.d.mts.map +1 -1
- package/dist/schema-ir-annotations.mjs +1 -1
- package/dist/types.d.mts +4 -4
- package/dist/types.mjs +3 -3
- package/package.json +20 -19
- package/src/core/authoring.ts +2 -2
- package/src/core/entity-kinds.ts +2 -2
- package/src/core/migrations/contract-to-postgres-database-schema-node.ts +125 -0
- package/src/core/migrations/diff-database-schema.ts +191 -0
- package/src/core/migrations/issue-planner.ts +1 -1
- package/src/core/migrations/op-factory-call.ts +1 -1
- package/src/core/migrations/operations/rls.ts +1 -1
- package/src/core/migrations/planner.ts +117 -68
- package/src/core/{schema-ir/postgres-schema-ir-annotations.ts → migrations/resolve-ddl-schema.ts} +8 -6
- package/src/core/migrations/runner.ts +13 -16
- package/src/core/migrations/verify-postgres-namespaces.ts +22 -14
- package/src/core/{schema-ir/postgres-rls-policy.ts → postgres-rls-policy.ts} +6 -43
- package/src/core/{schema-ir/postgres-role.ts → postgres-role.ts} +6 -21
- package/src/core/postgres-schema.ts +2 -2
- package/src/core/psl-infer/infer-psl-contract.ts +834 -0
- package/src/core/psl-infer/postgres-default-mapping.ts +16 -0
- package/src/core/psl-infer/postgres-type-map.ts +157 -0
- package/src/core/schema-ir/postgres-database-schema-node.ts +63 -0
- package/src/core/schema-ir/postgres-namespace-schema-node.ts +61 -0
- package/src/core/schema-ir/postgres-policy-schema-node.ts +93 -0
- package/src/core/schema-ir/postgres-role-schema-node.ts +66 -0
- package/src/core/schema-ir/{postgres-table-ir.ts → postgres-table-schema-node.ts} +29 -18
- package/src/core/schema-ir/schema-node-kinds.ts +28 -0
- package/src/exports/control.ts +30 -2
- package/src/exports/planner.ts +2 -5
- package/src/exports/schema-ir-annotations.ts +1 -1
- package/src/exports/types.ts +23 -15
- package/dist/authoring-CZmSQriw.mjs.map +0 -1
- package/dist/issue-planner-C-CwZd8D.mjs.map +0 -1
- package/dist/op-factory-call-DArx_1HM.mjs.map +0 -1
- package/dist/planner-BQ7lSqbm.mjs.map +0 -1
- package/dist/postgres-rls-policy-12wAEQhs.d.mts.map +0 -1
- package/dist/postgres-schema-DJUEkWg-.d.mts.map +0 -1
- package/dist/postgres-schema-DLcc3W2-.mjs.map +0 -1
- package/dist/postgres-schema-ir-BJl_a3J7.d.mts +0 -102
- package/dist/postgres-schema-ir-BJl_a3J7.d.mts.map +0 -1
- package/dist/postgres-schema-ir-I_FiUndw.mjs +0 -133
- package/dist/postgres-schema-ir-I_FiUndw.mjs.map +0 -1
- package/dist/postgres-schema-ir-annotations-BbDSiwx2.mjs +0 -14
- package/dist/postgres-schema-ir-annotations-BbDSiwx2.mjs.map +0 -1
- package/src/core/migrations/contract-to-postgres-schema-ir.ts +0 -91
- package/src/core/migrations/diff-postgres-schema.ts +0 -55
- package/src/core/schema-ir/postgres-schema-ir.ts +0 -138
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-BJl_a3J7.d.mts","names":[],"sources":["../src/core/schema-ir/postgres-table-ir.ts","../src/core/schema-ir/postgres-schema-ir.ts"],"mappings":";;;;;;UAeiB,oBAAA,SAA6B,eAAe;EAAA,SAClD,WAAA,YAAuB,iBAAA;AAAA;AADlC;;;;;;;;AACmD;AAenD;;;AAhBA,cAgBa,eAAA,SAAwB,eAAA,YAA2B,YAAA;EAAA,SACrD,IAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA,SAAe,WAAA;EAAA,SACjC,WAAA,EAAa,aAAA,CAAc,eAAA;EAAA,SAC3B,OAAA,EAAS,aAAA,CAAc,WAAA;EAAA,SACvB,OAAA,EAAS,aAAA,CAAc,UAAA;EAAA,SACf,UAAA,GAAa,UAAA;EAAA,SACb,WAAA,GAAc,cAAA;EAAA,SACd,MAAA,GAAS,aAAA,CAAc,oBAAA;EAAA,SAC/B,WAAA,WAAsB,iBAAA;cAEnB,KAAA,EAAO,oBAAA;EAAA,IAsCf,EAAA;EAIJ,SAAA,CAAU,MAAA,EAAQ,YAAA;EAIlB,QAAA,aAAqB,YAAA;AAAA;AAAA,iBAKP,iBAAA,CAAkB,IAAA,EAAM,YAAA,GAAe,IAAA,IAAQ,eAAe;;;UC/E7D,qBAAA;EAAA,SACN,MAAA,EAAQ,MAAA,SAEf,eAAA,IAAmB,eAAA;IAAoB,WAAA,YAAuB,iBAAA;EAAA;EAAA,SAEvD,YAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,WAAgB,YAAA;EAAA,SAChB,eAAA;EAAA,SACA,mBAAA;AAAA;ADQX;;;;;;;;;;;;;;;;;AAAA,cCYa,gBAAA,SAAyB,eAAA,YAA2B,YAAA;EAAA,SACtD,UAAA,EAAY,eAAA;EAAA,SACZ,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,eAAA;EAAA,SACxB,WAAA,GAAc,cAAA;EAAA,SACtB,YAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,WAAgB,YAAA;EAAA,SAChB,eAAA;EAAA,SACA,mBAAA;cAEG,KAAA,EAAO,qBAAA;EAAA,IAgCf,EAAA;EAAA,IAIA,WAAA,aAAwB,iBAAA;EAI5B,SAAA,CAAU,MAAA,EAAQ,YAAA;EAIlB,QAAA,aAAqB,YAAA;AAAA;;;;;;;;;;;iBAeP,kBAAA,CAAmB,MAAA,EAAQ,WAAA,GAAc,MAAA,IAAU,gBAAgB;AAAA,iBAInE,sBAAA,CAAuB,MAAA,EAAQ,WAAA,WAAsB,MAAA,IAAU,gBAAgB;;;;;;iBAa/E,sBAAA,CAAuB,MAAA,EAAQ,gBAAA,GAAmB,gBAAgB"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { blindCast } from "@prisma-next/utils/casts";
|
|
2
|
-
import { freezeNode } from "@prisma-next/framework-components/ir";
|
|
3
|
-
import { PrimaryKey, SqlCheckConstraintIR, SqlColumnIR, SqlForeignKeyIR, SqlIndexIR, SqlSchemaIRNode, SqlUniqueIR } from "@prisma-next/sql-schema-ir/types";
|
|
4
|
-
//#region src/core/schema-ir/postgres-table-ir.ts
|
|
5
|
-
/**
|
|
6
|
-
* Postgres-specific table IR node. Carries all `SqlTableIR` fields plus
|
|
7
|
-
* `rlsPolicies`, and implements `DiffableNode` so the table instance is
|
|
8
|
-
* directly the diff-tree node — no separate wrapper needed.
|
|
9
|
-
*
|
|
10
|
-
* Extends `SqlSchemaIRNode` directly rather than `SqlTableIR` because
|
|
11
|
-
* `SqlTableIR` calls `freezeNode` in its own constructor, which prevents
|
|
12
|
-
* subclass field initialisation. Same pattern as `PostgresSchemaIR`.
|
|
13
|
-
*
|
|
14
|
-
* `id` is the table name. `children()` returns the policies on this table.
|
|
15
|
-
* `isEqualTo` is always true — table-level attributes are not diffed yet.
|
|
16
|
-
*/
|
|
17
|
-
var PostgresTableIR = class extends SqlSchemaIRNode {
|
|
18
|
-
name;
|
|
19
|
-
columns;
|
|
20
|
-
foreignKeys;
|
|
21
|
-
uniques;
|
|
22
|
-
indexes;
|
|
23
|
-
rlsPolicies;
|
|
24
|
-
constructor(input) {
|
|
25
|
-
super();
|
|
26
|
-
this.name = input.name;
|
|
27
|
-
this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([key, col]) => [key, col instanceof SqlColumnIR ? col : new SqlColumnIR(col)])));
|
|
28
|
-
this.foreignKeys = Object.freeze(input.foreignKeys.map((fk) => fk instanceof SqlForeignKeyIR ? fk : new SqlForeignKeyIR(fk)));
|
|
29
|
-
this.uniques = Object.freeze(input.uniques.map((u) => u instanceof SqlUniqueIR ? u : new SqlUniqueIR(u)));
|
|
30
|
-
this.indexes = Object.freeze(input.indexes.map((i) => i instanceof SqlIndexIR ? i : new SqlIndexIR(i)));
|
|
31
|
-
if (input.primaryKey !== void 0) this.primaryKey = input.primaryKey instanceof PrimaryKey ? input.primaryKey : new PrimaryKey(input.primaryKey);
|
|
32
|
-
if (input.annotations !== void 0) this.annotations = input.annotations;
|
|
33
|
-
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map((c) => c instanceof SqlCheckConstraintIR ? c : new SqlCheckConstraintIR(c)));
|
|
34
|
-
this.rlsPolicies = Object.freeze([...input.rlsPolicies ?? []]);
|
|
35
|
-
freezeNode(this);
|
|
36
|
-
}
|
|
37
|
-
get id() {
|
|
38
|
-
return this.name;
|
|
39
|
-
}
|
|
40
|
-
isEqualTo(_other) {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
children() {
|
|
44
|
-
return this.rlsPolicies;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
function isPostgresTableIR(node) {
|
|
48
|
-
return node instanceof PostgresTableIR;
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/core/schema-ir/postgres-schema-ir.ts
|
|
52
|
-
/**
|
|
53
|
-
* Postgres-specific schema IR. Mirrors the structure of `SqlSchemaIR`
|
|
54
|
-
* (same `tables` + optional `annotations` fields) and adds typed fields for
|
|
55
|
-
* data the postgres adapter collects during introspection.
|
|
56
|
-
*
|
|
57
|
-
* Extends `SqlSchemaIRNode` directly rather than `SqlSchemaIR` because
|
|
58
|
-
* `SqlSchemaIR` calls `freezeNode` in its constructor, which prevents
|
|
59
|
-
* subclass field initialisation. `PostgresSchemaIR` replicates the minimal
|
|
60
|
-
* `SqlSchemaIR` structure and freezes itself at the end of its own
|
|
61
|
-
* constructor.
|
|
62
|
-
*
|
|
63
|
-
* `tables` holds `PostgresTableIR` instances which carry their own RLS
|
|
64
|
-
* policies. `children()` returns the tables directly — the table instances
|
|
65
|
-
* ARE the diff-tree nodes.
|
|
66
|
-
*
|
|
67
|
-
* Nothing RLS-specific leaks into the sql-family layer.
|
|
68
|
-
*/
|
|
69
|
-
var PostgresSchemaIR = class extends SqlSchemaIRNode {
|
|
70
|
-
nodeTarget = "postgres";
|
|
71
|
-
tables;
|
|
72
|
-
pgSchemaName;
|
|
73
|
-
pgVersion;
|
|
74
|
-
roles;
|
|
75
|
-
existingSchemas;
|
|
76
|
-
nativeEnumTypeNames;
|
|
77
|
-
constructor(input) {
|
|
78
|
-
super();
|
|
79
|
-
this.tables = Object.freeze(Object.fromEntries(Object.entries(input.tables).map(([key, t]) => [key, t instanceof PostgresTableIR ? t : new PostgresTableIR(t)])));
|
|
80
|
-
this.pgSchemaName = input.pgSchemaName;
|
|
81
|
-
this.pgVersion = input.pgVersion;
|
|
82
|
-
this.roles = Object.freeze([...input.roles]);
|
|
83
|
-
this.existingSchemas = Object.freeze([...input.existingSchemas]);
|
|
84
|
-
this.nativeEnumTypeNames = Object.freeze([...input.nativeEnumTypeNames]);
|
|
85
|
-
this.annotations = { pg: {
|
|
86
|
-
schema: input.pgSchemaName,
|
|
87
|
-
...input.nativeEnumTypeNames.length > 0 && { nativeEnumTypeNames: input.nativeEnumTypeNames },
|
|
88
|
-
...input.existingSchemas.length > 0 && { existingSchemas: input.existingSchemas }
|
|
89
|
-
} };
|
|
90
|
-
freezeNode(this);
|
|
91
|
-
}
|
|
92
|
-
get id() {
|
|
93
|
-
return this.pgSchemaName;
|
|
94
|
-
}
|
|
95
|
-
get rlsPolicies() {
|
|
96
|
-
return Object.values(this.tables).flatMap((t) => t.rlsPolicies);
|
|
97
|
-
}
|
|
98
|
-
isEqualTo(_other) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
children() {
|
|
102
|
-
return Object.values(this.tables);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* Structural guard for `PostgresSchemaIR`, narrowing on the `nodeTarget`
|
|
107
|
-
* discriminant rather than `instanceof`. `nodeTarget` is an enumerable own field
|
|
108
|
-
* (a plain class-field initializer), so it survives the `{ ...schema, tables }`
|
|
109
|
-
* spread the multi-space verify path (`projectSchemaToSpace`) produces — that
|
|
110
|
-
* projected object is not a class instance but retains every enumerable own
|
|
111
|
-
* property. The family-level `kind = 'sql-schema-ir'` discriminator is unusable
|
|
112
|
-
* here: it is shared by every SQL schema-IR node and is non-enumerable (dropped
|
|
113
|
-
* by the spread).
|
|
114
|
-
*/
|
|
115
|
-
function isPostgresSchemaIR(schema) {
|
|
116
|
-
return schema.nodeTarget === "postgres";
|
|
117
|
-
}
|
|
118
|
-
function assertPostgresSchemaIR(schema) {
|
|
119
|
-
if (!isPostgresSchemaIR(schema)) throw new Error(`planPostgresSchemaDiff: expected a PostgresSchemaIR but got nodeTarget=${String(schema.nodeTarget ?? typeof schema)}`);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Returns `schema` as-is when it is a real `PostgresSchemaIR` instance, or
|
|
123
|
-
* reconstructs one when `projectSchemaToSpace` has spread the class into a
|
|
124
|
-
* plain object (losing prototype methods).
|
|
125
|
-
*/
|
|
126
|
-
function ensurePostgresSchemaIR(schema) {
|
|
127
|
-
if (schema instanceof PostgresSchemaIR) return schema;
|
|
128
|
-
return new PostgresSchemaIR(blindCast(schema));
|
|
129
|
-
}
|
|
130
|
-
//#endregion
|
|
131
|
-
export { PostgresTableIR as a, isPostgresSchemaIR as i, assertPostgresSchemaIR as n, isPostgresTableIR as o, ensurePostgresSchemaIR as r, PostgresSchemaIR as t };
|
|
132
|
-
|
|
133
|
-
//# sourceMappingURL=postgres-schema-ir-I_FiUndw.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-I_FiUndw.mjs","names":[],"sources":["../src/core/schema-ir/postgres-table-ir.ts","../src/core/schema-ir/postgres-schema-ir.ts"],"sourcesContent":["import type { DiffableNode } from '@prisma-next/framework-components/control';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport {\n PrimaryKey,\n type SqlAnnotations,\n SqlCheckConstraintIR,\n SqlColumnIR,\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlSchemaIRNode,\n type SqlTableIRInput,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport type { PostgresRlsPolicy } from './postgres-rls-policy';\n\nexport interface PostgresTableIRInput extends SqlTableIRInput {\n readonly rlsPolicies?: readonly PostgresRlsPolicy[];\n}\n\n/**\n * Postgres-specific table IR node. Carries all `SqlTableIR` fields plus\n * `rlsPolicies`, and implements `DiffableNode` so the table instance is\n * directly the diff-tree node — no separate wrapper needed.\n *\n * Extends `SqlSchemaIRNode` directly rather than `SqlTableIR` because\n * `SqlTableIR` calls `freezeNode` in its own constructor, which prevents\n * subclass field initialisation. Same pattern as `PostgresSchemaIR`.\n *\n * `id` is the table name. `children()` returns the policies on this table.\n * `isEqualTo` is always true — table-level attributes are not diffed yet.\n */\nexport class PostgresTableIR extends SqlSchemaIRNode implements DiffableNode {\n readonly name: string;\n readonly columns: Readonly<Record<string, SqlColumnIR>>;\n readonly foreignKeys: ReadonlyArray<SqlForeignKeyIR>;\n readonly uniques: ReadonlyArray<SqlUniqueIR>;\n readonly indexes: ReadonlyArray<SqlIndexIR>;\n declare readonly primaryKey?: PrimaryKey;\n declare readonly annotations?: SqlAnnotations;\n declare readonly checks?: ReadonlyArray<SqlCheckConstraintIR>;\n readonly rlsPolicies: readonly PostgresRlsPolicy[];\n\n constructor(input: PostgresTableIRInput) {\n super();\n this.name = input.name;\n this.columns = Object.freeze(\n Object.fromEntries(\n Object.entries(input.columns).map(([key, col]) => [\n key,\n col instanceof SqlColumnIR ? col : new SqlColumnIR(col),\n ]),\n ),\n );\n this.foreignKeys = Object.freeze(\n input.foreignKeys.map((fk) => (fk instanceof SqlForeignKeyIR ? fk : new SqlForeignKeyIR(fk))),\n );\n this.uniques = Object.freeze(\n input.uniques.map((u) => (u instanceof SqlUniqueIR ? u : new SqlUniqueIR(u))),\n );\n this.indexes = Object.freeze(\n input.indexes.map((i) => (i instanceof SqlIndexIR ? i : new SqlIndexIR(i))),\n );\n if (input.primaryKey !== undefined) {\n this.primaryKey =\n input.primaryKey instanceof PrimaryKey\n ? input.primaryKey\n : new PrimaryKey(input.primaryKey);\n }\n if (input.annotations !== undefined) this.annotations = input.annotations;\n if (input.checks !== undefined && input.checks.length > 0) {\n this.checks = Object.freeze(\n input.checks.map((c) =>\n c instanceof SqlCheckConstraintIR ? c : new SqlCheckConstraintIR(c),\n ),\n );\n }\n this.rlsPolicies = Object.freeze([...(input.rlsPolicies ?? [])]);\n freezeNode(this);\n }\n\n get id(): string {\n return this.name;\n }\n\n isEqualTo(_other: DiffableNode): boolean {\n return true;\n }\n\n children(): readonly DiffableNode[] {\n return this.rlsPolicies;\n }\n}\n\nexport function isPostgresTableIR(node: DiffableNode): node is PostgresTableIR {\n return node instanceof PostgresTableIR;\n}\n","import type { DiffableNode } from '@prisma-next/framework-components/control';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport {\n type SqlAnnotations,\n type SqlSchemaIR,\n SqlSchemaIRNode,\n type SqlSchemaTarget,\n type SqlTableIRInput,\n} from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { PostgresRlsPolicy } from './postgres-rls-policy';\nimport type { PostgresRole } from './postgres-role';\nimport { PostgresTableIR } from './postgres-table-ir';\n\nexport interface PostgresSchemaIRInput {\n readonly tables: Record<\n string,\n PostgresTableIR | (SqlTableIRInput & { rlsPolicies?: readonly PostgresRlsPolicy[] })\n >;\n readonly pgSchemaName: string;\n readonly pgVersion: string;\n readonly roles: readonly PostgresRole[];\n readonly existingSchemas: readonly string[];\n readonly nativeEnumTypeNames: readonly string[];\n}\n\n/**\n * Postgres-specific schema IR. Mirrors the structure of `SqlSchemaIR`\n * (same `tables` + optional `annotations` fields) and adds typed fields for\n * data the postgres adapter collects during introspection.\n *\n * Extends `SqlSchemaIRNode` directly rather than `SqlSchemaIR` because\n * `SqlSchemaIR` calls `freezeNode` in its constructor, which prevents\n * subclass field initialisation. `PostgresSchemaIR` replicates the minimal\n * `SqlSchemaIR` structure and freezes itself at the end of its own\n * constructor.\n *\n * `tables` holds `PostgresTableIR` instances which carry their own RLS\n * policies. `children()` returns the tables directly — the table instances\n * ARE the diff-tree nodes.\n *\n * Nothing RLS-specific leaks into the sql-family layer.\n */\nexport class PostgresSchemaIR extends SqlSchemaIRNode implements DiffableNode {\n readonly nodeTarget: SqlSchemaTarget = 'postgres';\n readonly tables: Readonly<Record<string, PostgresTableIR>>;\n declare readonly annotations?: SqlAnnotations;\n readonly pgSchemaName: string;\n readonly pgVersion: string;\n readonly roles: readonly PostgresRole[];\n readonly existingSchemas: readonly string[];\n readonly nativeEnumTypeNames: readonly string[];\n\n constructor(input: PostgresSchemaIRInput) {\n super();\n this.tables = Object.freeze(\n Object.fromEntries(\n Object.entries(input.tables).map(([key, t]) => [\n key,\n t instanceof PostgresTableIR ? t : new PostgresTableIR(t),\n ]),\n ),\n );\n this.pgSchemaName = input.pgSchemaName;\n this.pgVersion = input.pgVersion;\n this.roles = Object.freeze([...input.roles]);\n this.existingSchemas = Object.freeze([...input.existingSchemas]);\n this.nativeEnumTypeNames = Object.freeze([...input.nativeEnumTypeNames]);\n // Populate the annotations.pg bag with only the subset the family layer\n // reads (nativeEnumTypeNames for PSL inference, existingSchemas for\n // namespace presence checks).\n this.annotations = {\n pg: {\n schema: input.pgSchemaName,\n ...(input.nativeEnumTypeNames.length > 0 && {\n nativeEnumTypeNames: input.nativeEnumTypeNames,\n }),\n ...(input.existingSchemas.length > 0 && {\n existingSchemas: input.existingSchemas,\n }),\n },\n };\n freezeNode(this);\n }\n\n get id(): string {\n return this.pgSchemaName;\n }\n\n get rlsPolicies(): readonly PostgresRlsPolicy[] {\n return Object.values(this.tables).flatMap((t) => t.rlsPolicies);\n }\n\n isEqualTo(_other: DiffableNode): boolean {\n return true;\n }\n\n children(): readonly DiffableNode[] {\n return Object.values(this.tables);\n }\n}\n\n/**\n * Structural guard for `PostgresSchemaIR`, narrowing on the `nodeTarget`\n * discriminant rather than `instanceof`. `nodeTarget` is an enumerable own field\n * (a plain class-field initializer), so it survives the `{ ...schema, tables }`\n * spread the multi-space verify path (`projectSchemaToSpace`) produces — that\n * projected object is not a class instance but retains every enumerable own\n * property. The family-level `kind = 'sql-schema-ir'` discriminator is unusable\n * here: it is shared by every SQL schema-IR node and is non-enumerable (dropped\n * by the spread).\n */\nexport function isPostgresSchemaIR(schema: SqlSchemaIR): schema is PostgresSchemaIR {\n return schema.nodeTarget === 'postgres';\n}\n\nexport function assertPostgresSchemaIR(schema: SqlSchemaIR): asserts schema is PostgresSchemaIR {\n if (!isPostgresSchemaIR(schema)) {\n throw new Error(\n `planPostgresSchemaDiff: expected a PostgresSchemaIR but got nodeTarget=${String(schema.nodeTarget ?? typeof schema)}`,\n );\n }\n}\n\n/**\n * Returns `schema` as-is when it is a real `PostgresSchemaIR` instance, or\n * reconstructs one when `projectSchemaToSpace` has spread the class into a\n * plain object (losing prototype methods).\n */\nexport function ensurePostgresSchemaIR(schema: PostgresSchemaIR): PostgresSchemaIR {\n if (schema instanceof PostgresSchemaIR) return schema;\n return new PostgresSchemaIR(\n blindCast<\n PostgresSchemaIRInput,\n 'spread objects from projectSchemaToSpace preserve all own-enumerable fields'\n >(schema),\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { r as isPostgresSchema } from "./postgres-schema-DLcc3W2-.mjs";
|
|
2
|
-
import { i as isPostgresSchemaIR } from "./postgres-schema-ir-I_FiUndw.mjs";
|
|
3
|
-
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
4
|
-
//#region src/core/schema-ir/postgres-schema-ir-annotations.ts
|
|
5
|
-
function resolveDdlSchemaForNamespaceStorage(storage, namespaceId, schemaIr) {
|
|
6
|
-
if (namespaceId === UNBOUND_NAMESPACE_ID) return (schemaIr && isPostgresSchemaIR(schemaIr) ? schemaIr.pgSchemaName : void 0) ?? "public";
|
|
7
|
-
const namespace = storage.namespaces[namespaceId];
|
|
8
|
-
if (namespace && isPostgresSchema(namespace)) return namespace.ddlSchemaName(storage);
|
|
9
|
-
return namespaceId;
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { resolveDdlSchemaForNamespaceStorage as t };
|
|
13
|
-
|
|
14
|
-
//# sourceMappingURL=postgres-schema-ir-annotations-BbDSiwx2.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-annotations-BbDSiwx2.mjs","names":[],"sources":["../src/core/schema-ir/postgres-schema-ir-annotations.ts"],"sourcesContent":["import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { isPostgresSchema } from '../postgres-schema';\nimport { isPostgresSchemaIR } from './postgres-schema-ir';\n\nexport function resolveDdlSchemaForNamespaceStorage(\n storage: SqlStorage,\n namespaceId: string,\n schemaIr?: SqlSchemaIR,\n): string {\n if (namespaceId === UNBOUND_NAMESPACE_ID) {\n return (\n (schemaIr && isPostgresSchemaIR(schemaIr) ? schemaIr.pgSchemaName : undefined) ?? 'public'\n );\n }\n const namespace = storage.namespaces[namespaceId];\n if (namespace && isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n"],"mappings":";;;;AAMA,SAAgB,oCACd,SACA,aACA,UACQ;CACR,IAAI,gBAAgB,sBAClB,QACG,YAAY,mBAAmB,QAAQ,IAAI,SAAS,eAAe,KAAA,MAAc;CAGtF,MAAM,YAAY,QAAQ,WAAW;CACrC,IAAI,aAAa,iBAAiB,SAAS,GACzC,OAAO,UAAU,cAAc,OAAO;CAExC,OAAO;AACT"}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { ContractToSchemaIROptions } from '@prisma-next/family-sql/control';
|
|
2
|
-
import { contractToSchemaIR } from '@prisma-next/family-sql/control';
|
|
3
|
-
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
|
-
import type { PostgresContract } from '../postgres-schema';
|
|
5
|
-
import { isPostgresSchema } from '../postgres-schema';
|
|
6
|
-
import { PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';
|
|
7
|
-
import { PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';
|
|
8
|
-
import { resolveDdlSchemaForNamespaceStorage } from '../schema-ir/postgres-schema-ir-annotations';
|
|
9
|
-
import { PostgresTableIR } from '../schema-ir/postgres-table-ir';
|
|
10
|
-
|
|
11
|
-
export function contractToPostgresSchemaIR(
|
|
12
|
-
contract: PostgresContract | null,
|
|
13
|
-
options: ContractToSchemaIROptions,
|
|
14
|
-
): PostgresSchemaIR {
|
|
15
|
-
const sqlIr = contractToSchemaIR(contract, options);
|
|
16
|
-
const ownedSchemas =
|
|
17
|
-
contract === null
|
|
18
|
-
? []
|
|
19
|
-
: Object.values(contract.storage.namespaces)
|
|
20
|
-
.filter((ns) => isPostgresSchema(ns))
|
|
21
|
-
.map((ns) => resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id));
|
|
22
|
-
|
|
23
|
-
// Build a map of tableName → PostgresRlsPolicy[], resolving the DDL schema
|
|
24
|
-
// name once per namespace (not per policy).
|
|
25
|
-
const policiesByTable = new Map<string, PostgresRlsPolicy[]>();
|
|
26
|
-
if (contract !== null) {
|
|
27
|
-
for (const ns of Object.values(contract.storage.namespaces)) {
|
|
28
|
-
if (!isPostgresSchema(ns)) continue;
|
|
29
|
-
const resolvedSchema = resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id);
|
|
30
|
-
for (const policy of Object.values(ns.policy)) {
|
|
31
|
-
const resolved =
|
|
32
|
-
resolvedSchema === policy.namespaceId
|
|
33
|
-
? policy
|
|
34
|
-
: new PostgresRlsPolicy({
|
|
35
|
-
name: policy.name,
|
|
36
|
-
prefix: policy.prefix,
|
|
37
|
-
tableName: policy.tableName,
|
|
38
|
-
namespaceId: resolvedSchema,
|
|
39
|
-
operation: policy.operation,
|
|
40
|
-
roles: [...policy.roles],
|
|
41
|
-
...ifDefined('using', policy.using),
|
|
42
|
-
...ifDefined('withCheck', policy.withCheck),
|
|
43
|
-
permissive: policy.permissive,
|
|
44
|
-
});
|
|
45
|
-
const list = policiesByTable.get(policy.tableName) ?? [];
|
|
46
|
-
list.push(resolved);
|
|
47
|
-
policiesByTable.set(policy.tableName, list);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Attach policies to each table from the relational projection. A policy that
|
|
53
|
-
// references a table absent from the schema IR is a malformed contract — the
|
|
54
|
-
// loop below throws rather than fabricating a stub table.
|
|
55
|
-
const tables: Record<string, PostgresTableIR> = {};
|
|
56
|
-
for (const [tableName, sqlTable] of Object.entries(sqlIr.tables)) {
|
|
57
|
-
tables[tableName] = new PostgresTableIR({
|
|
58
|
-
name: sqlTable.name,
|
|
59
|
-
columns: sqlTable.columns,
|
|
60
|
-
foreignKeys: sqlTable.foreignKeys,
|
|
61
|
-
uniques: sqlTable.uniques,
|
|
62
|
-
indexes: sqlTable.indexes,
|
|
63
|
-
...(sqlTable.primaryKey !== undefined ? { primaryKey: sqlTable.primaryKey } : {}),
|
|
64
|
-
...(sqlTable.annotations !== undefined ? { annotations: sqlTable.annotations } : {}),
|
|
65
|
-
...(sqlTable.checks !== undefined ? { checks: sqlTable.checks } : {}),
|
|
66
|
-
rlsPolicies: policiesByTable.get(tableName) ?? [],
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
for (const [tableName, policies] of policiesByTable) {
|
|
70
|
-
if (!(tableName in tables)) {
|
|
71
|
-
const policyName = policies[0]?.name ?? '(unknown)';
|
|
72
|
-
throw new Error(
|
|
73
|
-
`contract-to-postgres-schema-ir: policy "${policyName}" references table "${tableName}" not present in the schema`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return new PostgresSchemaIR({
|
|
79
|
-
tables,
|
|
80
|
-
roles:
|
|
81
|
-
contract === null
|
|
82
|
-
? []
|
|
83
|
-
: Object.values(contract.storage.namespaces).flatMap((ns) =>
|
|
84
|
-
isPostgresSchema(ns) ? Object.values(ns.role) : [],
|
|
85
|
-
),
|
|
86
|
-
pgSchemaName: 'public',
|
|
87
|
-
pgVersion: '',
|
|
88
|
-
existingSchemas: ownedSchemas,
|
|
89
|
-
nativeEnumTypeNames: [],
|
|
90
|
-
});
|
|
91
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
2
|
-
import { diffSchemas } from '@prisma-next/framework-components/control';
|
|
3
|
-
import { isPostgresRlsPolicy, type PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';
|
|
4
|
-
import { ensurePostgresSchemaIR, type PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';
|
|
5
|
-
|
|
6
|
-
// Renders a display-only reference string for the diff message. If policy
|
|
7
|
-
// rendering grows, route it through the adapter's SQL renderer so the message
|
|
8
|
-
// can't diverge from the emitted policy SQL.
|
|
9
|
-
function renderPostgresPolicyReference(policy: PostgresRlsPolicy): string {
|
|
10
|
-
return `policy "${policy.name}" on "${policy.namespaceId}"."${policy.tableName}"`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Computes schema drift between two derived schema IRs.
|
|
15
|
-
*
|
|
16
|
-
* 1. Runs the framework total diff.
|
|
17
|
-
* 2. Filters to policy-subject issues only — this is transitional: the generic
|
|
18
|
-
* differ walks the whole tree, but the legacy relational verifier still owns
|
|
19
|
-
* table/column drift, so non-policy issues are dropped here.
|
|
20
|
-
* 3. Remaps the message to a human-readable policy reference.
|
|
21
|
-
*
|
|
22
|
-
* Ownership filtering (dropping `extra` issues in namespaces a contract doesn't
|
|
23
|
-
* own) is the caller's responsibility — use `filterIssuesByOwnership`.
|
|
24
|
-
*/
|
|
25
|
-
export function diffPostgresSchema(
|
|
26
|
-
expected: PostgresSchemaIR,
|
|
27
|
-
actual: PostgresSchemaIR,
|
|
28
|
-
): readonly SchemaDiffIssue[] {
|
|
29
|
-
const safeActual = ensurePostgresSchemaIR(actual);
|
|
30
|
-
const issues = diffSchemas(expected, safeActual);
|
|
31
|
-
|
|
32
|
-
return issues
|
|
33
|
-
.filter((i) => isPostgresRlsPolicy(i.expected ?? i.actual))
|
|
34
|
-
.map((i) => {
|
|
35
|
-
const policy = i.expected ?? i.actual;
|
|
36
|
-
if (!isPostgresRlsPolicy(policy)) return i;
|
|
37
|
-
return { ...i, message: `${i.outcome}: ${renderPostgresPolicyReference(policy)}` };
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Filters `extra` policy issues to those in owned namespaces. Call after
|
|
43
|
-
* `diffPostgresSchema` with the union of namespace ids from the expected IR's
|
|
44
|
-
* policies and its `existingSchemas`.
|
|
45
|
-
*/
|
|
46
|
-
export function filterIssuesByOwnership(
|
|
47
|
-
issues: readonly SchemaDiffIssue[],
|
|
48
|
-
ownedSchemaNames: ReadonlySet<string>,
|
|
49
|
-
): readonly SchemaDiffIssue[] {
|
|
50
|
-
return issues.filter(
|
|
51
|
-
(i) =>
|
|
52
|
-
i.outcome !== 'extra' ||
|
|
53
|
-
(isPostgresRlsPolicy(i.actual) && ownedSchemaNames.has(i.actual.namespaceId)),
|
|
54
|
-
);
|
|
55
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import type { DiffableNode } from '@prisma-next/framework-components/control';
|
|
2
|
-
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
3
|
-
import {
|
|
4
|
-
type SqlAnnotations,
|
|
5
|
-
type SqlSchemaIR,
|
|
6
|
-
SqlSchemaIRNode,
|
|
7
|
-
type SqlSchemaTarget,
|
|
8
|
-
type SqlTableIRInput,
|
|
9
|
-
} from '@prisma-next/sql-schema-ir/types';
|
|
10
|
-
import { blindCast } from '@prisma-next/utils/casts';
|
|
11
|
-
import type { PostgresRlsPolicy } from './postgres-rls-policy';
|
|
12
|
-
import type { PostgresRole } from './postgres-role';
|
|
13
|
-
import { PostgresTableIR } from './postgres-table-ir';
|
|
14
|
-
|
|
15
|
-
export interface PostgresSchemaIRInput {
|
|
16
|
-
readonly tables: Record<
|
|
17
|
-
string,
|
|
18
|
-
PostgresTableIR | (SqlTableIRInput & { rlsPolicies?: readonly PostgresRlsPolicy[] })
|
|
19
|
-
>;
|
|
20
|
-
readonly pgSchemaName: string;
|
|
21
|
-
readonly pgVersion: string;
|
|
22
|
-
readonly roles: readonly PostgresRole[];
|
|
23
|
-
readonly existingSchemas: readonly string[];
|
|
24
|
-
readonly nativeEnumTypeNames: readonly string[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Postgres-specific schema IR. Mirrors the structure of `SqlSchemaIR`
|
|
29
|
-
* (same `tables` + optional `annotations` fields) and adds typed fields for
|
|
30
|
-
* data the postgres adapter collects during introspection.
|
|
31
|
-
*
|
|
32
|
-
* Extends `SqlSchemaIRNode` directly rather than `SqlSchemaIR` because
|
|
33
|
-
* `SqlSchemaIR` calls `freezeNode` in its constructor, which prevents
|
|
34
|
-
* subclass field initialisation. `PostgresSchemaIR` replicates the minimal
|
|
35
|
-
* `SqlSchemaIR` structure and freezes itself at the end of its own
|
|
36
|
-
* constructor.
|
|
37
|
-
*
|
|
38
|
-
* `tables` holds `PostgresTableIR` instances which carry their own RLS
|
|
39
|
-
* policies. `children()` returns the tables directly — the table instances
|
|
40
|
-
* ARE the diff-tree nodes.
|
|
41
|
-
*
|
|
42
|
-
* Nothing RLS-specific leaks into the sql-family layer.
|
|
43
|
-
*/
|
|
44
|
-
export class PostgresSchemaIR extends SqlSchemaIRNode implements DiffableNode {
|
|
45
|
-
readonly nodeTarget: SqlSchemaTarget = 'postgres';
|
|
46
|
-
readonly tables: Readonly<Record<string, PostgresTableIR>>;
|
|
47
|
-
declare readonly annotations?: SqlAnnotations;
|
|
48
|
-
readonly pgSchemaName: string;
|
|
49
|
-
readonly pgVersion: string;
|
|
50
|
-
readonly roles: readonly PostgresRole[];
|
|
51
|
-
readonly existingSchemas: readonly string[];
|
|
52
|
-
readonly nativeEnumTypeNames: readonly string[];
|
|
53
|
-
|
|
54
|
-
constructor(input: PostgresSchemaIRInput) {
|
|
55
|
-
super();
|
|
56
|
-
this.tables = Object.freeze(
|
|
57
|
-
Object.fromEntries(
|
|
58
|
-
Object.entries(input.tables).map(([key, t]) => [
|
|
59
|
-
key,
|
|
60
|
-
t instanceof PostgresTableIR ? t : new PostgresTableIR(t),
|
|
61
|
-
]),
|
|
62
|
-
),
|
|
63
|
-
);
|
|
64
|
-
this.pgSchemaName = input.pgSchemaName;
|
|
65
|
-
this.pgVersion = input.pgVersion;
|
|
66
|
-
this.roles = Object.freeze([...input.roles]);
|
|
67
|
-
this.existingSchemas = Object.freeze([...input.existingSchemas]);
|
|
68
|
-
this.nativeEnumTypeNames = Object.freeze([...input.nativeEnumTypeNames]);
|
|
69
|
-
// Populate the annotations.pg bag with only the subset the family layer
|
|
70
|
-
// reads (nativeEnumTypeNames for PSL inference, existingSchemas for
|
|
71
|
-
// namespace presence checks).
|
|
72
|
-
this.annotations = {
|
|
73
|
-
pg: {
|
|
74
|
-
schema: input.pgSchemaName,
|
|
75
|
-
...(input.nativeEnumTypeNames.length > 0 && {
|
|
76
|
-
nativeEnumTypeNames: input.nativeEnumTypeNames,
|
|
77
|
-
}),
|
|
78
|
-
...(input.existingSchemas.length > 0 && {
|
|
79
|
-
existingSchemas: input.existingSchemas,
|
|
80
|
-
}),
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
freezeNode(this);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
get id(): string {
|
|
87
|
-
return this.pgSchemaName;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
get rlsPolicies(): readonly PostgresRlsPolicy[] {
|
|
91
|
-
return Object.values(this.tables).flatMap((t) => t.rlsPolicies);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
isEqualTo(_other: DiffableNode): boolean {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
children(): readonly DiffableNode[] {
|
|
99
|
-
return Object.values(this.tables);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Structural guard for `PostgresSchemaIR`, narrowing on the `nodeTarget`
|
|
105
|
-
* discriminant rather than `instanceof`. `nodeTarget` is an enumerable own field
|
|
106
|
-
* (a plain class-field initializer), so it survives the `{ ...schema, tables }`
|
|
107
|
-
* spread the multi-space verify path (`projectSchemaToSpace`) produces — that
|
|
108
|
-
* projected object is not a class instance but retains every enumerable own
|
|
109
|
-
* property. The family-level `kind = 'sql-schema-ir'` discriminator is unusable
|
|
110
|
-
* here: it is shared by every SQL schema-IR node and is non-enumerable (dropped
|
|
111
|
-
* by the spread).
|
|
112
|
-
*/
|
|
113
|
-
export function isPostgresSchemaIR(schema: SqlSchemaIR): schema is PostgresSchemaIR {
|
|
114
|
-
return schema.nodeTarget === 'postgres';
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function assertPostgresSchemaIR(schema: SqlSchemaIR): asserts schema is PostgresSchemaIR {
|
|
118
|
-
if (!isPostgresSchemaIR(schema)) {
|
|
119
|
-
throw new Error(
|
|
120
|
-
`planPostgresSchemaDiff: expected a PostgresSchemaIR but got nodeTarget=${String(schema.nodeTarget ?? typeof schema)}`,
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Returns `schema` as-is when it is a real `PostgresSchemaIR` instance, or
|
|
127
|
-
* reconstructs one when `projectSchemaToSpace` has spread the class into a
|
|
128
|
-
* plain object (losing prototype methods).
|
|
129
|
-
*/
|
|
130
|
-
export function ensurePostgresSchemaIR(schema: PostgresSchemaIR): PostgresSchemaIR {
|
|
131
|
-
if (schema instanceof PostgresSchemaIR) return schema;
|
|
132
|
-
return new PostgresSchemaIR(
|
|
133
|
-
blindCast<
|
|
134
|
-
PostgresSchemaIRInput,
|
|
135
|
-
'spread objects from projectSchemaToSpace preserve all own-enumerable fields'
|
|
136
|
-
>(schema),
|
|
137
|
-
);
|
|
138
|
-
}
|