@prisma-next/target-postgres 0.14.0-dev.22 → 0.14.0-dev.24
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/contract-free.mjs +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +8 -7
- package/dist/control.mjs.map +1 -1
- package/dist/{ddl-BJPdPsT3.mjs → ddl-CGf6UABz.mjs} +2 -2
- package/dist/{ddl-BJPdPsT3.mjs.map → ddl-CGf6UABz.mjs.map} +1 -1
- package/dist/{descriptor-meta-CKpjK2Nv.mjs → descriptor-meta-Dvvpu_jU.mjs} +3 -3
- package/dist/{descriptor-meta-CKpjK2Nv.mjs.map → descriptor-meta-Dvvpu_jU.mjs.map} +1 -1
- package/dist/{descriptor-meta-runtime-DiVla56r.mjs → descriptor-meta-runtime-D5zHFKUz.mjs} +2 -2
- package/dist/descriptor-meta-runtime-D5zHFKUz.mjs.map +1 -0
- package/dist/{issue-planner-YwXUKGZ1.mjs → issue-planner-D5H1VuVP.mjs} +4 -4
- package/dist/{issue-planner-YwXUKGZ1.mjs.map → issue-planner-D5H1VuVP.mjs.map} +1 -1
- package/dist/issue-planner.d.mts +2 -2
- 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-DcY4BHNh.mjs → op-factory-call-DIdBDwmO.mjs} +3 -3
- package/dist/op-factory-call-DIdBDwmO.mjs.map +1 -0
- package/dist/{op-factory-call-CQ4P40QC.d.mts → op-factory-call-DPJR7tJc.d.mts} +3 -3
- package/dist/{op-factory-call-CQ4P40QC.d.mts.map → op-factory-call-DPJR7tJc.d.mts.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 +2 -3
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-_ZHpIQ1-.mjs → planner-BnNEtGYM.mjs} +116 -76
- package/dist/planner-BnNEtGYM.mjs.map +1 -0
- package/dist/{planner-produced-postgres-migration-CNTSCMl7.d.mts → planner-produced-postgres-migration-BO-frvvN.d.mts} +2 -2
- package/dist/{planner-produced-postgres-migration-CNTSCMl7.d.mts.map → planner-produced-postgres-migration-BO-frvvN.d.mts.map} +1 -1
- package/dist/{planner-produced-postgres-migration-Dv5ZAvHt.mjs → planner-produced-postgres-migration-DzvdQ-7K.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-Dv5ZAvHt.mjs.map → planner-produced-postgres-migration-DzvdQ-7K.mjs.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-C7nLjabn.mjs → planner-sql-checks-CyjaoKhm.mjs} +2 -2
- package/dist/{planner-sql-checks-C7nLjabn.mjs.map → planner-sql-checks-CyjaoKhm.mjs.map} +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/planner.d.mts +30 -35
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +2 -2
- package/dist/{postgres-contract-serializer-DJDGaS0q.mjs → postgres-contract-serializer-tGMiJcl4.mjs} +3 -3
- package/dist/{postgres-contract-serializer-DJDGaS0q.mjs.map → postgres-contract-serializer-tGMiJcl4.mjs.map} +1 -1
- package/dist/{postgres-migration-Bj0olfl3.mjs → postgres-migration-C8JZyTSJ.mjs} +2 -2
- package/dist/{postgres-migration-Bj0olfl3.mjs.map → postgres-migration-C8JZyTSJ.mjs.map} +1 -1
- package/dist/{postgres-migration-DJNJHcdP.d.mts → postgres-migration-Cs7zMOe1.d.mts} +3 -3
- package/dist/{postgres-migration-DJNJHcdP.d.mts.map → postgres-migration-Cs7zMOe1.d.mts.map} +1 -1
- package/dist/{postgres-rls-policy-D_z1osEq.d.mts → postgres-rls-policy-12wAEQhs.d.mts} +4 -4
- package/dist/postgres-rls-policy-12wAEQhs.d.mts.map +1 -0
- package/dist/{postgres-schema-Bn4tsMuo.d.mts → postgres-schema-DJUEkWg-.d.mts} +38 -5
- package/dist/postgres-schema-DJUEkWg-.d.mts.map +1 -0
- package/dist/{postgres-schema-DfuJq-q_.mjs → postgres-schema-DLcc3W2-.mjs} +37 -40
- package/dist/postgres-schema-DLcc3W2-.mjs.map +1 -0
- package/dist/postgres-schema-ir-BJl_a3J7.d.mts +102 -0
- package/dist/postgres-schema-ir-BJl_a3J7.d.mts.map +1 -0
- package/dist/postgres-schema-ir-I_FiUndw.mjs +133 -0
- package/dist/postgres-schema-ir-I_FiUndw.mjs.map +1 -0
- package/dist/{postgres-schema-ir-annotations-CWHQ-H9Y.mjs → postgres-schema-ir-annotations-BbDSiwx2.mjs} +4 -4
- package/dist/postgres-schema-ir-annotations-BbDSiwx2.mjs.map +1 -0
- package/dist/runtime.mjs +2 -2
- package/dist/schema-ir-annotations.d.mts +1 -1
- package/dist/schema-ir-annotations.d.mts.map +1 -1
- package/dist/schema-ir-annotations.mjs +1 -1
- package/dist/types.d.mts +4 -5
- package/dist/types.mjs +3 -3
- package/package.json +19 -19
- package/src/core/authoring.ts +2 -2
- package/src/core/entity-kinds.ts +2 -2
- package/src/core/migrations/contract-to-postgres-schema-ir.ts +91 -0
- package/src/core/migrations/diff-postgres-schema.ts +55 -0
- 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 +44 -59
- package/src/core/migrations/verify-postgres-namespaces.ts +1 -1
- package/src/core/postgres-schema.ts +6 -2
- package/src/core/{postgres-rls-policy.ts → schema-ir/postgres-rls-policy.ts} +8 -10
- package/src/core/{postgres-role.ts → schema-ir/postgres-role.ts} +8 -9
- package/src/core/{postgres-schema-ir-annotations.ts → schema-ir/postgres-schema-ir-annotations.ts} +1 -1
- package/src/core/{postgres-schema-ir.ts → schema-ir/postgres-schema-ir.ts} +53 -16
- package/src/core/schema-ir/postgres-table-ir.ts +96 -0
- package/src/exports/control.ts +11 -12
- package/src/exports/planner.ts +5 -1
- package/src/exports/schema-ir-annotations.ts +1 -1
- package/src/exports/types.ts +15 -7
- package/dist/descriptor-meta-runtime-DiVla56r.mjs.map +0 -1
- package/dist/op-factory-call-DcY4BHNh.mjs.map +0 -1
- package/dist/planner-_ZHpIQ1-.mjs.map +0 -1
- package/dist/postgres-rls-policy-D_z1osEq.d.mts.map +0 -1
- package/dist/postgres-role-_CCuyPCQ.d.mts +0 -33
- package/dist/postgres-role-_CCuyPCQ.d.mts.map +0 -1
- package/dist/postgres-schema-Bn4tsMuo.d.mts.map +0 -1
- package/dist/postgres-schema-DfuJq-q_.mjs.map +0 -1
- package/dist/postgres-schema-ir-BF0X8jit.mjs +0 -66
- package/dist/postgres-schema-ir-BF0X8jit.mjs.map +0 -1
- package/dist/postgres-schema-ir-BQ3RpZMz.d.mts +0 -60
- package/dist/postgres-schema-ir-BQ3RpZMz.d.mts.map +0 -1
- package/dist/postgres-schema-ir-annotations-CWHQ-H9Y.mjs.map +0 -1
- package/src/core/migrations/verify-postgres-rls-policies.ts +0 -62
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-BF0X8jit.mjs","names":[],"sources":["../src/core/postgres-schema-ir.ts"],"sourcesContent":["import { freezeNode } from '@prisma-next/framework-components/ir';\nimport {\n type SqlAnnotations,\n type SqlSchemaIR,\n SqlSchemaIRNode,\n type SqlSchemaTarget,\n SqlTableIR,\n type SqlTableIRInput,\n} from '@prisma-next/sql-schema-ir/types';\nimport type { PostgresRlsPolicy } from './postgres-rls-policy';\nimport type { PostgresRole } from './postgres-role';\n\nexport interface PostgresSchemaIRInput {\n readonly tables: Record<string, SqlTableIR | SqlTableIRInput>;\n readonly pgSchemaName: string;\n readonly pgVersion: string;\n readonly rlsPolicies: readonly PostgresRlsPolicy[];\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 * RLS-specific fields (`rlsPolicies`, `roles`) are typed top-level fields on\n * this class — no `Reflect.get`, no untyped annotation bag access. The\n * `annotations.pg` bag is populated with only the subset the family layer\n * reads (`nativeEnumTypeNames`, `existingSchemas`, `schema`) so family-layer\n * PSL inference and namespace verification continue to work without knowing\n * about RLS.\n *\n * Nothing RLS-specific leaks into the sql-family layer.\n */\nexport class PostgresSchemaIR extends SqlSchemaIRNode {\n readonly nodeTarget: SqlSchemaTarget = 'postgres';\n readonly tables: Readonly<Record<string, SqlTableIR>>;\n declare readonly annotations?: SqlAnnotations;\n readonly pgSchemaName: string;\n readonly pgVersion: string;\n readonly rlsPolicies: readonly PostgresRlsPolicy[];\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 SqlTableIR ? t : new SqlTableIR(t),\n ]),\n ),\n );\n this.pgSchemaName = input.pgSchemaName;\n this.pgVersion = input.pgVersion;\n this.rlsPolicies = Object.freeze([...input.rlsPolicies]);\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). rlsPolicies and roles are NOT placed here\n // — they are consumed directly via typed fields on this class.\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\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0CA,IAAa,mBAAb,cAAsC,gBAAgB;CACpD,aAAuC;CACvC;CAEA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,OAA8B;EACxC,MAAM;EACN,KAAK,SAAS,OAAO,OACnB,OAAO,YACL,OAAO,QAAQ,MAAM,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO,CAC7C,KACA,aAAa,aAAa,IAAI,IAAI,WAAW,CAAC,CAChD,CAAC,CACH,CACF;EACA,KAAK,eAAe,MAAM;EAC1B,KAAK,YAAY,MAAM;EACvB,KAAK,cAAc,OAAO,OAAO,CAAC,GAAG,MAAM,WAAW,CAAC;EACvD,KAAK,QAAQ,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC;EAC3C,KAAK,kBAAkB,OAAO,OAAO,CAAC,GAAG,MAAM,eAAe,CAAC;EAC/D,KAAK,sBAAsB,OAAO,OAAO,CAAC,GAAG,MAAM,mBAAmB,CAAC;EAKvE,KAAK,cAAc,EACjB,IAAI;GACF,QAAQ,MAAM;GACd,GAAI,MAAM,oBAAoB,SAAS,KAAK,EAC1C,qBAAqB,MAAM,oBAC7B;GACA,GAAI,MAAM,gBAAgB,SAAS,KAAK,EACtC,iBAAiB,MAAM,gBACzB;EACF,EACF;EACA,WAAW,IAAI;CACjB;AACF;;;;;;;;;;;AAYA,SAAgB,mBAAmB,QAAiD;CAClF,OAAO,OAAO,eAAe;AAC/B"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { t as PostgresRlsPolicy } from "./postgres-rls-policy-D_z1osEq.mjs";
|
|
2
|
-
import { t as PostgresRole } from "./postgres-role-_CCuyPCQ.mjs";
|
|
3
|
-
import { SqlAnnotations, SqlSchemaIR, SqlSchemaIRNode, SqlSchemaTarget, SqlTableIR, SqlTableIRInput } from "@prisma-next/sql-schema-ir/types";
|
|
4
|
-
|
|
5
|
-
//#region src/core/postgres-schema-ir.d.ts
|
|
6
|
-
interface PostgresSchemaIRInput {
|
|
7
|
-
readonly tables: Record<string, SqlTableIR | SqlTableIRInput>;
|
|
8
|
-
readonly pgSchemaName: string;
|
|
9
|
-
readonly pgVersion: string;
|
|
10
|
-
readonly rlsPolicies: readonly PostgresRlsPolicy[];
|
|
11
|
-
readonly roles: readonly PostgresRole[];
|
|
12
|
-
readonly existingSchemas: readonly string[];
|
|
13
|
-
readonly nativeEnumTypeNames: readonly string[];
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Postgres-specific schema IR. Mirrors the structure of `SqlSchemaIR`
|
|
17
|
-
* (same `tables` + optional `annotations` fields) and adds typed fields for
|
|
18
|
-
* data the postgres adapter collects during introspection.
|
|
19
|
-
*
|
|
20
|
-
* Extends `SqlSchemaIRNode` directly rather than `SqlSchemaIR` because
|
|
21
|
-
* `SqlSchemaIR` calls `freezeNode` in its constructor, which prevents
|
|
22
|
-
* subclass field initialisation. `PostgresSchemaIR` replicates the minimal
|
|
23
|
-
* `SqlSchemaIR` structure and freezes itself at the end of its own
|
|
24
|
-
* constructor.
|
|
25
|
-
*
|
|
26
|
-
* RLS-specific fields (`rlsPolicies`, `roles`) are typed top-level fields on
|
|
27
|
-
* this class — no `Reflect.get`, no untyped annotation bag access. The
|
|
28
|
-
* `annotations.pg` bag is populated with only the subset the family layer
|
|
29
|
-
* reads (`nativeEnumTypeNames`, `existingSchemas`, `schema`) so family-layer
|
|
30
|
-
* PSL inference and namespace verification continue to work without knowing
|
|
31
|
-
* about RLS.
|
|
32
|
-
*
|
|
33
|
-
* Nothing RLS-specific leaks into the sql-family layer.
|
|
34
|
-
*/
|
|
35
|
-
declare class PostgresSchemaIR extends SqlSchemaIRNode {
|
|
36
|
-
readonly nodeTarget: SqlSchemaTarget;
|
|
37
|
-
readonly tables: Readonly<Record<string, SqlTableIR>>;
|
|
38
|
-
readonly annotations?: SqlAnnotations;
|
|
39
|
-
readonly pgSchemaName: string;
|
|
40
|
-
readonly pgVersion: string;
|
|
41
|
-
readonly rlsPolicies: readonly PostgresRlsPolicy[];
|
|
42
|
-
readonly roles: readonly PostgresRole[];
|
|
43
|
-
readonly existingSchemas: readonly string[];
|
|
44
|
-
readonly nativeEnumTypeNames: readonly string[];
|
|
45
|
-
constructor(input: PostgresSchemaIRInput);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Structural guard for `PostgresSchemaIR`, narrowing on the `nodeTarget`
|
|
49
|
-
* discriminant rather than `instanceof`. `nodeTarget` is an enumerable own field
|
|
50
|
-
* (a plain class-field initializer), so it survives the `{ ...schema, tables }`
|
|
51
|
-
* spread the multi-space verify path (`projectSchemaToSpace`) produces — that
|
|
52
|
-
* projected object is not a class instance but retains every enumerable own
|
|
53
|
-
* property. The family-level `kind = 'sql-schema-ir'` discriminator is unusable
|
|
54
|
-
* here: it is shared by every SQL schema-IR node and is non-enumerable (dropped
|
|
55
|
-
* by the spread).
|
|
56
|
-
*/
|
|
57
|
-
declare function isPostgresSchemaIR(schema: SqlSchemaIR): schema is PostgresSchemaIR;
|
|
58
|
-
//#endregion
|
|
59
|
-
export { PostgresSchemaIRInput as n, isPostgresSchemaIR as r, PostgresSchemaIR as t };
|
|
60
|
-
//# sourceMappingURL=postgres-schema-ir-BQ3RpZMz.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-BQ3RpZMz.d.mts","names":[],"sources":["../src/core/postgres-schema-ir.ts"],"mappings":";;;;;UAYiB,qBAAA;EAAA,SACN,MAAA,EAAQ,MAAA,SAAe,UAAA,GAAa,eAAA;EAAA,SACpC,YAAA;EAAA,SACA,SAAA;EAAA,SACA,WAAA,WAAsB,iBAAA;EAAA,SACtB,KAAA,WAAgB,YAAA;EAAA,SAChB,eAAA;EAAA,SACA,mBAAA;AAAA;;;;;;;;;;;;;;;;;AAAmB;AAuB9B;;;cAAa,gBAAA,SAAyB,eAAA;EAAA,SAC3B,UAAA,EAAY,eAAA;EAAA,SACZ,MAAA,EAAQ,QAAA,CAAS,MAAA,SAAe,UAAA;EAAA,SACxB,WAAA,GAAc,cAAA;EAAA,SACtB,YAAA;EAAA,SACA,SAAA;EAAA,SACA,WAAA,WAAsB,iBAAA;EAAA,SACtB,KAAA,WAAgB,YAAA;EAAA,SAChB,eAAA;EAAA,SACA,mBAAA;cAEG,KAAA,EAAO,qBAAA;AAAA;;;;;;;;;;;iBA6CL,kBAAA,CAAmB,MAAA,EAAQ,WAAA,GAAc,MAAA,IAAU,gBAAgB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-ir-annotations-CWHQ-H9Y.mjs","names":[],"sources":["../src/core/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,62 +0,0 @@
|
|
|
1
|
-
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
-
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
3
|
-
import { diffNodes } from '@prisma-next/framework-components/control';
|
|
4
|
-
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
5
|
-
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
6
|
-
import { isPostgresSchema } from '../postgres-schema';
|
|
7
|
-
import type { PostgresSchemaIR } from '../postgres-schema-ir';
|
|
8
|
-
|
|
9
|
-
// Postgres binds the late-bound (`__unbound__`) namespace to the `public`
|
|
10
|
-
// schema, so an unbound contract owns `public` in the live database. Both the
|
|
11
|
-
// contract slot ids and the introspected policy coordinates can carry either
|
|
12
|
-
// form depending on how the schema was lowered, so normalize both sides to the
|
|
13
|
-
// same id before comparing ownership.
|
|
14
|
-
const POSTGRES_DEFAULT_NAMESPACE_ID = 'public';
|
|
15
|
-
|
|
16
|
-
function resolveNamespaceId(namespaceId: string): string {
|
|
17
|
-
return namespaceId === UNBOUND_NAMESPACE_ID ? POSTGRES_DEFAULT_NAMESPACE_ID : namespaceId;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Computes RLS policy drift between the contract and the live DB schema using
|
|
22
|
-
* the generic {@link diffNodes} differ. Returns `SchemaDiffIssue[]` keyed by
|
|
23
|
-
* the full `EntityCoordinate` (plane + namespaceId + entityKind + entityName).
|
|
24
|
-
*
|
|
25
|
-
* Both sides supply `PostgresRlsPolicy` nodes that implement `DiffableNode`
|
|
26
|
-
* with a concrete namespace coordinate — the contract carries explicit
|
|
27
|
-
* `namespaceId` set during lowering (e.g. `'public'`); the introspected schema
|
|
28
|
-
* carries the resolved DDL schema name. The differ matches purely on coordinate
|
|
29
|
-
* identity; no namespace interpretation happens here.
|
|
30
|
-
*
|
|
31
|
-
* The diff is scoped to the namespaces the verified contract owns. The live
|
|
32
|
-
* schema introspection returns every policy across all DB schemas, but a policy
|
|
33
|
-
* in a namespace this contract does not own belongs to another contract space
|
|
34
|
-
* (or is external) and must not be reported as extra. Without this scope a space
|
|
35
|
-
* that owns only `auth`/`storage` (e.g. the supabase extension space) would flag
|
|
36
|
-
* the application space's `public.*` policies as extra during verify.
|
|
37
|
-
*
|
|
38
|
-
* Ownership is the set of namespaces the contract declares (its
|
|
39
|
-
* `storage.namespaces` slot keys), with the late-bound `__unbound__` slot
|
|
40
|
-
* resolved to the Postgres default `public` so a single-namespace contract still
|
|
41
|
-
* owns — and diffs — its `public` policies.
|
|
42
|
-
*/
|
|
43
|
-
export function diffPostgresRlsPolicies(input: {
|
|
44
|
-
readonly contract: Contract<SqlStorage>;
|
|
45
|
-
readonly schema: PostgresSchemaIR;
|
|
46
|
-
}): readonly SchemaDiffIssue[] {
|
|
47
|
-
const { contract, schema } = input;
|
|
48
|
-
|
|
49
|
-
const ownedNamespaceIds = new Set(
|
|
50
|
-
Object.keys(contract.storage.namespaces).map(resolveNamespaceId),
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const expected = Object.values(contract.storage.namespaces).flatMap((ns) =>
|
|
54
|
-
isPostgresSchema(ns) ? Object.values(ns.policy) : [],
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const actual = schema.rlsPolicies.filter((policy) =>
|
|
58
|
-
ownedNamespaceIds.has(resolveNamespaceId(policy.namespaceId)),
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return diffNodes(expected, actual);
|
|
62
|
-
}
|