@prisma-next/target-postgres 0.14.0-dev.60 → 0.14.0-dev.62
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-WkqG_MkU.mjs → authoring-CdIZ0yvD.mjs} +147 -38
- package/dist/authoring-CdIZ0yvD.mjs.map +1 -0
- package/dist/contract-free.d.mts +1 -1
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +2 -2
- package/dist/{control-policy-Co_13Hxa.mjs → control-policy-DKp0HKpY.mjs} +203 -45
- package/dist/control-policy-DKp0HKpY.mjs.map +1 -0
- package/dist/control.mjs +22 -25
- package/dist/control.mjs.map +1 -1
- package/dist/{ddl-B-krEXY1.mjs → ddl-gmxHf68z.mjs} +20 -4
- package/dist/{ddl-B-krEXY1.mjs.map → ddl-gmxHf68z.mjs.map} +1 -1
- package/dist/ddl.d.mts +2 -2
- package/dist/ddl.mjs +2 -2
- package/dist/{descriptor-meta-BOcKPaLE.mjs → descriptor-meta-DEuXJfpR.mjs} +3 -3
- package/dist/{descriptor-meta-BOcKPaLE.mjs.map → descriptor-meta-DEuXJfpR.mjs.map} +1 -1
- package/dist/{diff-database-schema-BOsDnH64.mjs → diff-database-schema-D2sjvMw9.mjs} +55 -19
- package/dist/diff-database-schema-D2sjvMw9.mjs.map +1 -0
- package/dist/diff-database-schema.d.mts +4 -4
- package/dist/diff-database-schema.d.mts.map +1 -1
- package/dist/diff-database-schema.mjs +1 -1
- package/dist/issue-planner.d.mts +1 -1
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +2 -2
- package/dist/migration.mjs +2 -2
- package/dist/{nodes-BtQyZha6.d.mts → nodes-Bc2N3tMy.d.mts} +27 -3
- package/dist/nodes-Bc2N3tMy.d.mts.map +1 -0
- package/dist/{nodes-B815pj_X.mjs → nodes-DJC5B8Id.mjs} +32 -2
- package/dist/nodes-DJC5B8Id.mjs.map +1 -0
- package/dist/{op-factory-call-DxNNKUeZ.mjs → op-factory-call-C4flTtTG.mjs} +105 -6
- package/dist/op-factory-call-C4flTtTG.mjs.map +1 -0
- package/dist/{op-factory-call-D6_7-7Vc.d.mts → op-factory-call-CSIg5XDu.d.mts} +26 -3
- package/dist/{op-factory-call-D6_7-7Vc.d.mts.map → op-factory-call-CSIg5XDu.d.mts.map} +1 -1
- package/dist/op-factory-call.d.mts +2 -2
- package/dist/op-factory-call.mjs +2 -2
- package/dist/pack.d.mts +146 -3
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-CNrc1Odu.mjs → planner-BtEd5LMr.mjs} +32 -64
- package/dist/planner-BtEd5LMr.mjs.map +1 -0
- package/dist/{planner-ddl-builders-B8Nn6nHN.mjs → planner-ddl-builders-BKlmGDJl.mjs} +7 -3
- package/dist/planner-ddl-builders-BKlmGDJl.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-ddl-builders.mjs +1 -1
- package/dist/{planner-produced-postgres-migration-a-tjfKsA.d.mts → planner-produced-postgres-migration-CXue-6M9.d.mts} +2 -2
- package/dist/{planner-produced-postgres-migration-a-tjfKsA.d.mts.map → planner-produced-postgres-migration-CXue-6M9.d.mts.map} +1 -1
- package/dist/{planner-produced-postgres-migration-NI-oGKcw.mjs → planner-produced-postgres-migration-Jat3hg4u.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-NI-oGKcw.mjs.map → planner-produced-postgres-migration-Jat3hg4u.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-AXoxB1Jl.mjs → planner-sql-checks-Br1c_QsH.mjs} +3 -3
- package/dist/{planner-sql-checks-AXoxB1Jl.mjs.map → planner-sql-checks-Br1c_QsH.mjs.map} +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/planner.d.mts +3 -3
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +2 -2
- package/dist/{postgres-contract-view-Dg-N7KA7.mjs → postgres-contract-view-BAPW0ec1.mjs} +3 -3
- package/dist/{postgres-contract-view-Dg-N7KA7.mjs.map → postgres-contract-view-BAPW0ec1.mjs.map} +1 -1
- package/dist/{postgres-database-schema-node-CfdTY-Qs.d.mts → postgres-database-schema-node-CJv5bfbs.d.mts} +70 -26
- package/dist/postgres-database-schema-node-CJv5bfbs.d.mts.map +1 -0
- package/dist/{postgres-migration-ChyRsWvE.mjs → postgres-migration-ChLMQRd-.mjs} +19 -3
- package/dist/postgres-migration-ChLMQRd-.mjs.map +1 -0
- package/dist/{postgres-migration-Bzzi0Asr.d.mts → postgres-migration-DkmgGNcv.d.mts} +21 -2
- package/dist/postgres-migration-DkmgGNcv.d.mts.map +1 -0
- package/dist/{postgres-role-schema-node-BiSTCTNg.mjs → postgres-role-schema-node-Cm-j0ZGM.mjs} +20 -25
- package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs.map +1 -0
- package/dist/{postgres-schema-DTLA_aRi.mjs → postgres-schema-DWQ0-CPb.mjs} +32 -4
- package/dist/postgres-schema-DWQ0-CPb.mjs.map +1 -0
- package/dist/{postgres-schema-CU4gF6QZ.d.mts → postgres-schema-DsrtYp2v.d.mts} +13 -1
- package/dist/postgres-schema-DsrtYp2v.d.mts.map +1 -0
- package/dist/{postgres-table-schema-node-9FCtCUz2.mjs → postgres-table-schema-node-D6LvInCe.mjs} +71 -8
- package/dist/postgres-table-schema-node-D6LvInCe.mjs.map +1 -0
- package/dist/{resolve-ddl-schema-Ca88Tg6W.mjs → resolve-ddl-schema-CAza65Iy.mjs} +2 -2
- package/dist/{resolve-ddl-schema-Ca88Tg6W.mjs.map → resolve-ddl-schema-CAza65Iy.mjs.map} +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/schema-ir-annotations.mjs +1 -1
- 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 +3 -3
- package/dist/types.mjs +4 -4
- package/package.json +20 -20
- package/src/contract-free/ddl.ts +27 -0
- package/src/core/authoring.ts +136 -25
- package/src/core/ddl/nodes.ts +44 -0
- package/src/core/migrations/contract-to-postgres-database-schema-node.ts +12 -1
- package/src/core/migrations/control-policy.ts +172 -45
- package/src/core/migrations/diff-database-schema.ts +48 -13
- package/src/core/migrations/issue-planner.ts +77 -4
- package/src/core/migrations/op-factory-call.ts +84 -0
- package/src/core/migrations/operations/native-enum-types.ts +62 -0
- package/src/core/migrations/planner-ddl-builders.ts +12 -2
- package/src/core/migrations/planner.ts +30 -62
- package/src/core/migrations/postgres-migration.ts +31 -0
- package/src/core/migrations/verify-postgres-namespaces.ts +0 -1
- package/src/core/postgres-role.ts +22 -0
- package/src/core/postgres-schema.ts +22 -1
- package/src/core/postgres-validators.ts +1 -0
- package/src/core/psl-infer/infer-psl-contract.ts +7 -16
- package/src/core/schema-ir/node-storage-coordinate.ts +26 -0
- package/src/core/schema-ir/postgres-database-schema-node.ts +5 -4
- package/src/core/schema-ir/postgres-namespace-schema-node.ts +18 -27
- package/src/core/schema-ir/postgres-native-enum-schema-node.ts +83 -0
- package/src/core/schema-ir/postgres-role-schema-node.ts +4 -2
- package/src/core/schema-ir/schema-node-kinds.ts +19 -3
- package/src/core/sql-utils.ts +15 -2
- package/src/exports/ddl.ts +2 -0
- package/src/exports/op-factory-call.ts +2 -0
- package/src/exports/sql-utils.ts +1 -0
- package/src/exports/types.ts +4 -1
- package/dist/authoring-WkqG_MkU.mjs.map +0 -1
- package/dist/control-policy-Co_13Hxa.mjs.map +0 -1
- package/dist/diff-database-schema-BOsDnH64.mjs.map +0 -1
- package/dist/nodes-B815pj_X.mjs.map +0 -1
- package/dist/nodes-BtQyZha6.d.mts.map +0 -1
- package/dist/op-factory-call-DxNNKUeZ.mjs.map +0 -1
- package/dist/planner-CNrc1Odu.mjs.map +0 -1
- package/dist/planner-ddl-builders-B8Nn6nHN.mjs.map +0 -1
- package/dist/postgres-database-schema-node-CfdTY-Qs.d.mts.map +0 -1
- package/dist/postgres-migration-Bzzi0Asr.d.mts.map +0 -1
- package/dist/postgres-migration-ChyRsWvE.mjs.map +0 -1
- package/dist/postgres-role-schema-node-BiSTCTNg.mjs.map +0 -1
- package/dist/postgres-schema-CU4gF6QZ.d.mts.map +0 -1
- package/dist/postgres-schema-DTLA_aRi.mjs.map +0 -1
- package/dist/postgres-table-schema-node-9FCtCUz2.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/target-postgres",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.62",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Postgres target pack for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/cli": "0.14.0-dev.
|
|
10
|
-
"@prisma-next/contract": "0.14.0-dev.
|
|
11
|
-
"@prisma-next/errors": "0.14.0-dev.
|
|
12
|
-
"@prisma-next/family-sql": "0.14.0-dev.
|
|
13
|
-
"@prisma-next/framework-components": "0.14.0-dev.
|
|
14
|
-
"@prisma-next/migration-tools": "0.14.0-dev.
|
|
15
|
-
"@prisma-next/psl-parser": "0.14.0-dev.
|
|
16
|
-
"@prisma-next/sql-contract": "0.14.0-dev.
|
|
17
|
-
"@prisma-next/sql-errors": "0.14.0-dev.
|
|
18
|
-
"@prisma-next/sql-operations": "0.14.0-dev.
|
|
19
|
-
"@prisma-next/sql-relational-core": "0.14.0-dev.
|
|
20
|
-
"@prisma-next/sql-schema-ir": "0.14.0-dev.
|
|
21
|
-
"@prisma-next/ts-render": "0.14.0-dev.
|
|
22
|
-
"@prisma-next/utils": "0.14.0-dev.
|
|
9
|
+
"@prisma-next/cli": "0.14.0-dev.62",
|
|
10
|
+
"@prisma-next/contract": "0.14.0-dev.62",
|
|
11
|
+
"@prisma-next/errors": "0.14.0-dev.62",
|
|
12
|
+
"@prisma-next/family-sql": "0.14.0-dev.62",
|
|
13
|
+
"@prisma-next/framework-components": "0.14.0-dev.62",
|
|
14
|
+
"@prisma-next/migration-tools": "0.14.0-dev.62",
|
|
15
|
+
"@prisma-next/psl-parser": "0.14.0-dev.62",
|
|
16
|
+
"@prisma-next/sql-contract": "0.14.0-dev.62",
|
|
17
|
+
"@prisma-next/sql-errors": "0.14.0-dev.62",
|
|
18
|
+
"@prisma-next/sql-operations": "0.14.0-dev.62",
|
|
19
|
+
"@prisma-next/sql-relational-core": "0.14.0-dev.62",
|
|
20
|
+
"@prisma-next/sql-schema-ir": "0.14.0-dev.62",
|
|
21
|
+
"@prisma-next/ts-render": "0.14.0-dev.62",
|
|
22
|
+
"@prisma-next/utils": "0.14.0-dev.62",
|
|
23
23
|
"@standard-schema/spec": "^1.1.0",
|
|
24
24
|
"arktype": "^2.2.0",
|
|
25
25
|
"pathe": "^2.0.3"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@prisma-next/psl-printer": "0.14.0-dev.
|
|
29
|
-
"@prisma-next/sql-contract-psl": "0.14.0-dev.
|
|
30
|
-
"@prisma-next/test-utils": "0.14.0-dev.
|
|
31
|
-
"@prisma-next/tsconfig": "0.14.0-dev.
|
|
32
|
-
"@prisma-next/tsdown": "0.14.0-dev.
|
|
28
|
+
"@prisma-next/psl-printer": "0.14.0-dev.62",
|
|
29
|
+
"@prisma-next/sql-contract-psl": "0.14.0-dev.62",
|
|
30
|
+
"@prisma-next/test-utils": "0.14.0-dev.62",
|
|
31
|
+
"@prisma-next/tsconfig": "0.14.0-dev.62",
|
|
32
|
+
"@prisma-next/tsdown": "0.14.0-dev.62",
|
|
33
33
|
"tsdown": "0.22.1",
|
|
34
34
|
"typescript": "5.9.3",
|
|
35
35
|
"vitest": "4.1.8"
|
package/src/contract-free/ddl.ts
CHANGED
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
PostgresCreatePolicy,
|
|
9
9
|
PostgresCreateSchema,
|
|
10
10
|
PostgresCreateTable,
|
|
11
|
+
PostgresCreateType,
|
|
11
12
|
PostgresDisableRowLevelSecurity,
|
|
12
13
|
PostgresDropPolicy,
|
|
14
|
+
PostgresDropType,
|
|
13
15
|
type RlsPolicyOperation,
|
|
14
16
|
} from '../core/ddl/nodes';
|
|
15
17
|
|
|
@@ -48,6 +50,31 @@ export function createSchema(options: {
|
|
|
48
50
|
return new PostgresCreateSchema(options);
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Build a Postgres `CREATE TYPE … AS ENUM (…)` DDL node. The type name (and
|
|
55
|
+
* optional schema) are quoted by the renderer; the enum member `values` are
|
|
56
|
+
* emitted as single-quote-escaped string literals. An absent `schema` renders
|
|
57
|
+
* the type name unqualified so the connection's `search_path` resolves it.
|
|
58
|
+
*/
|
|
59
|
+
export function createType(options: {
|
|
60
|
+
readonly schema?: string;
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly values: readonly string[];
|
|
63
|
+
}): PostgresCreateType {
|
|
64
|
+
return new PostgresCreateType(options);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Build a Postgres `DROP TYPE` DDL node. See {@link createType} for the
|
|
69
|
+
* identifier-quoting and unqualified-when-schemaless behaviour.
|
|
70
|
+
*/
|
|
71
|
+
export function dropType(options: {
|
|
72
|
+
readonly schema?: string;
|
|
73
|
+
readonly name: string;
|
|
74
|
+
}): PostgresDropType {
|
|
75
|
+
return new PostgresDropType(options);
|
|
76
|
+
}
|
|
77
|
+
|
|
51
78
|
/**
|
|
52
79
|
* Build an `ADD COLUMN` action for use inside {@link alterTable}.
|
|
53
80
|
* The column is a structured `DdlColumn` so codec-encoded defaults flow
|
package/src/core/authoring.ts
CHANGED
|
@@ -12,10 +12,11 @@ import type {
|
|
|
12
12
|
} from '@prisma-next/framework-components/authoring';
|
|
13
13
|
import { modelAttribute } from '@prisma-next/psl-parser';
|
|
14
14
|
import type { SqlValueSetDerivingEntityTypeOutput } from '@prisma-next/sql-contract/value-set-derivation-hook';
|
|
15
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
15
16
|
import { PG_ENUM_CODEC_ID } from './codec-ids';
|
|
16
17
|
import { PostgresNativeEnum } from './postgres-native-enum';
|
|
17
18
|
import { PostgresRlsEnablement, type PostgresRlsEnablementInput } from './postgres-rls-enablement';
|
|
18
|
-
import { PostgresRlsPolicy } from './postgres-rls-policy';
|
|
19
|
+
import { PostgresRlsPolicy, type RlsPolicyOperation } from './postgres-rls-policy';
|
|
19
20
|
import { PostgresRole, type PostgresRoleInput } from './postgres-role';
|
|
20
21
|
import {
|
|
21
22
|
PostgresNativeEnumSchema,
|
|
@@ -50,6 +51,35 @@ export interface RlsPolicyExtensionBlock extends PslExtensionBlock {
|
|
|
50
51
|
readonly namespaceId: string;
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Maps a `policy_<op>` keyword to the RLS operation it authors. The keyword
|
|
56
|
+
* IS the operation (per the project's rejection of a `policy { operation = … }`
|
|
57
|
+
* conditional block).
|
|
58
|
+
*/
|
|
59
|
+
const POLICY_KEYWORD_OPERATION: Readonly<Record<string, RlsPolicyOperation>> = {
|
|
60
|
+
policy_select: 'select',
|
|
61
|
+
policy_insert: 'insert',
|
|
62
|
+
policy_update: 'update',
|
|
63
|
+
policy_delete: 'delete',
|
|
64
|
+
policy_all: 'all',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Which predicate each RLS operation admits, mirroring Postgres: SELECT and
|
|
69
|
+
* DELETE decide row visibility/eligibility with `USING` only; INSERT validates
|
|
70
|
+
* the new row with `WITH CHECK` only; UPDATE and ALL take both. A predicate
|
|
71
|
+
* outside this set is a load-time error (see {@link lowerRlsPolicyFromBlock}).
|
|
72
|
+
*/
|
|
73
|
+
const POLICY_OPERATION_PREDICATES: Readonly<
|
|
74
|
+
Record<RlsPolicyOperation, { readonly using: boolean; readonly withCheck: boolean }>
|
|
75
|
+
> = {
|
|
76
|
+
select: { using: true, withCheck: false },
|
|
77
|
+
insert: { using: false, withCheck: true },
|
|
78
|
+
update: { using: true, withCheck: true },
|
|
79
|
+
delete: { using: true, withCheck: false },
|
|
80
|
+
all: { using: true, withCheck: true },
|
|
81
|
+
};
|
|
82
|
+
|
|
53
83
|
function readRefParam(block: PslExtensionBlock, key: string): string | undefined {
|
|
54
84
|
const param = block.parameters[key];
|
|
55
85
|
return param?.kind === 'ref' ? param.identifier : undefined;
|
|
@@ -101,18 +131,43 @@ function unwrapQuotedString(raw: string): string {
|
|
|
101
131
|
|
|
102
132
|
function lowerRlsPolicyFromBlock(
|
|
103
133
|
block: RlsPolicyExtensionBlock,
|
|
104
|
-
|
|
105
|
-
): PostgresRlsPolicy {
|
|
134
|
+
ctx: AuthoringEntityContext,
|
|
135
|
+
): PostgresRlsPolicy | undefined {
|
|
106
136
|
const prefix = block.name;
|
|
137
|
+
const operation = POLICY_KEYWORD_OPERATION[block.keyword] ?? 'select';
|
|
107
138
|
const targetModelName = readRefParam(block, 'target') ?? '';
|
|
108
139
|
const tableName = targetModelName.charAt(0).toLowerCase() + targetModelName.slice(1);
|
|
109
140
|
const roles = [...readListRefParams(block, 'roles')].sort();
|
|
110
|
-
|
|
141
|
+
|
|
142
|
+
const usingRaw = readValueParam(block, 'using');
|
|
143
|
+
const withCheckRaw = readValueParam(block, 'withCheck');
|
|
144
|
+
|
|
145
|
+
// Reject a predicate the operation does not take (e.g. `using` on INSERT, or
|
|
146
|
+
// `withCheck` on SELECT/DELETE). The descriptor's param set already omits it,
|
|
147
|
+
// but the generic descriptor validator is not wired into the SQL-family
|
|
148
|
+
// interpreter, so the lowering enforces the per-operation predicate matrix
|
|
149
|
+
// directly — a wrong predicate is a load-time diagnostic, not a silent drop.
|
|
150
|
+
const support = POLICY_OPERATION_PREDICATES[operation];
|
|
151
|
+
const rejectPredicate = (predicate: 'using' | 'withCheck'): undefined => {
|
|
152
|
+
ctx.diagnostics?.push({
|
|
153
|
+
code: 'PSL_RLS_PREDICATE_NOT_FOR_OPERATION',
|
|
154
|
+
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'}.`,
|
|
155
|
+
sourceId: ctx.sourceId ?? 'unknown',
|
|
156
|
+
span: block.parameters[predicate]?.span ?? block.span,
|
|
157
|
+
});
|
|
158
|
+
return undefined;
|
|
159
|
+
};
|
|
160
|
+
if (usingRaw !== undefined && !support.using) return rejectPredicate('using');
|
|
161
|
+
if (withCheckRaw !== undefined && !support.withCheck) return rejectPredicate('withCheck');
|
|
162
|
+
|
|
163
|
+
const using = usingRaw !== undefined ? unwrapQuotedString(usingRaw) : undefined;
|
|
164
|
+
const withCheck = withCheckRaw !== undefined ? unwrapQuotedString(withCheckRaw) : undefined;
|
|
111
165
|
|
|
112
166
|
const wireHash = computeContentHash({
|
|
113
|
-
using
|
|
167
|
+
...ifDefined('using', using !== undefined ? normalizePredicate(using) : undefined),
|
|
168
|
+
...ifDefined('withCheck', withCheck !== undefined ? normalizePredicate(withCheck) : undefined),
|
|
114
169
|
roles,
|
|
115
|
-
operation
|
|
170
|
+
operation,
|
|
116
171
|
permissive: true,
|
|
117
172
|
});
|
|
118
173
|
const wireName = formatRlsPolicyWireName(prefix, wireHash);
|
|
@@ -122,9 +177,10 @@ function lowerRlsPolicyFromBlock(
|
|
|
122
177
|
prefix,
|
|
123
178
|
tableName,
|
|
124
179
|
namespaceId: block.namespaceId,
|
|
125
|
-
operation
|
|
180
|
+
operation,
|
|
126
181
|
roles,
|
|
127
|
-
using,
|
|
182
|
+
...ifDefined('using', using),
|
|
183
|
+
...ifDefined('withCheck', withCheck),
|
|
128
184
|
permissive: true,
|
|
129
185
|
});
|
|
130
186
|
}
|
|
@@ -298,13 +354,10 @@ export const postgresAuthoringEntityTypes = {
|
|
|
298
354
|
* the family pack instead.
|
|
299
355
|
*/
|
|
300
356
|
/**
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
* interpreter (a later dispatch). The `discriminator` matches
|
|
306
|
-
* `PostgresRlsPolicy.kind` so the parsed block node carries the same
|
|
307
|
-
* discriminant as the IR class it will lower to.
|
|
357
|
+
* Shared parameter descriptors for the five `policy_<op>` PSL block
|
|
358
|
+
* keywords. All five share the `policy` discriminator — the parser
|
|
359
|
+
* dispatches by keyword (see the framework's PSL-block SPI), and every
|
|
360
|
+
* keyword's factory lowers to `PostgresRlsPolicy` via `lowerRlsPolicyFromBlock`.
|
|
308
361
|
*
|
|
309
362
|
* The `roles` list uses `scope:'cross-space'` because same-namespace
|
|
310
363
|
* role ref resolution requires PSL namespace entries keyed by `refKind`
|
|
@@ -313,24 +366,82 @@ export const postgresAuthoringEntityTypes = {
|
|
|
313
366
|
* slice 4 (cross-space roles). Until then cross-space passes validation
|
|
314
367
|
* unconditionally and the authored role names flow through unchanged.
|
|
315
368
|
*/
|
|
369
|
+
const policyTargetParam = {
|
|
370
|
+
kind: 'ref',
|
|
371
|
+
refKind: 'model',
|
|
372
|
+
scope: 'same-namespace',
|
|
373
|
+
required: true,
|
|
374
|
+
} as const;
|
|
375
|
+
const policyRolesParam = {
|
|
376
|
+
kind: 'list',
|
|
377
|
+
of: { kind: 'ref', refKind: 'role', scope: 'cross-space' },
|
|
378
|
+
} as const;
|
|
379
|
+
const policyPredicateParam = { kind: 'value', codecId: 'pg/text@1', required: true } as const;
|
|
380
|
+
// A policy may only target an RLS-controlled model: the model named by
|
|
381
|
+
// `target` must declare `@@rls`, or the load fails with a diagnostic naming
|
|
382
|
+
// the model and the policy prefix.
|
|
383
|
+
const policyRequiresRls = { parameter: 'target', attribute: 'rls' } as const;
|
|
384
|
+
|
|
316
385
|
export const postgresAuthoringPslBlockDescriptors = {
|
|
386
|
+
// The predicate param set per keyword mirrors Postgres: SELECT/DELETE take
|
|
387
|
+
// USING only; INSERT takes WITH CHECK only; UPDATE/ALL take both. The
|
|
388
|
+
// per-operation predicate matrix is enforced in `lowerRlsPolicyFromBlock`
|
|
389
|
+
// (a wrong predicate for the operation is a load-time diagnostic there),
|
|
390
|
+
// since the generic descriptor validator is not wired into the SQL-family
|
|
391
|
+
// interpreter.
|
|
317
392
|
policy_select: {
|
|
318
393
|
kind: 'pslBlock',
|
|
319
394
|
keyword: 'policy_select',
|
|
320
395
|
discriminator: 'policy',
|
|
321
396
|
name: { required: true },
|
|
397
|
+
parameters: { target: policyTargetParam, roles: policyRolesParam, using: policyPredicateParam },
|
|
398
|
+
requiresModelAttribute: policyRequiresRls,
|
|
399
|
+
},
|
|
400
|
+
policy_delete: {
|
|
401
|
+
kind: 'pslBlock',
|
|
402
|
+
keyword: 'policy_delete',
|
|
403
|
+
discriminator: 'policy',
|
|
404
|
+
name: { required: true },
|
|
405
|
+
parameters: { target: policyTargetParam, roles: policyRolesParam, using: policyPredicateParam },
|
|
406
|
+
requiresModelAttribute: policyRequiresRls,
|
|
407
|
+
},
|
|
408
|
+
policy_insert: {
|
|
409
|
+
kind: 'pslBlock',
|
|
410
|
+
keyword: 'policy_insert',
|
|
411
|
+
discriminator: 'policy',
|
|
412
|
+
name: { required: true },
|
|
322
413
|
parameters: {
|
|
323
|
-
target:
|
|
324
|
-
roles:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
414
|
+
target: policyTargetParam,
|
|
415
|
+
roles: policyRolesParam,
|
|
416
|
+
withCheck: policyPredicateParam,
|
|
417
|
+
},
|
|
418
|
+
requiresModelAttribute: policyRequiresRls,
|
|
419
|
+
},
|
|
420
|
+
policy_update: {
|
|
421
|
+
kind: 'pslBlock',
|
|
422
|
+
keyword: 'policy_update',
|
|
423
|
+
discriminator: 'policy',
|
|
424
|
+
name: { required: true },
|
|
425
|
+
parameters: {
|
|
426
|
+
target: policyTargetParam,
|
|
427
|
+
roles: policyRolesParam,
|
|
428
|
+
using: policyPredicateParam,
|
|
429
|
+
withCheck: policyPredicateParam,
|
|
430
|
+
},
|
|
431
|
+
requiresModelAttribute: policyRequiresRls,
|
|
432
|
+
},
|
|
433
|
+
policy_all: {
|
|
434
|
+
kind: 'pslBlock',
|
|
435
|
+
keyword: 'policy_all',
|
|
436
|
+
discriminator: 'policy',
|
|
437
|
+
name: { required: true },
|
|
438
|
+
parameters: {
|
|
439
|
+
target: policyTargetParam,
|
|
440
|
+
roles: policyRolesParam,
|
|
441
|
+
using: policyPredicateParam,
|
|
442
|
+
withCheck: policyPredicateParam,
|
|
329
443
|
},
|
|
330
|
-
|
|
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' },
|
|
444
|
+
requiresModelAttribute: policyRequiresRls,
|
|
334
445
|
},
|
|
335
446
|
/**
|
|
336
447
|
* PSL block descriptor for `native_enum`.
|
package/src/core/ddl/nodes.ts
CHANGED
|
@@ -67,6 +67,8 @@ export type AnyAlterTableAction = AddColumnAction | DropDefaultAction;
|
|
|
67
67
|
export interface PostgresDdlVisitor<R> {
|
|
68
68
|
createTable(node: PostgresCreateTable): R;
|
|
69
69
|
createSchema(node: PostgresCreateSchema): R;
|
|
70
|
+
createType(node: PostgresCreateType): R;
|
|
71
|
+
dropType(node: PostgresDropType): R;
|
|
70
72
|
alterTable(node: PostgresAlterTable): R;
|
|
71
73
|
createPolicy(node: PostgresCreatePolicy): R;
|
|
72
74
|
dropPolicy(node: PostgresDropPolicy): R;
|
|
@@ -134,6 +136,46 @@ export class PostgresCreateSchema extends PostgresDdlNode {
|
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
export class PostgresCreateType extends PostgresDdlNode {
|
|
140
|
+
readonly kind = 'create-type' as const;
|
|
141
|
+
readonly schema: string | undefined;
|
|
142
|
+
readonly name: string;
|
|
143
|
+
readonly values: ReadonlyArray<string>;
|
|
144
|
+
|
|
145
|
+
constructor(options: {
|
|
146
|
+
readonly schema?: string;
|
|
147
|
+
readonly name: string;
|
|
148
|
+
readonly values: readonly string[];
|
|
149
|
+
}) {
|
|
150
|
+
super();
|
|
151
|
+
this.schema = options.schema;
|
|
152
|
+
this.name = options.name;
|
|
153
|
+
this.values = Object.freeze([...options.values]);
|
|
154
|
+
this.freeze();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
158
|
+
return visitor.createType(this);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export class PostgresDropType extends PostgresDdlNode {
|
|
163
|
+
readonly kind = 'drop-type' as const;
|
|
164
|
+
readonly schema: string | undefined;
|
|
165
|
+
readonly name: string;
|
|
166
|
+
|
|
167
|
+
constructor(options: { readonly schema?: string; readonly name: string }) {
|
|
168
|
+
super();
|
|
169
|
+
this.schema = options.schema;
|
|
170
|
+
this.name = options.name;
|
|
171
|
+
this.freeze();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
175
|
+
return visitor.dropType(this);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
137
179
|
export class PostgresAlterTable extends PostgresDdlNode {
|
|
138
180
|
readonly kind = 'alter-table' as const;
|
|
139
181
|
readonly table: string;
|
|
@@ -262,6 +304,8 @@ export class PostgresDisableRowLevelSecurity extends PostgresDdlNode {
|
|
|
262
304
|
export type AnyPostgresDdlNode =
|
|
263
305
|
| PostgresCreateTable
|
|
264
306
|
| PostgresCreateSchema
|
|
307
|
+
| PostgresCreateType
|
|
308
|
+
| PostgresDropType
|
|
265
309
|
| PostgresAlterTable
|
|
266
310
|
| PostgresCreatePolicy
|
|
267
311
|
| PostgresDropPolicy
|
|
@@ -8,6 +8,7 @@ import type { PostgresContract } from '../postgres-schema';
|
|
|
8
8
|
import { isPostgresSchema } from '../postgres-schema';
|
|
9
9
|
import { PostgresDatabaseSchemaNode } from '../schema-ir/postgres-database-schema-node';
|
|
10
10
|
import { PostgresNamespaceSchemaNode } from '../schema-ir/postgres-namespace-schema-node';
|
|
11
|
+
import { PostgresNativeEnumSchemaNode } from '../schema-ir/postgres-native-enum-schema-node';
|
|
11
12
|
import { PostgresPolicySchemaNode } from '../schema-ir/postgres-policy-schema-node';
|
|
12
13
|
import { PostgresRoleSchemaNode } from '../schema-ir/postgres-role-schema-node';
|
|
13
14
|
import { PostgresTableSchemaNode } from '../schema-ir/postgres-table-schema-node';
|
|
@@ -140,10 +141,20 @@ export function contractToPostgresDatabaseSchemaNode(
|
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
const nativeEnums = Object.values(ns.entries.native_enum ?? {}).map(
|
|
145
|
+
(entity) =>
|
|
146
|
+
new PostgresNativeEnumSchemaNode({
|
|
147
|
+
typeName: entity.typeName,
|
|
148
|
+
namespaceId: ddlSchema,
|
|
149
|
+
members: entity.members,
|
|
150
|
+
...ifDefined('control', entity.control),
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
|
|
143
154
|
namespaces[ddlSchema] = new PostgresNamespaceSchemaNode({
|
|
144
155
|
schemaName: ddlSchema,
|
|
145
156
|
tables,
|
|
146
|
-
|
|
157
|
+
nativeEnums,
|
|
147
158
|
});
|
|
148
159
|
|
|
149
160
|
for (const role of Object.values(ns.role)) {
|