@prisma-next/target-postgres 0.14.0-dev.55 → 0.14.0-dev.57
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-BBIGcFZM.mjs → authoring-WkqG_MkU.mjs} +38 -6
- package/dist/authoring-WkqG_MkU.mjs.map +1 -0
- package/dist/contract-free.d.mts +27 -2
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +3 -3
- package/dist/{control-policy-DievMCOV.mjs → control-policy-BtOZBVxL.mjs} +38 -13
- package/dist/control-policy-BtOZBVxL.mjs.map +1 -0
- package/dist/control.mjs +6 -6
- package/dist/{ddl-D5j4JiAB.mjs → ddl-B-krEXY1.mjs} +18 -4
- package/dist/{ddl-D5j4JiAB.mjs.map → ddl-B-krEXY1.mjs.map} +1 -1
- package/dist/ddl.d.mts +2 -2
- package/dist/ddl.mjs +2 -2
- package/dist/{descriptor-meta-C-tyS25s.mjs → descriptor-meta-BOcKPaLE.mjs} +4 -3
- package/dist/descriptor-meta-BOcKPaLE.mjs.map +1 -0
- package/dist/{diff-database-schema-ff3ioNtK.mjs → diff-database-schema-CWb-jeLy.mjs} +19 -11
- package/dist/diff-database-schema-CWb-jeLy.mjs.map +1 -0
- package/dist/diff-database-schema.d.mts +1 -1
- package/dist/diff-database-schema.d.mts.map +1 -1
- package/dist/diff-database-schema.mjs +1 -1
- 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 +2 -2
- package/dist/migration.mjs +2 -2
- package/dist/{nodes-Dh__NS58.mjs → nodes-B815pj_X.mjs} +34 -2
- package/dist/{nodes-Dh__NS58.mjs.map → nodes-B815pj_X.mjs.map} +1 -1
- package/dist/{nodes-CSkPX3rI.d.mts → nodes-BtQyZha6.d.mts} +29 -3
- package/dist/nodes-BtQyZha6.d.mts.map +1 -0
- package/dist/{op-factory-call-Dt-Jx5JS.d.mts → op-factory-call-D6_7-7Vc.d.mts} +24 -2
- package/dist/{op-factory-call-Dt-Jx5JS.d.mts.map → op-factory-call-D6_7-7Vc.d.mts.map} +1 -1
- package/dist/{op-factory-call-DZWTTjKM.mjs → op-factory-call-DxNNKUeZ.mjs} +99 -4
- package/dist/op-factory-call-DxNNKUeZ.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 +29 -2
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-DWQYPxP8.mjs → planner-BryLk0Ie.mjs} +80 -24
- package/dist/planner-BryLk0Ie.mjs.map +1 -0
- package/dist/{planner-produced-postgres-migration-Ch1L8RiV.mjs → planner-produced-postgres-migration-BLJH1zIc.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-Ch1L8RiV.mjs.map → planner-produced-postgres-migration-BLJH1zIc.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-C0a7I1-e.d.mts → planner-produced-postgres-migration-CGifB6VH.d.mts} +2 -2
- package/dist/{planner-produced-postgres-migration-C0a7I1-e.d.mts.map → planner-produced-postgres-migration-CGifB6VH.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-D8Q5ck4o.mjs → planner-sql-checks-AXoxB1Jl.mjs} +2 -2
- package/dist/{planner-sql-checks-D8Q5ck4o.mjs.map → planner-sql-checks-AXoxB1Jl.mjs.map} +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/planner.d.mts +23 -6
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +2 -2
- package/dist/{postgres-contract-view-C-By7rOB.mjs → postgres-contract-view-Dg-N7KA7.mjs} +4 -3
- package/dist/postgres-contract-view-Dg-N7KA7.mjs.map +1 -0
- package/dist/{postgres-database-schema-node-UpzA0Ug5.d.mts → postgres-database-schema-node-CfdTY-Qs.d.mts} +18 -3
- package/dist/postgres-database-schema-node-CfdTY-Qs.d.mts.map +1 -0
- package/dist/{postgres-migration-D3XACWKM.mjs → postgres-migration-BahMHTbj.mjs} +3 -3
- package/dist/{postgres-migration-D3XACWKM.mjs.map → postgres-migration-BahMHTbj.mjs.map} +1 -1
- package/dist/{postgres-migration-DFaxuRyI.d.mts → postgres-migration-cyBe2Ee0.d.mts} +2 -2
- package/dist/{postgres-migration-DFaxuRyI.d.mts.map → postgres-migration-cyBe2Ee0.d.mts.map} +1 -1
- package/dist/{postgres-table-schema-node-BZWWEo7B.mjs → postgres-role-schema-node-BiSTCTNg.mjs} +4 -69
- package/dist/postgres-role-schema-node-BiSTCTNg.mjs.map +1 -0
- package/dist/{postgres-schema-9vFZLwGo.d.mts → postgres-schema-CU4gF6QZ.d.mts} +30 -2
- package/dist/postgres-schema-CU4gF6QZ.d.mts.map +1 -0
- package/dist/{postgres-schema-DcG72fcT.mjs → postgres-schema-DTLA_aRi.mjs} +41 -2
- package/dist/postgres-schema-DTLA_aRi.mjs.map +1 -0
- package/dist/postgres-table-schema-node-9FCtCUz2.mjs +153 -0
- package/dist/postgres-table-schema-node-9FCtCUz2.mjs.map +1 -0
- package/dist/{resolve-ddl-schema-BOtCoeKV.mjs → resolve-ddl-schema-Ca88Tg6W.mjs} +2 -2
- package/dist/{resolve-ddl-schema-BOtCoeKV.mjs.map → resolve-ddl-schema-Ca88Tg6W.mjs.map} +1 -1
- package/dist/rls-canonicalize.d.mts +19 -1
- package/dist/rls-canonicalize.d.mts.map +1 -0
- package/dist/rls-canonicalize.mjs +2 -2
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/schema-ir-annotations.mjs +1 -1
- package/dist/types.d.mts +3 -3
- package/dist/types.mjs +4 -3
- package/dist/{canonicalize-Bn3BM1Cn.mjs → wire-name-rHHtr1h0.mjs} +31 -2
- package/dist/wire-name-rHHtr1h0.mjs.map +1 -0
- package/package.json +20 -20
- package/src/contract-free/ddl.ts +26 -0
- package/src/core/authoring.ts +44 -1
- package/src/core/ddl/nodes.ts +48 -1
- package/src/core/descriptor-meta.ts +2 -0
- package/src/core/entity-kinds.ts +11 -0
- package/src/core/migrations/contract-to-postgres-database-schema-node.ts +9 -0
- package/src/core/migrations/control-policy.ts +31 -1
- package/src/core/migrations/diff-database-schema.ts +1 -0
- package/src/core/migrations/issue-planner.ts +49 -4
- package/src/core/migrations/op-factory-call.ts +81 -1
- package/src/core/migrations/operations/rls.ts +82 -1
- package/src/core/migrations/planner.ts +110 -26
- package/src/core/postgres-contract-serializer.ts +7 -1
- package/src/core/postgres-rls-enablement.ts +34 -0
- package/src/core/postgres-schema.ts +19 -3
- package/src/core/postgres-validators.ts +6 -0
- package/src/core/rls/wire-name.ts +33 -0
- package/src/core/schema-ir/postgres-table-schema-node.ts +25 -3
- package/src/exports/contract-free.ts +4 -0
- package/src/exports/ddl.ts +2 -0
- package/src/exports/rls-canonicalize.ts +1 -0
- package/src/exports/types.ts +4 -0
- package/dist/authoring-BBIGcFZM.mjs.map +0 -1
- package/dist/canonicalize-Bn3BM1Cn.mjs.map +0 -1
- package/dist/control-policy-DievMCOV.mjs.map +0 -1
- package/dist/descriptor-meta-C-tyS25s.mjs.map +0 -1
- package/dist/diff-database-schema-ff3ioNtK.mjs.map +0 -1
- package/dist/nodes-CSkPX3rI.d.mts.map +0 -1
- package/dist/op-factory-call-DZWTTjKM.mjs.map +0 -1
- package/dist/planner-DWQYPxP8.mjs.map +0 -1
- package/dist/postgres-contract-view-C-By7rOB.mjs.map +0 -1
- package/dist/postgres-database-schema-node-UpzA0Ug5.d.mts.map +0 -1
- package/dist/postgres-schema-9vFZLwGo.d.mts.map +0 -1
- package/dist/postgres-schema-DcG72fcT.mjs.map +0 -1
- package/dist/postgres-table-schema-node-BZWWEo7B.mjs.map +0 -1
- package/dist/schema-node-kinds-ClScchhi.mjs +0 -76
- package/dist/schema-node-kinds-ClScchhi.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-table-schema-node-9FCtCUz2.mjs","names":[],"sources":["../src/core/schema-ir/schema-node-kinds.ts","../src/core/schema-ir/postgres-table-schema-node.ts"],"sourcesContent":["import type {\n DiffableNode,\n DiffSubjectGranularity,\n} from '@prisma-next/framework-components/control';\nimport {\n relationalNodeEntityKind,\n relationalNodeGranularity,\n type SqlSchemaIRNode,\n} from '@prisma-next/sql-schema-ir/types';\n\n/**\n * A Postgres schema-diff-tree node: a `SqlSchemaIRNode` that also implements\n * `DiffableNode` (the five `Postgres*SchemaNode` classes). `SqlSchemaIRNode`\n * alone is not a `DiffableNode` — its relational subclasses (`SqlColumnIR`, …)\n * carry no `id`/`isEqualTo`/`children` — so this intersection is the honest node\n * type the differ produces and the planner consumes (`SchemaDiff<SqlSchemaDiffNode>`).\n */\nexport type SqlSchemaDiffNode = SqlSchemaIRNode & DiffableNode;\n\n/**\n * The `nodeKind` discriminant for each Postgres schema-diff node. Each node\n * carries a unique value; the static `is`/`assert` guards compare against these\n * identifiers rather than spelling the string inline or using `instanceof`. The\n * field is an enumerable own property carried on every node instance.\n */\nexport const PostgresSchemaNodeKind = {\n database: 'postgres-database',\n namespace: 'postgres-namespace',\n table: 'postgres-table',\n policy: 'postgres-policy',\n role: 'postgres-role',\n} as const;\n\nexport type PostgresSchemaNodeKind =\n (typeof PostgresSchemaNodeKind)[keyof typeof PostgresSchemaNodeKind];\n\n/**\n * The one real map from a Postgres-specific `nodeKind` to the\n * framework-neutral {@link DiffSubjectGranularity} its diff issues carry —\n * resolution is by `nodeKind` equality against this map, never a\n * `nodeKind`-suffix string match and never anything stamped on the node.\n */\nconst POSTGRES_NODE_GRANULARITY: Readonly<Record<PostgresSchemaNodeKind, DiffSubjectGranularity>> =\n {\n [PostgresSchemaNodeKind.database]: 'structural',\n [PostgresSchemaNodeKind.namespace]: 'namespace',\n [PostgresSchemaNodeKind.table]: 'entity',\n [PostgresSchemaNodeKind.policy]: 'structural',\n [PostgresSchemaNodeKind.role]: 'structural',\n };\n\nfunction isPostgresSchemaNodeKind(nodeKind: string): nodeKind is PostgresSchemaNodeKind {\n return Object.hasOwn(POSTGRES_NODE_GRANULARITY, nodeKind);\n}\n\n/** Looks up the subject granularity for a Postgres-specific `nodeKind`. */\nexport function postgresNodeGranularity(nodeKind: PostgresSchemaNodeKind): DiffSubjectGranularity {\n return POSTGRES_NODE_GRANULARITY[nodeKind];\n}\n\n/**\n * The subject granularity for any node kind that appears in a Postgres diff\n * tree — the tree mixes Postgres-specific kinds (database/namespace/table/\n * policy/role) with the relational leaf kinds (columns, constraints, indexes,\n * …), so this dispatches to whichever family/target map owns the kind. Called\n * on demand by consumers (the family verdict, the framework aggregate's\n * unclaimed-elements sweep, via the {@link\n * import('@prisma-next/framework-components/control').SchemaSubjectClassifierCapable}\n * capability) — never stamped onto the issue or the node.\n */\nexport function postgresDiffSubjectGranularity(nodeKind: string): DiffSubjectGranularity {\n return isPostgresSchemaNodeKind(nodeKind)\n ? postgresNodeGranularity(nodeKind)\n : relationalNodeGranularity(nodeKind);\n}\n\n/**\n * The one real map from a Postgres-specific `nodeKind` to its storage\n * `entityKind` — the same vocabulary the contract storage's `entries`\n * dictionary keys use. Only the whole-table kind has an entity of its own;\n * database/namespace/policy/role nodes map to nothing here (a namespace is\n * addressed by id, not by an `entries` kind; policies and roles are\n * structural, never a sibling space's unclaimed entity).\n */\nconst POSTGRES_NODE_ENTITY_KIND: Partial<Readonly<Record<PostgresSchemaNodeKind, string>>> = {\n [PostgresSchemaNodeKind.table]: 'table',\n};\n\n/** Looks up the storage entityKind for a Postgres-specific `nodeKind`. */\nexport function postgresNodeEntityKind(nodeKind: PostgresSchemaNodeKind): string | undefined {\n return POSTGRES_NODE_ENTITY_KIND[nodeKind];\n}\n\n/**\n * The storage `entityKind` for any node kind that appears in a Postgres diff\n * tree — sibling of {@link postgresDiffSubjectGranularity}, dispatching the\n * same way to whichever family/target map owns the kind. Called on demand by\n * the framework aggregate's unclaimed-elements sweep via the {@link\n * import('@prisma-next/framework-components/control').SchemaSubjectClassifierCapable}\n * capability — never stamped onto the issue or the node.\n */\nexport function postgresDiffSubjectEntityKind(nodeKind: string): string | undefined {\n return isPostgresSchemaNodeKind(nodeKind)\n ? postgresNodeEntityKind(nodeKind)\n : relationalNodeEntityKind(nodeKind);\n}\n","import type { DiffableNode } from '@prisma-next/framework-components/control';\nimport { freezeNode } from '@prisma-next/framework-components/ir';\nimport {\n assertNode,\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 { blindCast } from '@prisma-next/utils/casts';\nimport type { PostgresPolicySchemaNode } from './postgres-policy-schema-node';\nimport { PostgresSchemaNodeKind } from './schema-node-kinds';\n\nexport interface PostgresTableSchemaNodeInput extends SqlTableIRInput {\n readonly policies?: readonly PostgresPolicySchemaNode[];\n /**\n * Whether row-level security is enabled on this table. Expected side:\n * stamped from the contract's `entries.rls` marker (never from the\n * policy set). Actual side: stamped from `pg_class.relrowsecurity` at\n * introspection. Required with no default so every construction site\n * supplies a deliberate value.\n */\n readonly rlsEnabled: boolean;\n}\n\n/**\n * Postgres-specific table schema-diff node. Carries all `SqlTableIR` fields\n * plus `policies`, 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.\n *\n * `id` is the table name. `isEqualTo` compares id + `rlsEnabled` — the\n * table's one own diffable attribute; all other structural drift is\n * expressed by its children. `children()` returns every column, the primary\n * key (when present), every foreign key, unique, index, and check constraint,\n * plus the policy nodes — one flat list, so a drifted column and a drifted\n * policy are both reported by the same walk. Order is deterministic (object\n * key order for columns, array order for the rest) so two structurally equal\n * tables always produce the same child list.\n */\nexport class PostgresTableSchemaNode extends SqlSchemaIRNode implements DiffableNode {\n override readonly nodeKind = PostgresSchemaNodeKind.table;\n\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 policies: readonly PostgresPolicySchemaNode[];\n readonly rlsEnabled: boolean;\n\n constructor(input: PostgresTableSchemaNodeInput) {\n super();\n this.name = input.name;\n this.rlsEnabled = input.rlsEnabled;\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.policies = Object.freeze([...(input.policies ?? [])]);\n freezeNode(this);\n }\n\n get id(): string {\n return this.name;\n }\n\n /**\n * Equal iff the ids (names) match AND `rlsEnabled` matches — the table's\n * one own attribute in the diff; all other structural drift is expressed\n * by children. A paired `not-equal` therefore always means enablement\n * drift, which the planner maps to ENABLE/DISABLE ROW LEVEL SECURITY.\n */\n isEqualTo(other: DiffableNode): boolean {\n const node = blindCast<\n SqlSchemaIRNode,\n 'every diff-tree node the differ pairs is a SqlSchemaIRNode'\n >(other);\n PostgresTableSchemaNode.assert(node);\n return this.id === node.id && this.rlsEnabled === node.rlsEnabled;\n }\n\n children(): readonly DiffableNode[] {\n return [\n ...Object.values(this.columns),\n ...(this.primaryKey ? [this.primaryKey] : []),\n ...this.foreignKeys,\n ...this.uniques,\n ...this.indexes,\n ...(this.checks ?? []),\n ...this.policies,\n ];\n }\n\n static is(node: SqlSchemaIRNode): node is PostgresTableSchemaNode {\n return node.nodeKind === PostgresSchemaNodeKind.table;\n }\n\n static assert(node: SqlSchemaIRNode): asserts node is PostgresTableSchemaNode {\n assertNode(node, 'PostgresTableSchemaNode', PostgresTableSchemaNode.is);\n }\n}\n"],"mappings":";;;;;;;;;;AAyBA,MAAa,yBAAyB;CACpC,UAAU;CACV,WAAW;CACX,OAAO;CACP,QAAQ;CACR,MAAM;AACR;;;;;;;AAWA,MAAM,4BACJ;EACG,uBAAuB,WAAW;EAClC,uBAAuB,YAAY;EACnC,uBAAuB,QAAQ;EAC/B,uBAAuB,SAAS;EAChC,uBAAuB,OAAO;AACjC;AAEF,SAAS,yBAAyB,UAAsD;CACtF,OAAO,OAAO,OAAO,2BAA2B,QAAQ;AAC1D;;AAGA,SAAgB,wBAAwB,UAA0D;CAChG,OAAO,0BAA0B;AACnC;;;;;;;;;;;AAYA,SAAgB,+BAA+B,UAA0C;CACvF,OAAO,yBAAyB,QAAQ,IACpC,wBAAwB,QAAQ,IAChC,0BAA0B,QAAQ;AACxC;;;;;;;;;AAUA,MAAM,4BAAuF,GAC1F,uBAAuB,QAAQ,QAClC;;AAGA,SAAgB,uBAAuB,UAAsD;CAC3F,OAAO,0BAA0B;AACnC;;;;;;;;;AAUA,SAAgB,8BAA8B,UAAsC;CAClF,OAAO,yBAAyB,QAAQ,IACpC,uBAAuB,QAAQ,IAC/B,yBAAyB,QAAQ;AACvC;;;;;;;;;;;;;;;;;;;;;ACzDA,IAAa,0BAAb,MAAa,gCAAgC,gBAAwC;CACnF,WAA6B,uBAAuB;CAEpD;CACA;CACA;CACA;CACA;CAIA;CACA;CAEA,YAAY,OAAqC;EAC/C,MAAM;EACN,KAAK,OAAO,MAAM;EAClB,KAAK,aAAa,MAAM;EACxB,KAAK,UAAU,OAAO,OACpB,OAAO,YACL,OAAO,QAAQ,MAAM,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAChD,KACA,eAAe,cAAc,MAAM,IAAI,YAAY,GAAG,CACxD,CAAC,CACH,CACF;EACA,KAAK,cAAc,OAAO,OACxB,MAAM,YAAY,KAAK,OAAQ,cAAc,kBAAkB,KAAK,IAAI,gBAAgB,EAAE,CAAE,CAC9F;EACA,KAAK,UAAU,OAAO,OACpB,MAAM,QAAQ,KAAK,MAAO,aAAa,cAAc,IAAI,IAAI,YAAY,CAAC,CAAE,CAC9E;EACA,KAAK,UAAU,OAAO,OACpB,MAAM,QAAQ,KAAK,MAAO,aAAa,aAAa,IAAI,IAAI,WAAW,CAAC,CAAE,CAC5E;EACA,IAAI,MAAM,eAAe,KAAA,GACvB,KAAK,aACH,MAAM,sBAAsB,aACxB,MAAM,aACN,IAAI,WAAW,MAAM,UAAU;EAEvC,IAAI,MAAM,gBAAgB,KAAA,GAAW,KAAK,cAAc,MAAM;EAC9D,IAAI,MAAM,WAAW,KAAA,KAAa,MAAM,OAAO,SAAS,GACtD,KAAK,SAAS,OAAO,OACnB,MAAM,OAAO,KAAK,MAChB,aAAa,uBAAuB,IAAI,IAAI,qBAAqB,CAAC,CACpE,CACF;EAEF,KAAK,WAAW,OAAO,OAAO,CAAC,GAAI,MAAM,YAAY,CAAC,CAAE,CAAC;EACzD,WAAW,IAAI;CACjB;CAEA,IAAI,KAAa;EACf,OAAO,KAAK;CACd;;;;;;;CAQA,UAAU,OAA8B;EACtC,MAAM,OAAO,UAGX,KAAK;EACP,wBAAwB,OAAO,IAAI;EACnC,OAAO,KAAK,OAAO,KAAK,MAAM,KAAK,eAAe,KAAK;CACzD;CAEA,WAAoC;EAClC,OAAO;GACL,GAAG,OAAO,OAAO,KAAK,OAAO;GAC7B,GAAI,KAAK,aAAa,CAAC,KAAK,UAAU,IAAI,CAAC;GAC3C,GAAG,KAAK;GACR,GAAG,KAAK;GACR,GAAG,KAAK;GACR,GAAI,KAAK,UAAU,CAAC;GACpB,GAAG,KAAK;EACV;CACF;CAEA,OAAO,GAAG,MAAwD;EAChE,OAAO,KAAK,aAAa,uBAAuB;CAClD;CAEA,OAAO,OAAO,MAAgE;EAC5E,WAAW,MAAM,2BAA2B,wBAAwB,EAAE;CACxE;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as DEFAULT_NAMESPACE_ID } from "./namespace-ids-xtp_ZY86.mjs";
|
|
2
|
-
import { r as isPostgresSchema } from "./postgres-schema-
|
|
2
|
+
import { r as isPostgresSchema } from "./postgres-schema-DTLA_aRi.mjs";
|
|
3
3
|
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
4
4
|
//#region src/core/migrations/resolve-ddl-schema.ts
|
|
5
5
|
/**
|
|
@@ -19,4 +19,4 @@ function resolveDdlSchemaForNamespaceStorage(storage, namespaceId) {
|
|
|
19
19
|
//#endregion
|
|
20
20
|
export { resolveDdlSchemaForNamespaceStorage as t };
|
|
21
21
|
|
|
22
|
-
//# sourceMappingURL=resolve-ddl-schema-
|
|
22
|
+
//# sourceMappingURL=resolve-ddl-schema-Ca88Tg6W.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-ddl-schema-
|
|
1
|
+
{"version":3,"file":"resolve-ddl-schema-Ca88Tg6W.mjs","names":[],"sources":["../src/core/migrations/resolve-ddl-schema.ts"],"sourcesContent":["import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport { DEFAULT_NAMESPACE_ID } from '../namespace-ids';\nimport { isPostgresSchema } from '../postgres-schema';\n\n/**\n * Given the contract's storage and a namespace id, returns the live Postgres\n * DDL schema name that namespace maps to. A named Postgres namespace dispatches\n * to its `ddlSchemaName(storage)`; the unbound sentinel resolves to\n * `DEFAULT_NAMESPACE_ID` (the search-path default for offline planning); a\n * bare object payload (used by some tests) falls back to the namespace id\n * itself.\n */\nexport function resolveDdlSchemaForNamespaceStorage(\n storage: SqlStorage,\n namespaceId: string,\n): string {\n if (namespaceId === UNBOUND_NAMESPACE_ID) {\n return DEFAULT_NAMESPACE_ID;\n }\n const namespace = storage.namespaces[namespaceId];\n if (namespace && isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,oCACd,SACA,aACQ;CACR,IAAI,gBAAgB,sBAClB,OAAO;CAET,MAAM,YAAY,QAAQ,WAAW;CACrC,IAAI,aAAa,iBAAiB,SAAS,GACzC,OAAO,UAAU,cAAc,OAAO;CAExC,OAAO;AACT"}
|
|
@@ -1,2 +1,20 @@
|
|
|
1
1
|
import { i as normalizePredicate, n as RlsPolicyOperation, r as computeContentHash, t as ContentHashParts } from "./canonicalize-CAbXtVtB.mjs";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/core/rls/wire-name.d.ts
|
|
4
|
+
interface RlsPolicyWireName {
|
|
5
|
+
/** The user-supplied part before the `_<8hex>` suffix. */
|
|
6
|
+
readonly prefix: string;
|
|
7
|
+
/** The 8-lowercase-hex content-hash suffix. */
|
|
8
|
+
readonly hash: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Splits an RLS policy wire name (`<prefix>_<8hex>`) into its prefix and
|
|
12
|
+
* content-hash suffix. Returns `undefined` when the name does not follow the
|
|
13
|
+
* wire-name shape (e.g. a policy created outside the toolchain) — callers
|
|
14
|
+
* treat such names as all-prefix. Consumed by introspection (prefix
|
|
15
|
+
* extraction) and by rename pairing (same hash, different prefix).
|
|
16
|
+
*/
|
|
17
|
+
declare function parseRlsPolicyWireName(name: string): RlsPolicyWireName | undefined;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { type ContentHashParts, type RlsPolicyOperation, type RlsPolicyWireName, computeContentHash, normalizePredicate, parseRlsPolicyWireName };
|
|
20
|
+
//# sourceMappingURL=rls-canonicalize.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rls-canonicalize.d.mts","names":[],"sources":["../src/core/rls/wire-name.ts"],"mappings":";;;UAAiB,iBAAA;;WAEN,MAAA;EAFM;EAAA,SAIN,IAAI;AAAA;;;;;;;;iBAsBC,sBAAA,CAAuB,IAAA,WAAe,iBAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { computeContentHash, normalizePredicate };
|
|
1
|
+
import { i as normalizePredicate, n as parseRlsPolicyWireName, r as computeContentHash } from "./wire-name-rHHtr1h0.mjs";
|
|
2
|
+
export { computeContentHash, normalizePredicate, parseRlsPolicyWireName };
|
package/dist/runtime.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/postgres-contract-serializer.ts","../src/exports/runtime.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/postgres-contract-serializer.ts","../src/exports/runtime.ts"],"mappings":";;;;;;;;;;cA0Ea,0BAAA,SAAmC,yBAAA,CAA0B,QAAA,CAAS,UAAA;cACrE,oBAAA,YAA+B,uBAAA;EAAA,UAWxB,wBAAA,CACjB,IAAA,UACA,GAAA,EAAK,MAAA,oBACJ,SAAA,GAAY,iBAAA;EAyBN,iBAAA,CAAkB,QAAA,EAAU,QAAA,CAAS,UAAA,IAAc,UAAA;AAAA;;;UCxG7C,6BAAA,SAAsC,qBAAqB;;;;;ADgE5E;;cCxDM,+BAAA,EAAiC,uBAAA,oBAGrC,6BAAA;EAAA,SAES,MAAA,iBAAuB,kBAAA;AAAA"}
|
package/dist/runtime.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as postgresTargetDescriptorMetaRuntime } from "./descriptor-meta-runtime-UwYdV8fD.mjs";
|
|
2
|
-
import { n as PostgresContractSerializer, t as PostgresContractView } from "./postgres-contract-view-
|
|
2
|
+
import { n as PostgresContractSerializer, t as PostgresContractView } from "./postgres-contract-view-Dg-N7KA7.mjs";
|
|
3
3
|
//#region src/exports/runtime.ts
|
|
4
4
|
/**
|
|
5
5
|
* Target-postgres deliberately does NOT import `SqlRuntimeTargetDescriptor` from `@prisma-next/sql-runtime`. The target package is a control-plane residence and must not pull the SQL execution-plane package into its dependency closure. The runtime descriptor here is shaped to satisfy the framework's `RuntimeTargetDescriptor` plus the structural `SqlStaticContributions` (`codecs:` returning a descriptor list) that
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as resolveDdlSchemaForNamespaceStorage } from "./resolve-ddl-schema-
|
|
1
|
+
import { t as resolveDdlSchemaForNamespaceStorage } from "./resolve-ddl-schema-Ca88Tg6W.mjs";
|
|
2
2
|
export { resolveDdlSchemaForNamespaceStorage };
|
package/dist/types.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as PostgresRlsPolicyInput, r as RlsPolicyOperation, t as PostgresRlsPolicy } from "./postgres-rls-policy--CSddvMR.mjs";
|
|
2
|
-
import { a as PostgresNamespaceSchemaNode, c as PostgresTableSchemaNode, d as PostgresPolicySchemaNodeInput, i as PostgresRoleSchemaNodeInput, l as PostgresTableSchemaNodeInput, n as PostgresDatabaseSchemaNodeInput, o as PostgresNamespaceSchemaNodeInput, r as PostgresRoleSchemaNode, s as PostgresNativeEnumIntrospection, t as PostgresDatabaseSchemaNode, u as PostgresPolicySchemaNode } from "./postgres-database-schema-node-
|
|
2
|
+
import { a as PostgresNamespaceSchemaNode, c as PostgresTableSchemaNode, d as PostgresPolicySchemaNodeInput, i as PostgresRoleSchemaNodeInput, l as PostgresTableSchemaNodeInput, n as PostgresDatabaseSchemaNodeInput, o as PostgresNamespaceSchemaNodeInput, r as PostgresRoleSchemaNode, s as PostgresNativeEnumIntrospection, t as PostgresDatabaseSchemaNode, u as PostgresPolicySchemaNode } from "./postgres-database-schema-node-CfdTY-Qs.mjs";
|
|
3
3
|
import { t as PostgresColumnDefault } from "./types-BDKkx8MA.mjs";
|
|
4
|
-
import { a as postgresCreateNamespace, c as
|
|
5
|
-
export { type PostgresColumnDefault, type PostgresContract, PostgresDatabaseSchemaNode, type PostgresDatabaseSchemaNodeInput, PostgresNamespaceSchemaNode, type PostgresNamespaceSchemaNodeInput, PostgresNativeEnum, type PostgresNativeEnumInput, type PostgresNativeEnumIntrospection, PostgresPolicySchemaNode, type PostgresPolicySchemaNodeInput, PostgresRlsPolicy, type PostgresRlsPolicyInput, PostgresRole, type PostgresRoleInput, PostgresRoleSchemaNode, type PostgresRoleSchemaNodeInput, PostgresSchema, PostgresTableSchemaNode, type PostgresTableSchemaNodeInput, PostgresUnboundSchema, type RlsPolicyOperation, isPostgresSchema, postgresCreateNamespace };
|
|
4
|
+
import { a as postgresCreateNamespace, c as PostgresRlsEnablement, d as PostgresRoleInput, i as isPostgresSchema, l as PostgresRlsEnablementInput, n as PostgresSchema, o as PostgresNativeEnum, r as PostgresUnboundSchema, s as PostgresNativeEnumInput, t as PostgresContract, u as PostgresRole } from "./postgres-schema-CU4gF6QZ.mjs";
|
|
5
|
+
export { type PostgresColumnDefault, type PostgresContract, PostgresDatabaseSchemaNode, type PostgresDatabaseSchemaNodeInput, PostgresNamespaceSchemaNode, type PostgresNamespaceSchemaNodeInput, PostgresNativeEnum, type PostgresNativeEnumInput, type PostgresNativeEnumIntrospection, PostgresPolicySchemaNode, type PostgresPolicySchemaNodeInput, PostgresRlsEnablement, type PostgresRlsEnablementInput, PostgresRlsPolicy, type PostgresRlsPolicyInput, PostgresRole, type PostgresRoleInput, PostgresRoleSchemaNode, type PostgresRoleSchemaNodeInput, PostgresSchema, PostgresTableSchemaNode, type PostgresTableSchemaNodeInput, PostgresUnboundSchema, type RlsPolicyOperation, isPostgresSchema, postgresCreateNamespace };
|
package/dist/types.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as PostgresNativeEnum } from "./postgres-native-enum-xdiqmBf_.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { g as PostgresRlsEnablement, h as PostgresRlsPolicy, i as postgresCreateNamespace, m as PostgresRole, n as PostgresUnboundSchema, r as isPostgresSchema, t as PostgresSchema } from "./postgres-schema-DTLA_aRi.mjs";
|
|
3
|
+
import { t as PostgresTableSchemaNode } from "./postgres-table-schema-node-9FCtCUz2.mjs";
|
|
4
|
+
import { i as PostgresDatabaseSchemaNode, n as PostgresPolicySchemaNode, r as PostgresNamespaceSchemaNode, t as PostgresRoleSchemaNode } from "./postgres-role-schema-node-BiSTCTNg.mjs";
|
|
5
|
+
export { PostgresDatabaseSchemaNode, PostgresNamespaceSchemaNode, PostgresNativeEnum, PostgresPolicySchemaNode, PostgresRlsEnablement, PostgresRlsPolicy, PostgresRole, PostgresRoleSchemaNode, PostgresSchema, PostgresTableSchemaNode, PostgresUnboundSchema, isPostgresSchema, postgresCreateNamespace };
|
|
@@ -41,6 +41,35 @@ function computeContentHash(parts) {
|
|
|
41
41
|
return createHash("sha256").update(tuple).digest("hex").slice(0, 8);
|
|
42
42
|
}
|
|
43
43
|
//#endregion
|
|
44
|
-
|
|
44
|
+
//#region src/core/rls/wire-name.ts
|
|
45
|
+
const WIRE_NAME_PATTERN = /^(.+)_([0-9a-f]{8})$/;
|
|
46
|
+
/**
|
|
47
|
+
* Assembles an RLS policy wire name from its user-supplied prefix and its
|
|
48
|
+
* 8-hex content-hash suffix. This module owns the `<prefix>_<hash>` format
|
|
49
|
+
* on both sides — construction here and parsing in
|
|
50
|
+
* {@link parseRlsPolicyWireName} — so the two never drift.
|
|
51
|
+
*/
|
|
52
|
+
function formatRlsPolicyWireName(prefix, hash) {
|
|
53
|
+
return `${prefix}_${hash}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Splits an RLS policy wire name (`<prefix>_<8hex>`) into its prefix and
|
|
57
|
+
* content-hash suffix. Returns `undefined` when the name does not follow the
|
|
58
|
+
* wire-name shape (e.g. a policy created outside the toolchain) — callers
|
|
59
|
+
* treat such names as all-prefix. Consumed by introspection (prefix
|
|
60
|
+
* extraction) and by rename pairing (same hash, different prefix).
|
|
61
|
+
*/
|
|
62
|
+
function parseRlsPolicyWireName(name) {
|
|
63
|
+
const match = WIRE_NAME_PATTERN.exec(name);
|
|
64
|
+
const prefix = match?.[1];
|
|
65
|
+
const hash = match?.[2];
|
|
66
|
+
if (prefix === void 0 || hash === void 0) return void 0;
|
|
67
|
+
return {
|
|
68
|
+
prefix,
|
|
69
|
+
hash
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { normalizePredicate as i, parseRlsPolicyWireName as n, computeContentHash as r, formatRlsPolicyWireName as t };
|
|
45
74
|
|
|
46
|
-
//# sourceMappingURL=
|
|
75
|
+
//# sourceMappingURL=wire-name-rHHtr1h0.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-name-rHHtr1h0.mjs","names":[],"sources":["../src/core/rls/canonicalize.ts","../src/core/rls/wire-name.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nexport type RlsPolicyOperation = 'select' | 'insert' | 'update' | 'delete' | 'all';\n\nexport interface ContentHashParts {\n readonly using?: string;\n readonly withCheck?: string;\n readonly roles: readonly string[];\n readonly operation: RlsPolicyOperation;\n readonly permissive: boolean;\n}\n\n/**\n * Stabilizes an authored predicate for hashing: trim, and collapse runs of\n * internal whitespace to a single space.\n *\n * This is deliberately minimal. The content hash is the equivalence relation\n * for a policy, and the wire name (prefix + hash) is the only thing ever\n * compared — we never recompute the hash from an introspected policy body, so\n * there is no need to match Postgres's reprinted form. Minimal normalization\n * also protects the no-collision property: aggressive rewriting (lowercasing,\n * paren-stripping, cast-alias folding) risks collapsing two distinct predicates\n * onto one hash. Out-of-band alteration of a hashed policy is unsupported.\n *\n * The normalizer is a stability commitment: any change re-suffixes all wire names.\n */\nexport function normalizePredicate(sql: string): string {\n return sql.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Returns the first 8 lowercase hex characters of the SHA-256 digest over the\n * canonical content tuple for an RLS policy:\n *\n * [normalize(using), normalize(withCheck), sortedRoles, operation, permissive]\n *\n * Schema and table are excluded (they are orthogonal to policy equivalence).\n * Uses `JSON.stringify` for a deterministic encoding.\n */\nexport function computeContentHash(parts: ContentHashParts): string {\n const using = normalizePredicate(parts.using ?? '');\n const withCheck = normalizePredicate(parts.withCheck ?? '');\n const roles = [...new Set(parts.roles)].sort();\n const permissive = parts.permissive ? 'permissive' : 'restrictive';\n\n const tuple = JSON.stringify([using, withCheck, roles, parts.operation, permissive]);\n return createHash('sha256').update(tuple).digest('hex').slice(0, 8);\n}\n","export interface RlsPolicyWireName {\n /** The user-supplied part before the `_<8hex>` suffix. */\n readonly prefix: string;\n /** The 8-lowercase-hex content-hash suffix. */\n readonly hash: string;\n}\n\nconst WIRE_NAME_PATTERN = /^(.+)_([0-9a-f]{8})$/;\n\n/**\n * Assembles an RLS policy wire name from its user-supplied prefix and its\n * 8-hex content-hash suffix. This module owns the `<prefix>_<hash>` format\n * on both sides — construction here and parsing in\n * {@link parseRlsPolicyWireName} — so the two never drift.\n */\nexport function formatRlsPolicyWireName(prefix: string, hash: string): string {\n return `${prefix}_${hash}`;\n}\n\n/**\n * Splits an RLS policy wire name (`<prefix>_<8hex>`) into its prefix and\n * content-hash suffix. Returns `undefined` when the name does not follow the\n * wire-name shape (e.g. a policy created outside the toolchain) — callers\n * treat such names as all-prefix. Consumed by introspection (prefix\n * extraction) and by rename pairing (same hash, different prefix).\n */\nexport function parseRlsPolicyWireName(name: string): RlsPolicyWireName | undefined {\n const match = WIRE_NAME_PATTERN.exec(name);\n const prefix = match?.[1];\n const hash = match?.[2];\n if (prefix === undefined || hash === undefined) return undefined;\n return { prefix, hash };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,SAAgB,mBAAmB,KAAqB;CACtD,OAAO,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AACvC;;;;;;;;;;AAWA,SAAgB,mBAAmB,OAAiC;CAClE,MAAM,QAAQ,mBAAmB,MAAM,SAAS,EAAE;CAClD,MAAM,YAAY,mBAAmB,MAAM,aAAa,EAAE;CAC1D,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK;CAC7C,MAAM,aAAa,MAAM,aAAa,eAAe;CAErD,MAAM,QAAQ,KAAK,UAAU;EAAC;EAAO;EAAW;EAAO,MAAM;EAAW;CAAU,CAAC;CACnF,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;AACpE;;;ACxCA,MAAM,oBAAoB;;;;;;;AAQ1B,SAAgB,wBAAwB,QAAgB,MAAsB;CAC5E,OAAO,GAAG,OAAO,GAAG;AACtB;;;;;;;;AASA,SAAgB,uBAAuB,MAA6C;CAClF,MAAM,QAAQ,kBAAkB,KAAK,IAAI;CACzC,MAAM,SAAS,QAAQ;CACvB,MAAM,OAAO,QAAQ;CACrB,IAAI,WAAW,KAAA,KAAa,SAAS,KAAA,GAAW,OAAO,KAAA;CACvD,OAAO;EAAE;EAAQ;CAAK;AACxB"}
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/target-postgres",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.57",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Postgres target pack for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/cli": "0.14.0-dev.
|
|
10
|
-
"@prisma-next/contract": "0.14.0-dev.
|
|
11
|
-
"@prisma-next/errors": "0.14.0-dev.
|
|
12
|
-
"@prisma-next/family-sql": "0.14.0-dev.
|
|
13
|
-
"@prisma-next/framework-components": "0.14.0-dev.
|
|
14
|
-
"@prisma-next/migration-tools": "0.14.0-dev.
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/sql-
|
|
17
|
-
"@prisma-next/sql-
|
|
18
|
-
"@prisma-next/sql-
|
|
19
|
-
"@prisma-next/sql-
|
|
20
|
-
"@prisma-next/
|
|
21
|
-
"@prisma-next/
|
|
9
|
+
"@prisma-next/cli": "0.14.0-dev.57",
|
|
10
|
+
"@prisma-next/contract": "0.14.0-dev.57",
|
|
11
|
+
"@prisma-next/errors": "0.14.0-dev.57",
|
|
12
|
+
"@prisma-next/family-sql": "0.14.0-dev.57",
|
|
13
|
+
"@prisma-next/framework-components": "0.14.0-dev.57",
|
|
14
|
+
"@prisma-next/migration-tools": "0.14.0-dev.57",
|
|
15
|
+
"@prisma-next/psl-parser": "0.14.0-dev.57",
|
|
16
|
+
"@prisma-next/sql-contract": "0.14.0-dev.57",
|
|
17
|
+
"@prisma-next/sql-errors": "0.14.0-dev.57",
|
|
18
|
+
"@prisma-next/sql-operations": "0.14.0-dev.57",
|
|
19
|
+
"@prisma-next/sql-relational-core": "0.14.0-dev.57",
|
|
20
|
+
"@prisma-next/sql-schema-ir": "0.14.0-dev.57",
|
|
21
|
+
"@prisma-next/ts-render": "0.14.0-dev.57",
|
|
22
|
+
"@prisma-next/utils": "0.14.0-dev.57",
|
|
22
23
|
"@standard-schema/spec": "^1.1.0",
|
|
23
24
|
"arktype": "^2.2.0",
|
|
24
25
|
"pathe": "^2.0.3"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
|
-
"@prisma-next/psl-
|
|
28
|
-
"@prisma-next/psl
|
|
29
|
-
"@prisma-next/
|
|
30
|
-
"@prisma-next/
|
|
31
|
-
"@prisma-next/
|
|
32
|
-
"@prisma-next/tsdown": "0.14.0-dev.55",
|
|
28
|
+
"@prisma-next/psl-printer": "0.14.0-dev.57",
|
|
29
|
+
"@prisma-next/sql-contract-psl": "0.14.0-dev.57",
|
|
30
|
+
"@prisma-next/test-utils": "0.14.0-dev.57",
|
|
31
|
+
"@prisma-next/tsconfig": "0.14.0-dev.57",
|
|
32
|
+
"@prisma-next/tsdown": "0.14.0-dev.57",
|
|
33
33
|
"tsdown": "0.22.1",
|
|
34
34
|
"typescript": "5.9.3",
|
|
35
35
|
"vitest": "4.1.8"
|
package/src/contract-free/ddl.ts
CHANGED
|
@@ -3,10 +3,12 @@ import {
|
|
|
3
3
|
AddColumnAction,
|
|
4
4
|
type AnyAlterTableAction,
|
|
5
5
|
DropDefaultAction,
|
|
6
|
+
PostgresAlterPolicyRename,
|
|
6
7
|
PostgresAlterTable,
|
|
7
8
|
PostgresCreatePolicy,
|
|
8
9
|
PostgresCreateSchema,
|
|
9
10
|
PostgresCreateTable,
|
|
11
|
+
PostgresDisableRowLevelSecurity,
|
|
10
12
|
PostgresDropPolicy,
|
|
11
13
|
type RlsPolicyOperation,
|
|
12
14
|
} from '../core/ddl/nodes';
|
|
@@ -106,3 +108,27 @@ export function dropPolicy(options: {
|
|
|
106
108
|
}): PostgresDropPolicy {
|
|
107
109
|
return new PostgresDropPolicy(options);
|
|
108
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Build a Postgres `ALTER POLICY … RENAME TO` DDL node.
|
|
114
|
+
* Identifiers (`schema`, `table`, `name`, `newName`) are quoted by the renderer.
|
|
115
|
+
*/
|
|
116
|
+
export function alterPolicyRename(options: {
|
|
117
|
+
readonly schema: string;
|
|
118
|
+
readonly table: string;
|
|
119
|
+
readonly name: string;
|
|
120
|
+
readonly newName: string;
|
|
121
|
+
}): PostgresAlterPolicyRename {
|
|
122
|
+
return new PostgresAlterPolicyRename(options);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Build a Postgres `ALTER TABLE … DISABLE ROW LEVEL SECURITY` DDL node.
|
|
127
|
+
* Identifiers (`schema`, `table`) are quoted by the renderer.
|
|
128
|
+
*/
|
|
129
|
+
export function disableRowLevelSecurity(options: {
|
|
130
|
+
readonly schema: string;
|
|
131
|
+
readonly table: string;
|
|
132
|
+
}): PostgresDisableRowLevelSecurity {
|
|
133
|
+
return new PostgresDisableRowLevelSecurity(options);
|
|
134
|
+
}
|
package/src/core/authoring.ts
CHANGED
|
@@ -4,21 +4,27 @@ import type {
|
|
|
4
4
|
AuthoringEntityTypeFactoryOutput,
|
|
5
5
|
AuthoringEntityTypeNamespace,
|
|
6
6
|
AuthoringFieldNamespace,
|
|
7
|
+
AuthoringModelAttributeContext,
|
|
8
|
+
AuthoringModelAttributeDescriptorNamespace,
|
|
7
9
|
AuthoringPslBlockDescriptorNamespace,
|
|
8
10
|
AuthoringTypeNamespace,
|
|
9
11
|
PslExtensionBlock,
|
|
10
12
|
} from '@prisma-next/framework-components/authoring';
|
|
13
|
+
import { modelAttribute } from '@prisma-next/psl-parser';
|
|
11
14
|
import type { SqlValueSetDerivingEntityTypeOutput } from '@prisma-next/sql-contract/value-set-derivation-hook';
|
|
12
15
|
import { PG_ENUM_CODEC_ID } from './codec-ids';
|
|
13
16
|
import { PostgresNativeEnum } from './postgres-native-enum';
|
|
17
|
+
import { PostgresRlsEnablement, type PostgresRlsEnablementInput } from './postgres-rls-enablement';
|
|
14
18
|
import { PostgresRlsPolicy } from './postgres-rls-policy';
|
|
15
19
|
import { PostgresRole, type PostgresRoleInput } from './postgres-role';
|
|
16
20
|
import {
|
|
17
21
|
PostgresNativeEnumSchema,
|
|
22
|
+
PostgresRlsEnablementSchema,
|
|
18
23
|
PostgresRlsPolicySchema,
|
|
19
24
|
PostgresRoleSchema,
|
|
20
25
|
} from './postgres-validators';
|
|
21
26
|
import { computeContentHash, normalizePredicate } from './rls/canonicalize';
|
|
27
|
+
import { formatRlsPolicyWireName } from './rls/wire-name';
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* `pg.enum(<ref>)` registers as an ordinary type constructor whose sole
|
|
@@ -109,7 +115,7 @@ function lowerRlsPolicyFromBlock(
|
|
|
109
115
|
operation: 'select',
|
|
110
116
|
permissive: true,
|
|
111
117
|
});
|
|
112
|
-
const wireName =
|
|
118
|
+
const wireName = formatRlsPolicyWireName(prefix, wireHash);
|
|
113
119
|
|
|
114
120
|
return new PostgresRlsPolicy({
|
|
115
121
|
name: wireName,
|
|
@@ -253,6 +259,15 @@ export const postgresAuthoringEntityTypes = {
|
|
|
253
259
|
factory: (input: PostgresRoleInput): PostgresRole => new PostgresRole(input),
|
|
254
260
|
},
|
|
255
261
|
},
|
|
262
|
+
rls: {
|
|
263
|
+
kind: 'entity',
|
|
264
|
+
discriminator: 'rls',
|
|
265
|
+
validatorSchema: PostgresRlsEnablementSchema,
|
|
266
|
+
output: {
|
|
267
|
+
factory: (input: PostgresRlsEnablementInput): PostgresRlsEnablement =>
|
|
268
|
+
new PostgresRlsEnablement(input),
|
|
269
|
+
},
|
|
270
|
+
},
|
|
256
271
|
policy: {
|
|
257
272
|
kind: 'entity',
|
|
258
273
|
discriminator: 'policy',
|
|
@@ -312,6 +327,10 @@ export const postgresAuthoringPslBlockDescriptors = {
|
|
|
312
327
|
},
|
|
313
328
|
using: { kind: 'value', codecId: 'pg/text@1', required: true },
|
|
314
329
|
},
|
|
330
|
+
// A policy may only target an RLS-controlled model: the model named by
|
|
331
|
+
// `target` must declare `@@rls`, or the load fails with a diagnostic
|
|
332
|
+
// naming the model and the policy prefix.
|
|
333
|
+
requiresModelAttribute: { parameter: 'target', attribute: 'rls' },
|
|
315
334
|
},
|
|
316
335
|
/**
|
|
317
336
|
* PSL block descriptor for `native_enum`.
|
|
@@ -333,6 +352,30 @@ export const postgresAuthoringPslBlockDescriptors = {
|
|
|
333
352
|
},
|
|
334
353
|
} as const satisfies AuthoringPslBlockDescriptorNamespace;
|
|
335
354
|
|
|
355
|
+
/**
|
|
356
|
+
* `@@` model attributes contributed by the Postgres target pack.
|
|
357
|
+
*
|
|
358
|
+
* `@@rls` is argument-less: presence marks the model's table
|
|
359
|
+
* RLS-controlled. It lowers to a {@link PostgresRlsEnablement} marker in
|
|
360
|
+
* the namespace's `entries.rls`, keyed by the model's table name — the
|
|
361
|
+
* marker (never the policy set) is what drives
|
|
362
|
+
* `ENABLE`/`DISABLE ROW LEVEL SECURITY` planning.
|
|
363
|
+
*/
|
|
364
|
+
export const postgresAuthoringModelAttributes = {
|
|
365
|
+
rls: {
|
|
366
|
+
kind: 'modelAttribute',
|
|
367
|
+
attribute: 'rls',
|
|
368
|
+
spec: modelAttribute('rls', {}),
|
|
369
|
+
lower: (_parsed: Record<never, never>, ctx: AuthoringModelAttributeContext) => ({
|
|
370
|
+
key: ctx.storageName,
|
|
371
|
+
entity: new PostgresRlsEnablement({
|
|
372
|
+
tableName: ctx.storageName,
|
|
373
|
+
namespaceId: ctx.namespaceId,
|
|
374
|
+
}),
|
|
375
|
+
}),
|
|
376
|
+
},
|
|
377
|
+
} as const satisfies AuthoringModelAttributeDescriptorNamespace;
|
|
378
|
+
|
|
336
379
|
export const postgresAuthoringFieldPresets = {
|
|
337
380
|
text: {
|
|
338
381
|
kind: 'fieldPreset',
|
package/src/core/ddl/nodes.ts
CHANGED
|
@@ -70,6 +70,8 @@ export interface PostgresDdlVisitor<R> {
|
|
|
70
70
|
alterTable(node: PostgresAlterTable): R;
|
|
71
71
|
createPolicy(node: PostgresCreatePolicy): R;
|
|
72
72
|
dropPolicy(node: PostgresDropPolicy): R;
|
|
73
|
+
alterPolicyRename(node: PostgresAlterPolicyRename): R;
|
|
74
|
+
disableRowLevelSecurity(node: PostgresDisableRowLevelSecurity): R;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
export abstract class PostgresDdlNode extends DdlNode {
|
|
@@ -214,9 +216,54 @@ export class PostgresDropPolicy extends PostgresDdlNode {
|
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
218
|
|
|
219
|
+
export class PostgresAlterPolicyRename extends PostgresDdlNode {
|
|
220
|
+
readonly kind = 'alter-policy-rename' as const;
|
|
221
|
+
readonly schema: string;
|
|
222
|
+
readonly table: string;
|
|
223
|
+
readonly name: string;
|
|
224
|
+
readonly newName: string;
|
|
225
|
+
|
|
226
|
+
constructor(options: {
|
|
227
|
+
readonly schema: string;
|
|
228
|
+
readonly table: string;
|
|
229
|
+
readonly name: string;
|
|
230
|
+
readonly newName: string;
|
|
231
|
+
}) {
|
|
232
|
+
super();
|
|
233
|
+
this.schema = options.schema;
|
|
234
|
+
this.table = options.table;
|
|
235
|
+
this.name = options.name;
|
|
236
|
+
this.newName = options.newName;
|
|
237
|
+
this.freeze();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
241
|
+
return visitor.alterPolicyRename(this);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export class PostgresDisableRowLevelSecurity extends PostgresDdlNode {
|
|
246
|
+
readonly kind = 'disable-row-level-security' as const;
|
|
247
|
+
readonly schema: string;
|
|
248
|
+
readonly table: string;
|
|
249
|
+
|
|
250
|
+
constructor(options: { readonly schema: string; readonly table: string }) {
|
|
251
|
+
super();
|
|
252
|
+
this.schema = options.schema;
|
|
253
|
+
this.table = options.table;
|
|
254
|
+
this.freeze();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
258
|
+
return visitor.disableRowLevelSecurity(this);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
217
262
|
export type AnyPostgresDdlNode =
|
|
218
263
|
| PostgresCreateTable
|
|
219
264
|
| PostgresCreateSchema
|
|
220
265
|
| PostgresAlterTable
|
|
221
266
|
| PostgresCreatePolicy
|
|
222
|
-
| PostgresDropPolicy
|
|
267
|
+
| PostgresDropPolicy
|
|
268
|
+
| PostgresAlterPolicyRename
|
|
269
|
+
| PostgresDisableRowLevelSecurity;
|
|
@@ -2,6 +2,7 @@ import type { CodecTypes } from '../exports/codec-types';
|
|
|
2
2
|
import {
|
|
3
3
|
postgresAuthoringEntityTypes,
|
|
4
4
|
postgresAuthoringFieldPresets,
|
|
5
|
+
postgresAuthoringModelAttributes,
|
|
5
6
|
postgresAuthoringPslBlockDescriptors,
|
|
6
7
|
postgresAuthoringTypes,
|
|
7
8
|
} from './authoring';
|
|
@@ -18,6 +19,7 @@ const postgresTargetDescriptorMetaBase = {
|
|
|
18
19
|
field: postgresAuthoringFieldPresets,
|
|
19
20
|
entityTypes: postgresAuthoringEntityTypes,
|
|
20
21
|
pslBlockDescriptors: postgresAuthoringPslBlockDescriptors,
|
|
22
|
+
modelAttributes: postgresAuthoringModelAttributes,
|
|
21
23
|
createNamespace: postgresCreateNamespace,
|
|
22
24
|
qualifyColumnType: postgresQualifyColumnType,
|
|
23
25
|
},
|
package/src/core/entity-kinds.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { EntityKindDescriptor } from '@prisma-next/framework-components/ir';
|
|
2
2
|
import { PostgresNativeEnum, type PostgresNativeEnumInput } from './postgres-native-enum';
|
|
3
|
+
import { PostgresRlsEnablement, type PostgresRlsEnablementInput } from './postgres-rls-enablement';
|
|
3
4
|
import { PostgresRlsPolicy, type PostgresRlsPolicyInput } from './postgres-rls-policy';
|
|
4
5
|
import { PostgresRole, type PostgresRoleInput } from './postgres-role';
|
|
5
6
|
import {
|
|
6
7
|
PostgresNativeEnumSchema,
|
|
8
|
+
PostgresRlsEnablementSchema,
|
|
7
9
|
PostgresRlsPolicySchema,
|
|
8
10
|
PostgresRoleSchema,
|
|
9
11
|
} from './postgres-validators';
|
|
@@ -20,6 +22,15 @@ export const roleEntityKind: EntityKindDescriptor<PostgresRoleInput, PostgresRol
|
|
|
20
22
|
construct: (input) => new PostgresRole(input),
|
|
21
23
|
};
|
|
22
24
|
|
|
25
|
+
export const rlsEnablementEntityKind: EntityKindDescriptor<
|
|
26
|
+
PostgresRlsEnablementInput,
|
|
27
|
+
PostgresRlsEnablement
|
|
28
|
+
> = {
|
|
29
|
+
kind: 'rls',
|
|
30
|
+
schema: PostgresRlsEnablementSchema,
|
|
31
|
+
construct: (input) => new PostgresRlsEnablement(input),
|
|
32
|
+
};
|
|
33
|
+
|
|
23
34
|
export const nativeEnumEntityKind: EntityKindDescriptor<
|
|
24
35
|
PostgresNativeEnumInput,
|
|
25
36
|
PostgresNativeEnum
|
|
@@ -117,6 +117,9 @@ export function contractToPostgresDatabaseSchemaNode(
|
|
|
117
117
|
...ifDefined('annotations', sqlTable.annotations),
|
|
118
118
|
...ifDefined('checks', sqlTable.checks),
|
|
119
119
|
policies: policiesByTable.get(tableName) ?? [],
|
|
120
|
+
// Marker-driven, never derived from the policy set: the `rls` entry
|
|
121
|
+
// is the single authored source of enablement.
|
|
122
|
+
rlsEnabled: Object.hasOwn(ns.rls, tableName),
|
|
120
123
|
});
|
|
121
124
|
}
|
|
122
125
|
|
|
@@ -127,6 +130,12 @@ export function contractToPostgresDatabaseSchemaNode(
|
|
|
127
130
|
`contract-to-postgres-database-schema-node: policy "${policyName}" references table "${tableName}" not present in namespace "${ddlSchema}"`,
|
|
128
131
|
);
|
|
129
132
|
}
|
|
133
|
+
if (!Object.hasOwn(ns.rls, tableName)) {
|
|
134
|
+
const policyPrefix = tablePolicies[0]?.prefix ?? '(unknown)';
|
|
135
|
+
throw new Error(
|
|
136
|
+
`contract-to-postgres-database-schema-node: policy "${policyPrefix}" targets table "${tableName}" in namespace "${ddlSchema}", which is not RLS-controlled. Mark the model with @@rls (entries.rls["${tableName}"]) or remove the policy.`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
130
139
|
}
|
|
131
140
|
|
|
132
141
|
namespaces[ddlSchema] = new PostgresNamespaceSchemaNode({
|
|
@@ -7,6 +7,7 @@ import { blindCast } from '@prisma-next/utils/casts';
|
|
|
7
7
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
8
8
|
import { isPostgresSchema } from '../postgres-schema';
|
|
9
9
|
import type { PostgresNamespaceSchemaNode } from '../schema-ir/postgres-namespace-schema-node';
|
|
10
|
+
import { PostgresTableSchemaNode } from '../schema-ir/postgres-table-schema-node';
|
|
10
11
|
import type { SqlSchemaDiffNode } from '../schema-ir/schema-node-kinds';
|
|
11
12
|
import { PostgresSchemaNodeKind } from '../schema-ir/schema-node-kinds';
|
|
12
13
|
import { issueColumnName } from './issue-planner';
|
|
@@ -163,9 +164,37 @@ const POSTGRES_NODE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.
|
|
|
163
164
|
[PostgresSchemaNodeKind.table]: 'createTable',
|
|
164
165
|
});
|
|
165
166
|
|
|
167
|
+
/**
|
|
168
|
+
* A table `not-equal` issue whose `rlsEnabled` flips OFF→ON (expected on,
|
|
169
|
+
* actual off) is enablement toward `ENABLE ROW LEVEL SECURITY` —
|
|
170
|
+
* creation-class per `OBJECT_CREATION_FACTORIES` ('enableRowLevelSecurity'
|
|
171
|
+
* is a member): enabling RLS establishes the fail-closed guard the declared
|
|
172
|
+
* policy set attaches to, the same grant `tolerated` extends to creating the
|
|
173
|
+
* policies themselves. The opposite direction (`DISABLE`) is a modification
|
|
174
|
+
* and stays managed-only. Keying on the actual delta (not just the expected
|
|
175
|
+
* bit) keeps this correct if a second table attribute ever joins
|
|
176
|
+
* `isEqualTo`: a not-equal with no `rlsEnabled` delta is not enablement, so
|
|
177
|
+
* it is not admitted as creation-class here.
|
|
178
|
+
*/
|
|
179
|
+
function isEnablementCreationIssue(issue: SchemaDiffIssue<SqlSchemaDiffNode>): boolean {
|
|
180
|
+
if (issue.reason !== 'not-equal') return false;
|
|
181
|
+
const { expected, actual } = issue;
|
|
182
|
+
return (
|
|
183
|
+
expected !== undefined &&
|
|
184
|
+
actual !== undefined &&
|
|
185
|
+
PostgresTableSchemaNode.is(expected) &&
|
|
186
|
+
PostgresTableSchemaNode.is(actual) &&
|
|
187
|
+
expected.rlsEnabled === true &&
|
|
188
|
+
actual.rlsEnabled === false
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
166
192
|
export function resolvePostgresNodeIssueCreationFactoryName(
|
|
167
193
|
issue: SchemaDiffIssue<SqlSchemaDiffNode>,
|
|
168
194
|
): string | undefined {
|
|
195
|
+
if (isEnablementCreationIssue(issue)) {
|
|
196
|
+
return 'enableRowLevelSecurity';
|
|
197
|
+
}
|
|
169
198
|
if (issue.reason !== 'not-found') return undefined;
|
|
170
199
|
const node = issue.expected ?? issue.actual;
|
|
171
200
|
if (node === undefined) return undefined;
|
|
@@ -215,7 +244,8 @@ export function resolvePostgresNodeIssueControlPolicySubject(
|
|
|
215
244
|
entityName: tableName,
|
|
216
245
|
});
|
|
217
246
|
const createsNewObject =
|
|
218
|
-
node.nodeKind === PostgresSchemaNodeKind.table && issue.reason === 'not-found'
|
|
247
|
+
(node.nodeKind === PostgresSchemaNodeKind.table && issue.reason === 'not-found') ||
|
|
248
|
+
isEnablementCreationIssue(issue);
|
|
219
249
|
|
|
220
250
|
return {
|
|
221
251
|
namespaceId,
|
|
@@ -70,6 +70,7 @@ export function normalizePostgresActualForDiff(
|
|
|
70
70
|
...ifDefined('annotations', actualTable.annotations),
|
|
71
71
|
...ifDefined('checks', actualTable.checks),
|
|
72
72
|
policies: [...actualTable.policies],
|
|
73
|
+
rlsEnabled: actualTable.rlsEnabled,
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
namespaces[nsId] = new PostgresNamespaceSchemaNode({
|