@prisma-next/target-postgres 0.14.0-dev.55 → 0.14.0-dev.56

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.
Files changed (117) hide show
  1. package/dist/{authoring-BBIGcFZM.mjs → authoring-WkqG_MkU.mjs} +38 -6
  2. package/dist/authoring-WkqG_MkU.mjs.map +1 -0
  3. package/dist/contract-free.d.mts +27 -2
  4. package/dist/contract-free.d.mts.map +1 -1
  5. package/dist/contract-free.mjs +3 -3
  6. package/dist/{control-policy-DievMCOV.mjs → control-policy-BtOZBVxL.mjs} +38 -13
  7. package/dist/control-policy-BtOZBVxL.mjs.map +1 -0
  8. package/dist/control.mjs +6 -6
  9. package/dist/{ddl-D5j4JiAB.mjs → ddl-B-krEXY1.mjs} +18 -4
  10. package/dist/{ddl-D5j4JiAB.mjs.map → ddl-B-krEXY1.mjs.map} +1 -1
  11. package/dist/ddl.d.mts +2 -2
  12. package/dist/ddl.mjs +2 -2
  13. package/dist/{descriptor-meta-C-tyS25s.mjs → descriptor-meta-BOcKPaLE.mjs} +4 -3
  14. package/dist/descriptor-meta-BOcKPaLE.mjs.map +1 -0
  15. package/dist/{diff-database-schema-ff3ioNtK.mjs → diff-database-schema-CWb-jeLy.mjs} +19 -11
  16. package/dist/diff-database-schema-CWb-jeLy.mjs.map +1 -0
  17. package/dist/diff-database-schema.d.mts +1 -1
  18. package/dist/diff-database-schema.d.mts.map +1 -1
  19. package/dist/diff-database-schema.mjs +1 -1
  20. package/dist/issue-planner.d.mts +1 -1
  21. package/dist/issue-planner.d.mts.map +1 -1
  22. package/dist/issue-planner.mjs +1 -1
  23. package/dist/migration.d.mts +2 -2
  24. package/dist/migration.mjs +2 -2
  25. package/dist/{nodes-Dh__NS58.mjs → nodes-B815pj_X.mjs} +34 -2
  26. package/dist/{nodes-Dh__NS58.mjs.map → nodes-B815pj_X.mjs.map} +1 -1
  27. package/dist/{nodes-CSkPX3rI.d.mts → nodes-BtQyZha6.d.mts} +29 -3
  28. package/dist/nodes-BtQyZha6.d.mts.map +1 -0
  29. package/dist/{op-factory-call-Dt-Jx5JS.d.mts → op-factory-call-D6_7-7Vc.d.mts} +24 -2
  30. package/dist/{op-factory-call-Dt-Jx5JS.d.mts.map → op-factory-call-D6_7-7Vc.d.mts.map} +1 -1
  31. package/dist/{op-factory-call-DZWTTjKM.mjs → op-factory-call-DxNNKUeZ.mjs} +99 -4
  32. package/dist/op-factory-call-DxNNKUeZ.mjs.map +1 -0
  33. package/dist/op-factory-call.d.mts +1 -1
  34. package/dist/op-factory-call.mjs +1 -1
  35. package/dist/pack.d.mts +29 -2
  36. package/dist/pack.d.mts.map +1 -1
  37. package/dist/pack.mjs +1 -1
  38. package/dist/{planner-DWQYPxP8.mjs → planner-BryLk0Ie.mjs} +80 -24
  39. package/dist/planner-BryLk0Ie.mjs.map +1 -0
  40. package/dist/{planner-produced-postgres-migration-Ch1L8RiV.mjs → planner-produced-postgres-migration-BLJH1zIc.mjs} +2 -2
  41. package/dist/{planner-produced-postgres-migration-Ch1L8RiV.mjs.map → planner-produced-postgres-migration-BLJH1zIc.mjs.map} +1 -1
  42. package/dist/{planner-produced-postgres-migration-C0a7I1-e.d.mts → planner-produced-postgres-migration-CGifB6VH.d.mts} +2 -2
  43. package/dist/{planner-produced-postgres-migration-C0a7I1-e.d.mts.map → planner-produced-postgres-migration-CGifB6VH.d.mts.map} +1 -1
  44. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  45. package/dist/planner-produced-postgres-migration.mjs +1 -1
  46. package/dist/{planner-sql-checks-D8Q5ck4o.mjs → planner-sql-checks-AXoxB1Jl.mjs} +2 -2
  47. package/dist/{planner-sql-checks-D8Q5ck4o.mjs.map → planner-sql-checks-AXoxB1Jl.mjs.map} +1 -1
  48. package/dist/planner-sql-checks.mjs +1 -1
  49. package/dist/planner.d.mts +23 -6
  50. package/dist/planner.d.mts.map +1 -1
  51. package/dist/planner.mjs +2 -2
  52. package/dist/{postgres-contract-view-C-By7rOB.mjs → postgres-contract-view-Dg-N7KA7.mjs} +4 -3
  53. package/dist/postgres-contract-view-Dg-N7KA7.mjs.map +1 -0
  54. package/dist/{postgres-database-schema-node-UpzA0Ug5.d.mts → postgres-database-schema-node-CfdTY-Qs.d.mts} +18 -3
  55. package/dist/postgres-database-schema-node-CfdTY-Qs.d.mts.map +1 -0
  56. package/dist/{postgres-migration-D3XACWKM.mjs → postgres-migration-BahMHTbj.mjs} +3 -3
  57. package/dist/{postgres-migration-D3XACWKM.mjs.map → postgres-migration-BahMHTbj.mjs.map} +1 -1
  58. package/dist/{postgres-migration-DFaxuRyI.d.mts → postgres-migration-cyBe2Ee0.d.mts} +2 -2
  59. package/dist/{postgres-migration-DFaxuRyI.d.mts.map → postgres-migration-cyBe2Ee0.d.mts.map} +1 -1
  60. package/dist/{postgres-table-schema-node-BZWWEo7B.mjs → postgres-role-schema-node-BiSTCTNg.mjs} +4 -69
  61. package/dist/postgres-role-schema-node-BiSTCTNg.mjs.map +1 -0
  62. package/dist/{postgres-schema-9vFZLwGo.d.mts → postgres-schema-CU4gF6QZ.d.mts} +30 -2
  63. package/dist/postgres-schema-CU4gF6QZ.d.mts.map +1 -0
  64. package/dist/{postgres-schema-DcG72fcT.mjs → postgres-schema-DTLA_aRi.mjs} +41 -2
  65. package/dist/postgres-schema-DTLA_aRi.mjs.map +1 -0
  66. package/dist/postgres-table-schema-node-9FCtCUz2.mjs +153 -0
  67. package/dist/postgres-table-schema-node-9FCtCUz2.mjs.map +1 -0
  68. package/dist/{resolve-ddl-schema-BOtCoeKV.mjs → resolve-ddl-schema-Ca88Tg6W.mjs} +2 -2
  69. package/dist/{resolve-ddl-schema-BOtCoeKV.mjs.map → resolve-ddl-schema-Ca88Tg6W.mjs.map} +1 -1
  70. package/dist/rls-canonicalize.d.mts +19 -1
  71. package/dist/rls-canonicalize.d.mts.map +1 -0
  72. package/dist/rls-canonicalize.mjs +2 -2
  73. package/dist/runtime.d.mts.map +1 -1
  74. package/dist/runtime.mjs +1 -1
  75. package/dist/schema-ir-annotations.mjs +1 -1
  76. package/dist/types.d.mts +3 -3
  77. package/dist/types.mjs +4 -3
  78. package/dist/{canonicalize-Bn3BM1Cn.mjs → wire-name-rHHtr1h0.mjs} +31 -2
  79. package/dist/wire-name-rHHtr1h0.mjs.map +1 -0
  80. package/package.json +20 -20
  81. package/src/contract-free/ddl.ts +26 -0
  82. package/src/core/authoring.ts +44 -1
  83. package/src/core/ddl/nodes.ts +48 -1
  84. package/src/core/descriptor-meta.ts +2 -0
  85. package/src/core/entity-kinds.ts +11 -0
  86. package/src/core/migrations/contract-to-postgres-database-schema-node.ts +9 -0
  87. package/src/core/migrations/control-policy.ts +31 -1
  88. package/src/core/migrations/diff-database-schema.ts +1 -0
  89. package/src/core/migrations/issue-planner.ts +49 -4
  90. package/src/core/migrations/op-factory-call.ts +81 -1
  91. package/src/core/migrations/operations/rls.ts +82 -1
  92. package/src/core/migrations/planner.ts +110 -26
  93. package/src/core/postgres-contract-serializer.ts +7 -1
  94. package/src/core/postgres-rls-enablement.ts +34 -0
  95. package/src/core/postgres-schema.ts +19 -3
  96. package/src/core/postgres-validators.ts +6 -0
  97. package/src/core/rls/wire-name.ts +33 -0
  98. package/src/core/schema-ir/postgres-table-schema-node.ts +25 -3
  99. package/src/exports/contract-free.ts +4 -0
  100. package/src/exports/ddl.ts +2 -0
  101. package/src/exports/rls-canonicalize.ts +1 -0
  102. package/src/exports/types.ts +4 -0
  103. package/dist/authoring-BBIGcFZM.mjs.map +0 -1
  104. package/dist/canonicalize-Bn3BM1Cn.mjs.map +0 -1
  105. package/dist/control-policy-DievMCOV.mjs.map +0 -1
  106. package/dist/descriptor-meta-C-tyS25s.mjs.map +0 -1
  107. package/dist/diff-database-schema-ff3ioNtK.mjs.map +0 -1
  108. package/dist/nodes-CSkPX3rI.d.mts.map +0 -1
  109. package/dist/op-factory-call-DZWTTjKM.mjs.map +0 -1
  110. package/dist/planner-DWQYPxP8.mjs.map +0 -1
  111. package/dist/postgres-contract-view-C-By7rOB.mjs.map +0 -1
  112. package/dist/postgres-database-schema-node-UpzA0Ug5.d.mts.map +0 -1
  113. package/dist/postgres-schema-9vFZLwGo.d.mts.map +0 -1
  114. package/dist/postgres-schema-DcG72fcT.mjs.map +0 -1
  115. package/dist/postgres-table-schema-node-BZWWEo7B.mjs.map +0 -1
  116. package/dist/schema-node-kinds-ClScchhi.mjs +0 -76
  117. 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-DcG72fcT.mjs";
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-BOtCoeKV.mjs.map
22
+ //# sourceMappingURL=resolve-ddl-schema-Ca88Tg6W.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-ddl-schema-BOtCoeKV.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
+ {"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
- export { type ContentHashParts, type RlsPolicyOperation, computeContentHash, normalizePredicate };
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 { n as normalizePredicate, t as computeContentHash } from "./canonicalize-Bn3BM1Cn.mjs";
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 };
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/core/postgres-contract-serializer.ts","../src/exports/runtime.ts"],"mappings":";;;;;;;;;;cAqEa,0BAAA,SAAmC,yBAAA,CAA0B,QAAA,CAAS,UAAA;cACrE,oBAAA,YAA+B,uBAAA;EAAA,UAUxB,wBAAA,CACjB,IAAA,UACA,GAAA,EAAK,MAAA,oBACJ,SAAA,GAAY,iBAAA;EAyBN,iBAAA,CAAkB,QAAA,EAAU,QAAA,CAAS,UAAA,IAAc,UAAA;AAAA;;;UClG7C,6BAAA,SAAsC,qBAAqB;;;;;AD2D5E;;cCnDM,+BAAA,EAAiC,uBAAA,oBAGrC,6BAAA;EAAA,SAES,MAAA,iBAAuB,kBAAA;AAAA"}
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-C-By7rOB.mjs";
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-BOtCoeKV.mjs";
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-UpzA0Ug5.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-CfdTY-Qs.mjs";
3
3
  import { t as PostgresColumnDefault } from "./types-BDKkx8MA.mjs";
4
- import { a as postgresCreateNamespace, c as PostgresRole, i as isPostgresSchema, l as PostgresRoleInput, n as PostgresSchema, o as PostgresNativeEnum, r as PostgresUnboundSchema, s as PostgresNativeEnumInput, t as PostgresContract } from "./postgres-schema-9vFZLwGo.mjs";
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 { f as PostgresRole, i as postgresCreateNamespace, n as PostgresUnboundSchema, p as PostgresRlsPolicy, r as isPostgresSchema, t as PostgresSchema } from "./postgres-schema-DcG72fcT.mjs";
3
- import { a as PostgresDatabaseSchemaNode, i as PostgresNamespaceSchemaNode, n as PostgresRoleSchemaNode, r as PostgresPolicySchemaNode, t as PostgresTableSchemaNode } from "./postgres-table-schema-node-BZWWEo7B.mjs";
4
- export { PostgresDatabaseSchemaNode, PostgresNamespaceSchemaNode, PostgresNativeEnum, PostgresPolicySchemaNode, PostgresRlsPolicy, PostgresRole, PostgresRoleSchemaNode, PostgresSchema, PostgresTableSchemaNode, PostgresUnboundSchema, isPostgresSchema, postgresCreateNamespace };
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
- export { normalizePredicate as n, computeContentHash as t };
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=canonicalize-Bn3BM1Cn.mjs.map
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.55",
3
+ "version": "0.14.0-dev.56",
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.55",
10
- "@prisma-next/contract": "0.14.0-dev.55",
11
- "@prisma-next/errors": "0.14.0-dev.55",
12
- "@prisma-next/family-sql": "0.14.0-dev.55",
13
- "@prisma-next/framework-components": "0.14.0-dev.55",
14
- "@prisma-next/migration-tools": "0.14.0-dev.55",
15
- "@prisma-next/sql-contract": "0.14.0-dev.55",
16
- "@prisma-next/sql-errors": "0.14.0-dev.55",
17
- "@prisma-next/sql-operations": "0.14.0-dev.55",
18
- "@prisma-next/sql-relational-core": "0.14.0-dev.55",
19
- "@prisma-next/sql-schema-ir": "0.14.0-dev.55",
20
- "@prisma-next/ts-render": "0.14.0-dev.55",
21
- "@prisma-next/utils": "0.14.0-dev.55",
9
+ "@prisma-next/cli": "0.14.0-dev.56",
10
+ "@prisma-next/contract": "0.14.0-dev.56",
11
+ "@prisma-next/errors": "0.14.0-dev.56",
12
+ "@prisma-next/family-sql": "0.14.0-dev.56",
13
+ "@prisma-next/framework-components": "0.14.0-dev.56",
14
+ "@prisma-next/migration-tools": "0.14.0-dev.56",
15
+ "@prisma-next/psl-parser": "0.14.0-dev.56",
16
+ "@prisma-next/sql-contract": "0.14.0-dev.56",
17
+ "@prisma-next/sql-errors": "0.14.0-dev.56",
18
+ "@prisma-next/sql-operations": "0.14.0-dev.56",
19
+ "@prisma-next/sql-relational-core": "0.14.0-dev.56",
20
+ "@prisma-next/sql-schema-ir": "0.14.0-dev.56",
21
+ "@prisma-next/ts-render": "0.14.0-dev.56",
22
+ "@prisma-next/utils": "0.14.0-dev.56",
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-parser": "0.14.0-dev.55",
28
- "@prisma-next/psl-printer": "0.14.0-dev.55",
29
- "@prisma-next/sql-contract-psl": "0.14.0-dev.55",
30
- "@prisma-next/test-utils": "0.14.0-dev.55",
31
- "@prisma-next/tsconfig": "0.14.0-dev.55",
32
- "@prisma-next/tsdown": "0.14.0-dev.55",
28
+ "@prisma-next/psl-printer": "0.14.0-dev.56",
29
+ "@prisma-next/sql-contract-psl": "0.14.0-dev.56",
30
+ "@prisma-next/test-utils": "0.14.0-dev.56",
31
+ "@prisma-next/tsconfig": "0.14.0-dev.56",
32
+ "@prisma-next/tsdown": "0.14.0-dev.56",
33
33
  "tsdown": "0.22.1",
34
34
  "typescript": "5.9.3",
35
35
  "vitest": "4.1.8"
@@ -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
+ }
@@ -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 = `${prefix}_${wireHash}`;
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',
@@ -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
  },
@@ -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({