@prisma-next/target-postgres 0.14.0-dev.9 → 0.14.0-dev.90
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-BtsOWgI3.mjs +674 -0
- package/dist/authoring-BtsOWgI3.mjs.map +1 -0
- package/dist/canonicalize-D1F4vUnP.d.mts +48 -0
- package/dist/canonicalize-D1F4vUnP.d.mts.map +1 -0
- package/dist/{codec-ids-BvytN2P8.mjs → codec-ids-B10ZZHzw.mjs} +4 -2
- package/dist/codec-ids-B10ZZHzw.mjs.map +1 -0
- package/dist/{codec-ids-CnXu9Qy3.d.mts → codec-ids-CI144z7g.d.mts} +4 -2
- package/dist/codec-ids-CI144z7g.d.mts.map +1 -0
- package/dist/codec-ids.d.mts +2 -2
- package/dist/codec-ids.mjs +2 -2
- package/dist/{codec-types-DHCkwPKE.d.mts → codec-types-CTfT4U4O.d.mts} +4 -2
- package/dist/codec-types-CTfT4U4O.d.mts.map +1 -0
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs--0A5_4Bq.d.mts → codecs-D7W9O0Xx.d.mts} +134 -4
- package/dist/codecs-D7W9O0Xx.d.mts.map +1 -0
- package/dist/codecs-DRbb26Or.mjs +955 -0
- package/dist/codecs-DRbb26Or.mjs.map +1 -0
- package/dist/codecs.d.mts +2 -2
- package/dist/codecs.mjs +3 -757
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.d.mts +33 -3
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +23 -7
- package/dist/contract-free.mjs.map +1 -1
- package/dist/control-policy-DtbkLLGv.mjs +1285 -0
- package/dist/control-policy-DtbkLLGv.mjs.map +1 -0
- package/dist/control.d.mts +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +880 -36
- package/dist/control.mjs.map +1 -1
- package/dist/data-transform-BOWpliq8.mjs.map +1 -1
- package/dist/{data-transform-DDgWdB5o.d.mts → data-transform-DPzwBMhW.d.mts} +3 -3
- package/dist/{data-transform-DDgWdB5o.d.mts.map → data-transform-DPzwBMhW.d.mts.map} +1 -1
- package/dist/data-transform.d.mts +1 -1
- package/dist/{ddl-QDyOSeLc.mjs → ddl-GTTOvjx_.mjs} +128 -6
- package/dist/ddl-GTTOvjx_.mjs.map +1 -0
- package/dist/ddl.d.mts +3 -2
- package/dist/ddl.mjs +2 -2
- package/dist/default-normalizer.d.mts +1 -1
- package/dist/default-normalizer.d.mts.map +1 -1
- package/dist/default-normalizer.mjs +247 -1
- package/dist/default-normalizer.mjs.map +1 -0
- package/dist/descriptor-meta-CFQKLXl_.mjs +23 -0
- package/dist/descriptor-meta-CFQKLXl_.mjs.map +1 -0
- package/dist/descriptor-meta-runtime-UwYdV8fD.mjs +12 -0
- package/dist/descriptor-meta-runtime-UwYdV8fD.mjs.map +1 -0
- package/dist/diff-database-schema-GncqMuSI.mjs +305 -0
- package/dist/diff-database-schema-GncqMuSI.mjs.map +1 -0
- package/dist/diff-database-schema.d.mts +46 -0
- package/dist/diff-database-schema.d.mts.map +1 -0
- package/dist/diff-database-schema.mjs +2 -0
- package/dist/errors-DO-w0EUS.mjs +35 -0
- package/dist/errors-DO-w0EUS.mjs.map +1 -0
- package/dist/errors.d.mts +11 -9
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/issue-planner.d.mts +35 -11
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +2 -2
- package/dist/migration.d.mts +5 -5
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +4 -4
- package/dist/namespace-ids-xtp_ZY86.mjs +7 -0
- package/dist/namespace-ids-xtp_ZY86.mjs.map +1 -0
- package/dist/native-type-normalizer.mjs +37 -1
- package/dist/native-type-normalizer.mjs.map +1 -0
- package/dist/nodes-DJC5B8Id.mjs +192 -0
- package/dist/nodes-DJC5B8Id.mjs.map +1 -0
- package/dist/nodes-Dv5eCSq9.d.mts +170 -0
- package/dist/nodes-Dv5eCSq9.d.mts.map +1 -0
- package/dist/{op-factory-call-DmQEc3XV.d.mts → op-factory-call-Bn9zDx4_.d.mts} +114 -15
- package/dist/op-factory-call-Bn9zDx4_.d.mts.map +1 -0
- package/dist/{op-factory-call-D_p5vxwt.mjs → op-factory-call-C38NzvQD.mjs} +469 -32
- package/dist/op-factory-call-C38NzvQD.mjs.map +1 -0
- package/dist/op-factory-call.d.mts +2 -2
- package/dist/op-factory-call.mjs +2 -2
- package/dist/pack.d.mts +321 -3
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-ddl-builders-B2wOwLqI.mjs → planner-ddl-builders-BKlmGDJl.mjs} +17 -28
- package/dist/planner-ddl-builders-BKlmGDJl.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts +4 -6
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-ddl-builders.mjs +2 -2
- package/dist/planner-identity-values-CJPha2Sz.mjs.map +1 -1
- package/dist/planner-identity-values.d.mts +8 -2
- package/dist/planner-identity-values.d.mts.map +1 -1
- package/dist/planner-identity-values.mjs +2 -2
- package/dist/planner-kql24i_F.mjs +390 -0
- package/dist/planner-kql24i_F.mjs.map +1 -0
- package/dist/{planner-produced-postgres-migration-QqHa2C2l.d.mts → planner-produced-postgres-migration-BEY1T0Xm.d.mts} +4 -4
- package/dist/{planner-produced-postgres-migration-QqHa2C2l.d.mts.map → planner-produced-postgres-migration-BEY1T0Xm.d.mts.map} +1 -1
- package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs → planner-produced-postgres-migration-D7y-PEHK.mjs} +3 -3
- package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs.map → planner-produced-postgres-migration-D7y-PEHK.mjs.map} +1 -1
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-sql-checks-jqUUGyQR.mjs → planner-sql-checks-zqNfs2XZ.mjs} +5 -5
- package/dist/{planner-sql-checks-jqUUGyQR.mjs.map → planner-sql-checks-zqNfs2XZ.mjs.map} +1 -1
- package/dist/planner-sql-checks.d.mts +2 -2
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/{planner-target-details-CIY6tLeo.d.mts → planner-target-details-HkP4RrRO.d.mts} +2 -2
- package/dist/planner-target-details-HkP4RrRO.d.mts.map +1 -0
- package/dist/planner-target-details.d.mts +1 -1
- package/dist/planner.d.mts +72 -17
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +3 -2
- package/dist/postgres-contract-view-C9j5cqP0.d.mts +34 -0
- package/dist/postgres-contract-view-C9j5cqP0.d.mts.map +1 -0
- package/dist/{postgres-contract-serializer-k3TAcPMY.mjs → postgres-contract-view-DM8sN1Ot.mjs} +45 -41
- package/dist/postgres-contract-view-DM8sN1Ot.mjs.map +1 -0
- package/dist/postgres-database-schema-node-CJv5bfbs.d.mts +262 -0
- package/dist/postgres-database-schema-node-CJv5bfbs.d.mts.map +1 -0
- package/dist/{postgres-migration-Y4YBJqkS.d.mts → postgres-migration-DbckK1su.d.mts} +58 -9
- package/dist/postgres-migration-DbckK1su.d.mts.map +1 -0
- package/dist/{postgres-migration-B5jKrXv3.mjs → postgres-migration-arMSWU9b.mjs} +78 -45
- package/dist/postgres-migration-arMSWU9b.mjs.map +1 -0
- package/dist/postgres-native-enum-BwVNf0Ku.mjs +45 -0
- package/dist/postgres-native-enum-BwVNf0Ku.mjs.map +1 -0
- package/dist/postgres-rls-policy--CSddvMR.d.mts +52 -0
- package/dist/postgres-rls-policy--CSddvMR.d.mts.map +1 -0
- package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs +190 -0
- package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs.map +1 -0
- package/dist/{postgres-schema-COGZ1ark.mjs → postgres-schema-Cm4DtiGA.mjs} +200 -11
- package/dist/postgres-schema-Cm4DtiGA.mjs.map +1 -0
- package/dist/postgres-schema-DKq6s1P3.d.mts +269 -0
- package/dist/postgres-schema-DKq6s1P3.d.mts.map +1 -0
- package/dist/postgres-table-schema-node-D6LvInCe.mjs +216 -0
- package/dist/postgres-table-schema-node-D6LvInCe.mjs.map +1 -0
- package/dist/render-ops.d.mts +1 -1
- package/dist/{render-typescript-KMgosran.mjs → render-typescript-7yqILcwr.mjs} +45 -16
- package/dist/render-typescript-7yqILcwr.mjs.map +1 -0
- package/dist/render-typescript.mjs +1 -1
- package/dist/resolve-ddl-schema-XyBaaenM.mjs +22 -0
- package/dist/resolve-ddl-schema-XyBaaenM.mjs.map +1 -0
- package/dist/rls-canonicalize.d.mts +27 -0
- package/dist/rls-canonicalize.d.mts.map +1 -0
- package/dist/rls-canonicalize.mjs +2 -0
- package/dist/runtime.d.mts +6 -8
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +3 -3
- package/dist/runtime.mjs.map +1 -1
- package/dist/schema-ir-annotations.d.mts +15 -0
- package/dist/schema-ir-annotations.d.mts.map +1 -0
- package/dist/schema-ir-annotations.mjs +2 -0
- package/dist/{sql-utils-DcfMz4MQ.mjs → sql-utils-SU4FDvIV.mjs} +12 -3
- package/dist/{sql-utils-DcfMz4MQ.mjs.map → sql-utils-SU4FDvIV.mjs.map} +1 -1
- package/dist/sql-utils.d.mts +8 -1
- package/dist/sql-utils.d.mts.map +1 -1
- package/dist/sql-utils.mjs +2 -2
- package/dist/types.d.mts +4 -140
- package/dist/types.mjs +5 -2
- package/dist/wire-name-DbQ9-2RC.mjs +104 -0
- package/dist/wire-name-DbQ9-2RC.mjs.map +1 -0
- package/package.json +26 -20
- package/src/contract-free/checks.ts +153 -0
- package/src/contract-free/control-bootstrap.ts +20 -3
- package/src/contract-free/ddl.ts +98 -1
- package/src/core/authoring.ts +726 -2
- package/src/core/codec-helpers.ts +33 -7
- package/src/core/codec-ids.ts +2 -0
- package/src/core/codec-type-map.ts +4 -0
- package/src/core/codecs.ts +236 -12
- package/src/core/ddl/nodes.ts +185 -2
- package/src/core/default-normalizer.ts +122 -2
- package/src/core/descriptor-meta.ts +12 -1
- package/src/core/entity-kinds.ts +41 -0
- package/src/core/errors.ts +14 -12
- package/src/core/migrations/bound-schema.ts +10 -0
- package/src/core/migrations/column-ddl-rendering.ts +117 -0
- package/src/core/migrations/contract-to-postgres-database-schema-node.ts +189 -0
- package/src/core/migrations/control-policy.ts +217 -65
- package/src/core/migrations/diff-database-schema.ts +252 -0
- package/src/core/migrations/issue-planner.ts +817 -656
- package/src/core/migrations/op-factory-call.ts +383 -23
- package/src/core/migrations/operations/columns.ts +24 -12
- package/src/core/migrations/operations/constraints.ts +1 -1
- package/src/core/migrations/operations/data-transform.ts +6 -0
- package/src/core/migrations/operations/dependencies.ts +2 -1
- package/src/core/migrations/operations/native-enum-types.ts +62 -0
- package/src/core/migrations/operations/rls.ts +187 -0
- package/src/core/migrations/operations/shared.ts +0 -30
- package/src/core/migrations/planner-ddl-builders.ts +31 -59
- package/src/core/migrations/planner-identity-values.ts +1 -1
- package/src/core/migrations/planner-recipes.ts +31 -13
- package/src/core/migrations/planner-sql-checks.ts +1 -1
- package/src/core/migrations/planner-strategies.ts +248 -216
- package/src/core/migrations/planner-target-details.ts +3 -1
- package/src/core/migrations/planner.ts +357 -67
- package/src/core/migrations/postgres-migration.ts +118 -86
- package/src/core/migrations/render-typescript.ts +42 -15
- package/src/core/migrations/resolve-ddl-schema.ts +26 -0
- package/src/core/migrations/runner.ts +11 -16
- package/src/core/migrations/verify-postgres-namespaces.ts +46 -31
- package/src/core/namespace-ids.ts +3 -0
- package/src/core/postgres-contract-serializer.ts +46 -71
- package/src/core/postgres-contract-view.ts +48 -0
- package/src/core/postgres-native-enum.ts +61 -0
- package/src/core/postgres-rls-enablement.ts +34 -0
- package/src/core/postgres-rls-policy.ts +64 -0
- package/src/core/postgres-role.ts +59 -0
- package/src/core/postgres-schema-verifier.ts +10 -7
- package/src/core/postgres-schema.ts +85 -15
- package/src/core/postgres-validators.ts +34 -0
- package/src/core/psl-infer/infer-psl-contract.ts +1290 -0
- package/src/core/psl-infer/postgres-default-mapping.ts +16 -0
- package/src/core/psl-infer/postgres-type-map.ts +129 -0
- package/src/core/rls/canonicalize.ts +65 -0
- package/src/core/rls/wire-name.ts +33 -0
- package/src/core/schema-ir/node-storage-coordinate.ts +26 -0
- package/src/core/schema-ir/postgres-database-schema-node.ts +61 -0
- package/src/core/schema-ir/postgres-namespace-schema-node.ts +70 -0
- package/src/core/schema-ir/postgres-native-enum-schema-node.ts +83 -0
- package/src/core/schema-ir/postgres-policy-schema-node.ts +90 -0
- package/src/core/schema-ir/postgres-role-schema-node.ts +65 -0
- package/src/core/schema-ir/postgres-table-schema-node.ts +140 -0
- package/src/core/schema-ir/schema-node-kinds.ts +122 -0
- package/src/core/sql-utils.ts +15 -2
- package/src/exports/codecs.ts +5 -0
- package/src/exports/contract-free.ts +11 -1
- package/src/exports/control.ts +27 -33
- package/src/exports/ddl.ts +8 -0
- package/src/exports/diff-database-schema.ts +7 -0
- package/src/exports/issue-planner.ts +1 -1
- package/src/exports/migration.ts +1 -0
- package/src/exports/op-factory-call.ts +4 -0
- package/src/exports/planner-ddl-builders.ts +0 -2
- package/src/exports/planner-identity-values.ts +4 -1
- package/src/exports/planner.ts +1 -0
- package/src/exports/rls-canonicalize.ts +12 -0
- package/src/exports/runtime.ts +1 -0
- package/src/exports/schema-ir-annotations.ts +1 -0
- package/src/exports/sql-utils.ts +1 -0
- package/src/exports/types.ts +37 -0
- package/dist/codec-ids-BvytN2P8.mjs.map +0 -1
- package/dist/codec-ids-CnXu9Qy3.d.mts.map +0 -1
- package/dist/codec-types-DHCkwPKE.d.mts.map +0 -1
- package/dist/codecs--0A5_4Bq.d.mts.map +0 -1
- package/dist/ddl-QDyOSeLc.mjs.map +0 -1
- package/dist/default-normalizer-DyyCHQWs.mjs +0 -131
- package/dist/default-normalizer-DyyCHQWs.mjs.map +0 -1
- package/dist/descriptor-meta-CpGygXpI.mjs +0 -140
- package/dist/descriptor-meta-CpGygXpI.mjs.map +0 -1
- package/dist/errors-CUk87ByX.mjs +0 -33
- package/dist/errors-CUk87ByX.mjs.map +0 -1
- package/dist/issue-planner-DL6g3CmE.mjs +0 -824
- package/dist/issue-planner-DL6g3CmE.mjs.map +0 -1
- package/dist/native-type-normalizer-Bc9XJzWC.mjs +0 -38
- package/dist/native-type-normalizer-Bc9XJzWC.mjs.map +0 -1
- package/dist/nodes-Bbhs2rwj.mjs +0 -76
- package/dist/nodes-Bbhs2rwj.mjs.map +0 -1
- package/dist/nodes-pLeLgdis.d.mts +0 -67
- package/dist/nodes-pLeLgdis.d.mts.map +0 -1
- package/dist/op-factory-call-D_p5vxwt.mjs.map +0 -1
- package/dist/op-factory-call-DmQEc3XV.d.mts.map +0 -1
- package/dist/planner-Bs_baQax.mjs +0 -324
- package/dist/planner-Bs_baQax.mjs.map +0 -1
- package/dist/planner-ddl-builders-B2wOwLqI.mjs.map +0 -1
- package/dist/planner-target-details-CIY6tLeo.d.mts.map +0 -1
- package/dist/postgres-contract-serializer-k3TAcPMY.mjs.map +0 -1
- package/dist/postgres-migration-B5jKrXv3.mjs.map +0 -1
- package/dist/postgres-migration-Y4YBJqkS.d.mts.map +0 -1
- package/dist/postgres-schema-COGZ1ark.mjs.map +0 -1
- package/dist/render-typescript-KMgosran.mjs.map +0 -1
- package/dist/types.d.mts.map +0 -1
- package/src/core/postgres-enum-type-schema.ts +0 -17
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import { a as PG_ENUM_CODEC_ID } from "./codec-ids-B10ZZHzw.mjs";
|
|
2
|
+
import { t as PostgresNativeEnum } from "./postgres-native-enum-BwVNf0Ku.mjs";
|
|
3
|
+
import { _ as PostgresRlsEnablement, d as PostgresRlsEnablementSchema, f as PostgresRlsPolicySchema, g as PostgresRlsPolicy, m as PostgresRole, p as PostgresRoleSchema, u as PostgresNativeEnumSchema } from "./postgres-schema-Cm4DtiGA.mjs";
|
|
4
|
+
import { a as normalizePredicate, i as computeContentHash, r as POLICY_OPERATION_PREDICATES, t as formatRlsPolicyWireName } from "./wire-name-DbQ9-2RC.mjs";
|
|
5
|
+
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
6
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
7
|
+
import { temporalAuthoringPresets } from "@prisma-next/family-sql/control";
|
|
8
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
9
|
+
import { modelAttribute } from "@prisma-next/psl-parser";
|
|
10
|
+
import { assertDefined } from "@prisma-next/utils/assertions";
|
|
11
|
+
//#region src/core/authoring.ts
|
|
12
|
+
/**
|
|
13
|
+
* `pg.enum(<ref>)` registers as an ordinary type constructor whose sole
|
|
14
|
+
* positional argument names a `native_enum` entity instead of carrying a
|
|
15
|
+
* literal value. The interpreter resolves the ref to the `native_enum`
|
|
16
|
+
* entity generically (driven by `entityRefArg`); the `pg/enum@1` codec
|
|
17
|
+
* descriptor's `columnFromEntity` hook (see `codecs.ts`) converts that
|
|
18
|
+
* entity into the column's `typeParams` and native type.
|
|
19
|
+
*/
|
|
20
|
+
const postgresAuthoringTypes = { pg: { enum: {
|
|
21
|
+
kind: "typeConstructor",
|
|
22
|
+
entityRefArg: {
|
|
23
|
+
index: 0,
|
|
24
|
+
entityKind: "native_enum"
|
|
25
|
+
},
|
|
26
|
+
output: { codecId: PG_ENUM_CODEC_ID }
|
|
27
|
+
} } };
|
|
28
|
+
/**
|
|
29
|
+
* Maps a `policy_<op>` keyword to the RLS operation it authors. The keyword
|
|
30
|
+
* IS the operation (per the project's rejection of a `policy { operation = … }`
|
|
31
|
+
* conditional block).
|
|
32
|
+
*/
|
|
33
|
+
const POLICY_KEYWORD_OPERATION = {
|
|
34
|
+
policy_select: "select",
|
|
35
|
+
policy_insert: "insert",
|
|
36
|
+
policy_update: "update",
|
|
37
|
+
policy_delete: "delete",
|
|
38
|
+
policy_all: "all"
|
|
39
|
+
};
|
|
40
|
+
function readValueParam(block, key) {
|
|
41
|
+
const param = block.parameters[key];
|
|
42
|
+
return param?.kind === "value" ? param.raw : void 0;
|
|
43
|
+
}
|
|
44
|
+
function readListRefParams(block, key) {
|
|
45
|
+
const param = block.parameters[key];
|
|
46
|
+
if (param?.kind !== "list") return [];
|
|
47
|
+
return param.items.flatMap((item) => item.kind === "ref" ? [item.identifier] : []);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Unwraps a quoted PSL string argument, inverting the printer's
|
|
51
|
+
* `escapePslString` escapes (`\\`, `\"`, `\n`, `\r`). An unknown escape
|
|
52
|
+
* sequence is kept verbatim, matching the printer-side `unescapePslString`
|
|
53
|
+
* convention.
|
|
54
|
+
*/
|
|
55
|
+
function unwrapQuotedString(raw) {
|
|
56
|
+
if (!(raw.startsWith("\"") && raw.endsWith("\"") && raw.length >= 2)) return raw;
|
|
57
|
+
const inner = raw.slice(1, -1);
|
|
58
|
+
let result = "";
|
|
59
|
+
for (let i = 0; i < inner.length; i++) {
|
|
60
|
+
if (inner[i] !== "\\" || i + 1 >= inner.length) {
|
|
61
|
+
result += inner[i];
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const next = inner[i + 1];
|
|
65
|
+
if (next === "\\" || next === "\"") result += next;
|
|
66
|
+
else if (next === "n") result += "\n";
|
|
67
|
+
else if (next === "r") result += "\r";
|
|
68
|
+
else {
|
|
69
|
+
result += "\\";
|
|
70
|
+
result += next;
|
|
71
|
+
}
|
|
72
|
+
i++;
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Assembles a {@link PostgresRlsPolicy} from lowered inputs: normalizes the
|
|
78
|
+
* predicates, computes the content-hash wire name, and constructs the frozen
|
|
79
|
+
* entity. The single hash-assembly body shared by the PSL block lowering
|
|
80
|
+
* ({@link lowerRlsPolicyFromBlock}) and the TS entity-handle lowering
|
|
81
|
+
* ({@link postgresLowerEntityHandles}) so the two surfaces cannot drift.
|
|
82
|
+
*/
|
|
83
|
+
function buildRlsPolicyEntity(input) {
|
|
84
|
+
const wireHash = computeContentHash({
|
|
85
|
+
...ifDefined("using", input.using !== void 0 ? normalizePredicate(input.using) : void 0),
|
|
86
|
+
...ifDefined("withCheck", input.withCheck !== void 0 ? normalizePredicate(input.withCheck) : void 0),
|
|
87
|
+
roles: input.roles,
|
|
88
|
+
operation: input.operation,
|
|
89
|
+
permissive: true
|
|
90
|
+
});
|
|
91
|
+
return new PostgresRlsPolicy({
|
|
92
|
+
name: formatRlsPolicyWireName(input.prefix, wireHash),
|
|
93
|
+
prefix: input.prefix,
|
|
94
|
+
tableName: input.tableName,
|
|
95
|
+
namespaceId: input.namespaceId,
|
|
96
|
+
operation: input.operation,
|
|
97
|
+
roles: input.roles,
|
|
98
|
+
...ifDefined("using", input.using),
|
|
99
|
+
...ifDefined("withCheck", input.withCheck),
|
|
100
|
+
permissive: true
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function lowerRlsPolicyFromBlock(block, ctx) {
|
|
104
|
+
const prefix = block.name;
|
|
105
|
+
const operation = POLICY_KEYWORD_OPERATION[block.keyword] ?? "select";
|
|
106
|
+
const tableName = block.resolvedModelRefs?.["target"]?.tableName;
|
|
107
|
+
assertDefined(tableName, `lowerRlsPolicyFromBlock: policy "${block.name}" reached the factory without a resolved \`target\` ref; the interpreter resolves same-namespace model refs before invoking entity factories.`);
|
|
108
|
+
const roles = [...readListRefParams(block, "roles")].sort();
|
|
109
|
+
const usingRaw = readValueParam(block, "using");
|
|
110
|
+
const withCheckRaw = readValueParam(block, "withCheck");
|
|
111
|
+
const support = POLICY_OPERATION_PREDICATES[operation];
|
|
112
|
+
const rejectPredicate = (predicate) => {
|
|
113
|
+
ctx.diagnostics?.push({
|
|
114
|
+
code: "PSL_RLS_PREDICATE_NOT_FOR_OPERATION",
|
|
115
|
+
message: `\`${block.keyword}\` policy "${block.name}" does not take a \`${predicate}\` predicate; the ${operation.toUpperCase()} operation uses ${support.using ? "`using`" : "`withCheck`"}${support.using && support.withCheck ? " and `withCheck`" : " only"}.`,
|
|
116
|
+
sourceId: ctx.sourceId ?? "unknown",
|
|
117
|
+
span: block.parameters[predicate]?.span ?? block.span
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
if (usingRaw !== void 0 && !support.using) return rejectPredicate("using");
|
|
121
|
+
if (withCheckRaw !== void 0 && !support.withCheck) return rejectPredicate("withCheck");
|
|
122
|
+
const using = usingRaw !== void 0 ? unwrapQuotedString(usingRaw) : void 0;
|
|
123
|
+
const withCheck = withCheckRaw !== void 0 ? unwrapQuotedString(withCheckRaw) : void 0;
|
|
124
|
+
return buildRlsPolicyEntity({
|
|
125
|
+
prefix,
|
|
126
|
+
tableName,
|
|
127
|
+
namespaceId: block.namespaceId,
|
|
128
|
+
operation,
|
|
129
|
+
roles,
|
|
130
|
+
...ifDefined("using", using),
|
|
131
|
+
...ifDefined("withCheck", withCheck)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Lowers a `native_enum { memberName = "value" … @@map("type_name") }` block
|
|
136
|
+
* into a {@link PostgresNativeEnum}. Members must be authored as explicit
|
|
137
|
+
* `key = "value"` pairs — a bare (value-less) member is a diagnostic, not
|
|
138
|
+
* accepted (authoring-design.md §2.1). The parsed `memberName` is only used
|
|
139
|
+
* to duplicate-check and report diagnostics; the lowered entity carries just
|
|
140
|
+
* the member values (a native enum is value-only — the member "name" isn't
|
|
141
|
+
* a separate authoring concept from the value). `typeName` comes from
|
|
142
|
+
* `@@map` or defaults to the block name verbatim.
|
|
143
|
+
*/
|
|
144
|
+
function lowerNativeEnumFromBlock(block, ctx) {
|
|
145
|
+
const sourceId = ctx.sourceId ?? "unknown";
|
|
146
|
+
const diagnostics = ctx.diagnostics;
|
|
147
|
+
const mapAttr = block.blockAttributes.find((a) => a.name === "map");
|
|
148
|
+
let typeName = block.name;
|
|
149
|
+
if (mapAttr) {
|
|
150
|
+
const rawArg = mapAttr.args[0]?.value;
|
|
151
|
+
const mapped = rawArg !== void 0 ? unwrapQuotedString(rawArg) : void 0;
|
|
152
|
+
if (mapped === void 0) {
|
|
153
|
+
diagnostics?.push({
|
|
154
|
+
code: "PSL_NATIVE_ENUM_INVALID_MAP",
|
|
155
|
+
message: `native_enum "${block.name}" @@map attribute must have a quoted type-name argument`,
|
|
156
|
+
sourceId,
|
|
157
|
+
span: mapAttr.span
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
typeName = mapped;
|
|
162
|
+
}
|
|
163
|
+
let memberError = false;
|
|
164
|
+
const seenValues = /* @__PURE__ */ new Set();
|
|
165
|
+
const members = [];
|
|
166
|
+
for (const [memberName, paramValue] of Object.entries(block.parameters)) {
|
|
167
|
+
if (paramValue.kind === "bare") {
|
|
168
|
+
diagnostics?.push({
|
|
169
|
+
code: "PSL_NATIVE_ENUM_BARE_MEMBER",
|
|
170
|
+
message: `native_enum "${block.name}" member "${memberName}" has no value; members must be authored as "${memberName} = \\"value\\""`,
|
|
171
|
+
sourceId,
|
|
172
|
+
span: paramValue.span
|
|
173
|
+
});
|
|
174
|
+
memberError = true;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (paramValue.kind !== "value") continue;
|
|
178
|
+
let jsonValue;
|
|
179
|
+
try {
|
|
180
|
+
jsonValue = JSON.parse(paramValue.raw);
|
|
181
|
+
} catch {
|
|
182
|
+
diagnostics?.push({
|
|
183
|
+
code: "PSL_EXTENSION_INVALID_VALUE",
|
|
184
|
+
message: `native_enum "${block.name}" member "${memberName}" value "${paramValue.raw}" is not valid JSON`,
|
|
185
|
+
sourceId,
|
|
186
|
+
span: paramValue.span
|
|
187
|
+
});
|
|
188
|
+
memberError = true;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (typeof jsonValue !== "string") {
|
|
192
|
+
diagnostics?.push({
|
|
193
|
+
code: "PSL_EXTENSION_INVALID_VALUE",
|
|
194
|
+
message: `native_enum "${block.name}" member "${memberName}" value must be a string`,
|
|
195
|
+
sourceId,
|
|
196
|
+
span: paramValue.span
|
|
197
|
+
});
|
|
198
|
+
memberError = true;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (seenValues.has(jsonValue)) {
|
|
202
|
+
diagnostics?.push({
|
|
203
|
+
code: "PSL_NATIVE_ENUM_DUPLICATE_MEMBER_VALUE",
|
|
204
|
+
message: `native_enum "${block.name}": duplicate member value "${jsonValue}"`,
|
|
205
|
+
sourceId,
|
|
206
|
+
span: paramValue.span
|
|
207
|
+
});
|
|
208
|
+
memberError = true;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
seenValues.add(jsonValue);
|
|
212
|
+
members.push(jsonValue);
|
|
213
|
+
}
|
|
214
|
+
if (memberError) return void 0;
|
|
215
|
+
if (members.length === 0) {
|
|
216
|
+
diagnostics?.push({
|
|
217
|
+
code: "PSL_NATIVE_ENUM_MISSING_MEMBERS",
|
|
218
|
+
message: `native_enum "${block.name}" must have at least one member`,
|
|
219
|
+
sourceId,
|
|
220
|
+
span: block.span
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
return new PostgresNativeEnum({
|
|
225
|
+
typeName,
|
|
226
|
+
members
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* `native_enum`'s entity-type factory output, checked separately from the assembled
|
|
231
|
+
* `postgresAuthoringEntityTypes` map below: `deriveValueSet` is SQL-family surface
|
|
232
|
+
* ({@link SqlValueSetDerivingEntityTypeOutput}), not part of the framework
|
|
233
|
+
* `AuthoringEntityTypeFactoryOutput` shape, so folding it directly into the map's single
|
|
234
|
+
* `satisfies AuthoringEntityTypeNamespace` check would trip an excess-property error. Checking it
|
|
235
|
+
* here against the intersection of both shapes keeps it structurally valid against each without
|
|
236
|
+
* widening the map's own check.
|
|
237
|
+
*/
|
|
238
|
+
const nativeEnumEntityTypeOutput = {
|
|
239
|
+
factory: lowerNativeEnumFromBlock,
|
|
240
|
+
deriveValueSet: (entity) => ({
|
|
241
|
+
kind: "valueSet",
|
|
242
|
+
values: [...entity.members]
|
|
243
|
+
})
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Lowers a `role <name> {}` block into a {@link PostgresRole}. Roles are
|
|
247
|
+
* cluster-scoped in Postgres, so the block must be declared inside
|
|
248
|
+
* `namespace unbound { … }` — any other lexical namespace (a named schema,
|
|
249
|
+
* or the default bucket top-level declarations resolve to) is a load-time
|
|
250
|
+
* diagnostic. The lowered entity carries the unbound coordinate.
|
|
251
|
+
*/
|
|
252
|
+
function lowerRoleFromBlock(block, ctx) {
|
|
253
|
+
if (block.namespaceId !== UNBOUND_NAMESPACE_ID) {
|
|
254
|
+
ctx.diagnostics?.push({
|
|
255
|
+
code: "PSL_ROLE_BLOCK_OUTSIDE_UNBOUND_NAMESPACE",
|
|
256
|
+
message: `\`role\` block "${block.name}" must be declared inside \`namespace unbound { }\`, not in namespace "${block.namespaceId}"`,
|
|
257
|
+
sourceId: ctx.sourceId ?? "unknown",
|
|
258
|
+
span: block.span
|
|
259
|
+
});
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
return new PostgresRole({
|
|
263
|
+
name: block.name,
|
|
264
|
+
namespaceId: UNBOUND_NAMESPACE_ID
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
const postgresAuthoringEntityTypes = {
|
|
268
|
+
role: {
|
|
269
|
+
kind: "entity",
|
|
270
|
+
discriminator: "role",
|
|
271
|
+
validatorSchema: PostgresRoleSchema,
|
|
272
|
+
output: { factory: lowerRoleFromBlock }
|
|
273
|
+
},
|
|
274
|
+
rls: {
|
|
275
|
+
kind: "entity",
|
|
276
|
+
discriminator: "rls",
|
|
277
|
+
validatorSchema: PostgresRlsEnablementSchema,
|
|
278
|
+
output: { factory: (input) => new PostgresRlsEnablement(input) }
|
|
279
|
+
},
|
|
280
|
+
policy: {
|
|
281
|
+
kind: "entity",
|
|
282
|
+
discriminator: "policy",
|
|
283
|
+
validatorSchema: PostgresRlsPolicySchema,
|
|
284
|
+
output: { factory: lowerRlsPolicyFromBlock }
|
|
285
|
+
},
|
|
286
|
+
native_enum: {
|
|
287
|
+
kind: "entity",
|
|
288
|
+
discriminator: "native_enum",
|
|
289
|
+
validatorSchema: PostgresNativeEnumSchema,
|
|
290
|
+
output: nativeEnumEntityTypeOutput
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* Field presets contributed by the Postgres target pack.
|
|
295
|
+
*
|
|
296
|
+
* These mirror the PSL scalar-to-codec mapping used by the Postgres adapter
|
|
297
|
+
* (see `createPostgresPslScalarTypeDescriptors`), so that authoring a field
|
|
298
|
+
* via the TS callback surface (e.g. `field.int()`) and via the PSL scalar
|
|
299
|
+
* surface (e.g. `Int`) lowers to byte-identical contracts.
|
|
300
|
+
*
|
|
301
|
+
* The `uuidNative` / `id.uuidv4Native` / `id.uuidv7Native` presets use the
|
|
302
|
+
* native Postgres `uuid` type (codecId `pg/uuid@1`). For cross-target
|
|
303
|
+
* portability use `uuidString` / `id.uuidv4String` / `id.uuidv7String` from
|
|
304
|
+
* the family pack instead.
|
|
305
|
+
*/
|
|
306
|
+
/**
|
|
307
|
+
* Shared parameter descriptors for the five `policy_<op>` PSL block
|
|
308
|
+
* keywords. All five share the `policy` discriminator — the parser
|
|
309
|
+
* dispatches by keyword (see the framework's PSL-block SPI), and every
|
|
310
|
+
* keyword's factory lowers to `PostgresRlsPolicy` via `lowerRlsPolicyFromBlock`.
|
|
311
|
+
*
|
|
312
|
+
* The `roles` list uses `scope:'cross-space'` because same-namespace
|
|
313
|
+
* role ref resolution requires PSL namespace entries keyed by `refKind`
|
|
314
|
+
* (i.e. `'role'`), which in turn requires the role block discriminator to
|
|
315
|
+
* equal `'role'`. Aligning discriminator with refKind is tracked for
|
|
316
|
+
* slice 4 (cross-space roles). Until then cross-space passes validation
|
|
317
|
+
* unconditionally and the authored role names flow through unchanged.
|
|
318
|
+
*/
|
|
319
|
+
const policyTargetParam = {
|
|
320
|
+
kind: "ref",
|
|
321
|
+
refKind: "model",
|
|
322
|
+
scope: "same-namespace",
|
|
323
|
+
required: true
|
|
324
|
+
};
|
|
325
|
+
const policyRolesParam = {
|
|
326
|
+
kind: "list",
|
|
327
|
+
of: {
|
|
328
|
+
kind: "ref",
|
|
329
|
+
refKind: "role",
|
|
330
|
+
scope: "cross-space"
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
const policyPredicateParam = {
|
|
334
|
+
kind: "value",
|
|
335
|
+
codecId: "pg/text@1",
|
|
336
|
+
required: true
|
|
337
|
+
};
|
|
338
|
+
const policyRequiresRls = {
|
|
339
|
+
parameter: "target",
|
|
340
|
+
attribute: "rls"
|
|
341
|
+
};
|
|
342
|
+
const postgresAuthoringPslBlockDescriptors = {
|
|
343
|
+
policy_select: {
|
|
344
|
+
kind: "pslBlock",
|
|
345
|
+
keyword: "policy_select",
|
|
346
|
+
discriminator: "policy",
|
|
347
|
+
name: { required: true },
|
|
348
|
+
parameters: {
|
|
349
|
+
target: policyTargetParam,
|
|
350
|
+
roles: policyRolesParam,
|
|
351
|
+
using: policyPredicateParam
|
|
352
|
+
},
|
|
353
|
+
requiresModelAttribute: policyRequiresRls
|
|
354
|
+
},
|
|
355
|
+
policy_delete: {
|
|
356
|
+
kind: "pslBlock",
|
|
357
|
+
keyword: "policy_delete",
|
|
358
|
+
discriminator: "policy",
|
|
359
|
+
name: { required: true },
|
|
360
|
+
parameters: {
|
|
361
|
+
target: policyTargetParam,
|
|
362
|
+
roles: policyRolesParam,
|
|
363
|
+
using: policyPredicateParam
|
|
364
|
+
},
|
|
365
|
+
requiresModelAttribute: policyRequiresRls
|
|
366
|
+
},
|
|
367
|
+
policy_insert: {
|
|
368
|
+
kind: "pslBlock",
|
|
369
|
+
keyword: "policy_insert",
|
|
370
|
+
discriminator: "policy",
|
|
371
|
+
name: { required: true },
|
|
372
|
+
parameters: {
|
|
373
|
+
target: policyTargetParam,
|
|
374
|
+
roles: policyRolesParam,
|
|
375
|
+
withCheck: policyPredicateParam
|
|
376
|
+
},
|
|
377
|
+
requiresModelAttribute: policyRequiresRls
|
|
378
|
+
},
|
|
379
|
+
policy_update: {
|
|
380
|
+
kind: "pslBlock",
|
|
381
|
+
keyword: "policy_update",
|
|
382
|
+
discriminator: "policy",
|
|
383
|
+
name: { required: true },
|
|
384
|
+
parameters: {
|
|
385
|
+
target: policyTargetParam,
|
|
386
|
+
roles: policyRolesParam,
|
|
387
|
+
using: policyPredicateParam,
|
|
388
|
+
withCheck: policyPredicateParam
|
|
389
|
+
},
|
|
390
|
+
requiresModelAttribute: policyRequiresRls
|
|
391
|
+
},
|
|
392
|
+
policy_all: {
|
|
393
|
+
kind: "pslBlock",
|
|
394
|
+
keyword: "policy_all",
|
|
395
|
+
discriminator: "policy",
|
|
396
|
+
name: { required: true },
|
|
397
|
+
parameters: {
|
|
398
|
+
target: policyTargetParam,
|
|
399
|
+
roles: policyRolesParam,
|
|
400
|
+
using: policyPredicateParam,
|
|
401
|
+
withCheck: policyPredicateParam
|
|
402
|
+
},
|
|
403
|
+
requiresModelAttribute: policyRequiresRls
|
|
404
|
+
},
|
|
405
|
+
/**
|
|
406
|
+
* PSL block descriptor for `native_enum`.
|
|
407
|
+
*
|
|
408
|
+
* Reuses the existing variadic-block mechanism (the same shape the SQL
|
|
409
|
+
* family's `enum` block ships): the body is an open `memberName = "value"`
|
|
410
|
+
* list. `variadicParameters: true` opens the block to arbitrary keys
|
|
411
|
+
* beyond the declared (empty) `parameters` set — the lowering factory
|
|
412
|
+
* (`lowerNativeEnumFromBlock`) turns the variadic entries into ordered
|
|
413
|
+
* members and rejects a bare (value-less) member.
|
|
414
|
+
*/
|
|
415
|
+
native_enum: {
|
|
416
|
+
kind: "pslBlock",
|
|
417
|
+
keyword: "native_enum",
|
|
418
|
+
discriminator: "native_enum",
|
|
419
|
+
name: { required: true },
|
|
420
|
+
parameters: {},
|
|
421
|
+
variadicParameters: true
|
|
422
|
+
},
|
|
423
|
+
/**
|
|
424
|
+
* PSL block descriptor for `role` (e.g. `role anon {}`). Name-only, no
|
|
425
|
+
* parameters and no body content. Declared inside `namespace unbound { }`
|
|
426
|
+
* — see {@link lowerRoleFromBlock} for the placement check and the
|
|
427
|
+
* coordinate the lowered entity carries.
|
|
428
|
+
*/
|
|
429
|
+
role: {
|
|
430
|
+
kind: "pslBlock",
|
|
431
|
+
keyword: "role",
|
|
432
|
+
discriminator: "role",
|
|
433
|
+
name: { required: true },
|
|
434
|
+
parameters: {}
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
/**
|
|
438
|
+
* `@@` model attributes contributed by the Postgres target pack.
|
|
439
|
+
*
|
|
440
|
+
* `@@rls` is argument-less: presence marks the model's table
|
|
441
|
+
* RLS-controlled. It lowers to a {@link PostgresRlsEnablement} marker in
|
|
442
|
+
* the namespace's `entries.rls`, keyed by the model's table name — the
|
|
443
|
+
* marker (never the policy set) is what drives
|
|
444
|
+
* `ENABLE`/`DISABLE ROW LEVEL SECURITY` planning.
|
|
445
|
+
*/
|
|
446
|
+
const postgresAuthoringModelAttributes = { rls: {
|
|
447
|
+
kind: "modelAttribute",
|
|
448
|
+
attribute: "rls",
|
|
449
|
+
spec: modelAttribute("rls", {}),
|
|
450
|
+
lower: (_parsed, ctx) => ({
|
|
451
|
+
key: ctx.storageName,
|
|
452
|
+
entity: new PostgresRlsEnablement({
|
|
453
|
+
tableName: ctx.storageName,
|
|
454
|
+
namespaceId: ctx.namespaceId
|
|
455
|
+
})
|
|
456
|
+
})
|
|
457
|
+
} };
|
|
458
|
+
const postgresAuthoringFieldPresets = {
|
|
459
|
+
text: {
|
|
460
|
+
kind: "fieldPreset",
|
|
461
|
+
output: {
|
|
462
|
+
codecId: "pg/text@1",
|
|
463
|
+
nativeType: "text"
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
int: {
|
|
467
|
+
kind: "fieldPreset",
|
|
468
|
+
output: {
|
|
469
|
+
codecId: "pg/int4@1",
|
|
470
|
+
nativeType: "int4"
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
bigint: {
|
|
474
|
+
kind: "fieldPreset",
|
|
475
|
+
output: {
|
|
476
|
+
codecId: "pg/int8@1",
|
|
477
|
+
nativeType: "int8"
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
float: {
|
|
481
|
+
kind: "fieldPreset",
|
|
482
|
+
output: {
|
|
483
|
+
codecId: "pg/float8@1",
|
|
484
|
+
nativeType: "float8"
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
decimal: {
|
|
488
|
+
kind: "fieldPreset",
|
|
489
|
+
output: {
|
|
490
|
+
codecId: "pg/numeric@1",
|
|
491
|
+
nativeType: "numeric"
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
boolean: {
|
|
495
|
+
kind: "fieldPreset",
|
|
496
|
+
output: {
|
|
497
|
+
codecId: "pg/bool@1",
|
|
498
|
+
nativeType: "bool"
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
json: {
|
|
502
|
+
kind: "fieldPreset",
|
|
503
|
+
output: {
|
|
504
|
+
codecId: "pg/jsonb@1",
|
|
505
|
+
nativeType: "jsonb"
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
bytes: {
|
|
509
|
+
kind: "fieldPreset",
|
|
510
|
+
output: {
|
|
511
|
+
codecId: "pg/bytea@1",
|
|
512
|
+
nativeType: "bytea"
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
dateTime: {
|
|
516
|
+
kind: "fieldPreset",
|
|
517
|
+
output: {
|
|
518
|
+
codecId: "pg/timestamptz@1",
|
|
519
|
+
nativeType: "timestamptz"
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
temporal: /* @__PURE__ */ temporalAuthoringPresets({
|
|
523
|
+
codecId: "pg/timestamptz@1",
|
|
524
|
+
nativeType: "timestamptz"
|
|
525
|
+
}),
|
|
526
|
+
uuidNative: {
|
|
527
|
+
kind: "fieldPreset",
|
|
528
|
+
output: {
|
|
529
|
+
codecId: "pg/uuid@1",
|
|
530
|
+
nativeType: "uuid"
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
id: {
|
|
534
|
+
uuidv4Native: {
|
|
535
|
+
kind: "fieldPreset",
|
|
536
|
+
output: {
|
|
537
|
+
codecId: "pg/uuid@1",
|
|
538
|
+
nativeType: "uuid",
|
|
539
|
+
executionDefaults: { onCreate: {
|
|
540
|
+
kind: "generator",
|
|
541
|
+
id: "uuidv4"
|
|
542
|
+
} },
|
|
543
|
+
id: true
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
uuidv7Native: {
|
|
547
|
+
kind: "fieldPreset",
|
|
548
|
+
output: {
|
|
549
|
+
codecId: "pg/uuid@1",
|
|
550
|
+
nativeType: "uuid",
|
|
551
|
+
executionDefaults: { onCreate: {
|
|
552
|
+
kind: "generator",
|
|
553
|
+
id: "uuidv7"
|
|
554
|
+
} },
|
|
555
|
+
id: true
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
/**
|
|
561
|
+
* Postgres identifiers cap at 63 characters and the wire name appends a
|
|
562
|
+
* 9-character `_<8hex>` suffix, so the authored prefix is bounded at 54.
|
|
563
|
+
*/
|
|
564
|
+
const RLS_POLICY_PREFIX_MAX_LENGTH = 54;
|
|
565
|
+
/**
|
|
566
|
+
* Resolves an entity handle's `target` ref to a table coordinate of this
|
|
567
|
+
* contract, or throws the load-time diagnostic naming the handle: a
|
|
568
|
+
* cross-space target is rejected (you cannot CREATE POLICY on a table
|
|
569
|
+
* another space owns) and an unresolved target names the model.
|
|
570
|
+
*/
|
|
571
|
+
function requireLocalTarget(refs, subject) {
|
|
572
|
+
const target = refs["target"];
|
|
573
|
+
if (target !== void 0 && target.kind === "resolved") return {
|
|
574
|
+
namespaceId: target.namespaceId,
|
|
575
|
+
tableName: target.tableName
|
|
576
|
+
};
|
|
577
|
+
if (target !== void 0 && target.kind === "cross-space") throw new Error(`defineContract: ${subject} targets model "${target.modelName ?? target.tableName}", which lives in another contract space. Policies and rlsEnabled entries must target a model declared in this contract.`);
|
|
578
|
+
throw new Error(`defineContract: ${subject} targets model "${target?.modelName ?? "<anonymous>"}", which is not in the contract's models. Add the model to \`models\`.`);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* The SQL-family entity-handle batch lowering hook for the Postgres pack
|
|
582
|
+
* (`SqlEntityHandleLoweringContribution`). Receives every `entities` handle
|
|
583
|
+
* whose kind this pack registered — batch, so the cross-entity diagnostics
|
|
584
|
+
* (duplicate prefix, policy without rlsEnabled, duplicate role) can see
|
|
585
|
+
* sibling handles — and lowers them with the same keying and hash assembly
|
|
586
|
+
* as the PSL path: `policy` keyed by prefix (wire name via
|
|
587
|
+
* {@link buildRlsPolicyEntity}), `rls` keyed by table name, `role` keyed by
|
|
588
|
+
* name and filed under the default namespace (roles are declared
|
|
589
|
+
* contract-wide; PSL has no role block to set a precedent).
|
|
590
|
+
*/
|
|
591
|
+
function postgresLowerEntityHandles(input) {
|
|
592
|
+
const enablements = /* @__PURE__ */ new Map();
|
|
593
|
+
const roles = /* @__PURE__ */ new Map();
|
|
594
|
+
const policies = [];
|
|
595
|
+
const coordinateKey = (coordinate) => `${coordinate.namespaceId} ${coordinate.tableName}`;
|
|
596
|
+
for (const { handle, refs } of input.handles) switch (handle.entityKind) {
|
|
597
|
+
case "rls": {
|
|
598
|
+
const coordinate = requireLocalTarget(refs, "an rlsEnabled entry");
|
|
599
|
+
const key = coordinateKey(coordinate);
|
|
600
|
+
if (!enablements.has(key)) enablements.set(key, {
|
|
601
|
+
coordinate,
|
|
602
|
+
entity: new PostgresRlsEnablement({
|
|
603
|
+
tableName: coordinate.tableName,
|
|
604
|
+
namespaceId: coordinate.namespaceId
|
|
605
|
+
})
|
|
606
|
+
});
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
case "role": {
|
|
610
|
+
const roleHandle = blindCast(handle);
|
|
611
|
+
if (roles.has(roleHandle.name)) throw new Error(`defineContract: role "${roleHandle.name}" is declared more than once in the entities list.`);
|
|
612
|
+
roles.set(roleHandle.name, new PostgresRole({
|
|
613
|
+
name: roleHandle.name,
|
|
614
|
+
namespaceId: UNBOUND_NAMESPACE_ID
|
|
615
|
+
}));
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
case "policy": {
|
|
619
|
+
const policyHandle = blindCast(handle);
|
|
620
|
+
policies.push({
|
|
621
|
+
handle: policyHandle,
|
|
622
|
+
refs
|
|
623
|
+
});
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
default: throw new Error(`defineContract: the postgres pack does not lower "${handle.entityKind}" handles from the entities list.`);
|
|
627
|
+
}
|
|
628
|
+
const rows = [];
|
|
629
|
+
const seenPrefixes = /* @__PURE__ */ new Set();
|
|
630
|
+
for (const { handle: policy, refs } of policies) {
|
|
631
|
+
const prefix = policy.name;
|
|
632
|
+
if (prefix.length > RLS_POLICY_PREFIX_MAX_LENGTH) throw new Error(`defineContract: policy prefix "${prefix}" exceeds the ${RLS_POLICY_PREFIX_MAX_LENGTH}-character maximum (Postgres identifiers cap at 63 characters and the wire name appends a 9-character hash suffix).`);
|
|
633
|
+
const coordinate = requireLocalTarget(refs, `policy "${prefix}"`);
|
|
634
|
+
if (!enablements.has(coordinateKey(coordinate))) {
|
|
635
|
+
const target = refs["target"];
|
|
636
|
+
throw new Error(`defineContract: policy "${prefix}" targets model "${target?.modelName ?? coordinate.tableName}", whose table is not RLS-enabled. Add rlsEnabled(<model>) to the entities list.`);
|
|
637
|
+
}
|
|
638
|
+
const prefixKey = `${coordinate.namespaceId} ${prefix}`;
|
|
639
|
+
if (seenPrefixes.has(prefixKey)) throw new Error(`defineContract: policy prefix "${prefix}" is declared more than once in namespace "${coordinate.namespaceId}". Policy prefixes must be unique per namespace.`);
|
|
640
|
+
seenPrefixes.add(prefixKey);
|
|
641
|
+
const roleNames = [...new Set(policy.roles.map((roleHandle) => roleHandle.name))].sort();
|
|
642
|
+
rows.push({
|
|
643
|
+
namespaceId: coordinate.namespaceId,
|
|
644
|
+
entityKind: "policy",
|
|
645
|
+
key: prefix,
|
|
646
|
+
entity: buildRlsPolicyEntity({
|
|
647
|
+
prefix,
|
|
648
|
+
tableName: coordinate.tableName,
|
|
649
|
+
namespaceId: coordinate.namespaceId,
|
|
650
|
+
operation: policy.operation,
|
|
651
|
+
roles: roleNames,
|
|
652
|
+
...ifDefined("using", policy.using),
|
|
653
|
+
...ifDefined("withCheck", policy.withCheck)
|
|
654
|
+
})
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
for (const { coordinate, entity } of enablements.values()) rows.push({
|
|
658
|
+
namespaceId: coordinate.namespaceId,
|
|
659
|
+
entityKind: "rls",
|
|
660
|
+
key: coordinate.tableName,
|
|
661
|
+
entity
|
|
662
|
+
});
|
|
663
|
+
for (const [name, entity] of roles) rows.push({
|
|
664
|
+
namespaceId: UNBOUND_NAMESPACE_ID,
|
|
665
|
+
entityKind: "role",
|
|
666
|
+
key: name,
|
|
667
|
+
entity
|
|
668
|
+
});
|
|
669
|
+
return rows;
|
|
670
|
+
}
|
|
671
|
+
//#endregion
|
|
672
|
+
export { postgresAuthoringTypes as a, postgresAuthoringPslBlockDescriptors as i, postgresAuthoringFieldPresets as n, postgresLowerEntityHandles as o, postgresAuthoringModelAttributes as r, postgresAuthoringEntityTypes as t };
|
|
673
|
+
|
|
674
|
+
//# sourceMappingURL=authoring-BtsOWgI3.mjs.map
|