@prisma-next/target-postgres 0.14.0-dev.5 → 0.14.0-dev.50
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-DzHOdWTl.mjs +364 -0
- package/dist/authoring-DzHOdWTl.mjs.map +1 -0
- package/dist/canonicalize-Bn3BM1Cn.mjs +46 -0
- package/dist/canonicalize-Bn3BM1Cn.mjs.map +1 -0
- package/dist/canonicalize-CAbXtVtB.d.mts +37 -0
- package/dist/canonicalize-CAbXtVtB.d.mts.map +1 -0
- package/dist/{codec-ids-CnXu9Qy3.d.mts → codec-ids-BzrFF-I4.d.mts} +3 -2
- package/dist/codec-ids-BzrFF-I4.d.mts.map +1 -0
- package/dist/{codec-ids-BvytN2P8.mjs → codec-ids-C_-Hj6bL.mjs} +3 -2
- package/dist/codec-ids-C_-Hj6bL.mjs.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-BDVmvKAW.d.mts} +3 -2
- package/dist/codec-types-BDVmvKAW.d.mts.map +1 -0
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs--0A5_4Bq.d.mts → codecs-Dk2sxGLv.d.mts} +77 -4
- package/dist/codecs-Dk2sxGLv.d.mts.map +1 -0
- package/dist/codecs.d.mts +1 -1
- package/dist/codecs.mjs +117 -2
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.d.mts +8 -3
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +4 -4
- package/dist/control-policy-DUFgy9jO.mjs +1103 -0
- package/dist/control-policy-DUFgy9jO.mjs.map +1 -0
- package/dist/control.d.mts +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +757 -35
- 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-ujxH2A7r.mjs} +63 -6
- package/dist/ddl-ujxH2A7r.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-CuGDsrG4.mjs +19 -0
- package/dist/descriptor-meta-CuGDsrG4.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-BmSmWcaY.mjs +313 -0
- package/dist/diff-database-schema-BmSmWcaY.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/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-CSkPX3rI.d.mts +120 -0
- package/dist/nodes-CSkPX3rI.d.mts.map +1 -0
- package/dist/{nodes-Bbhs2rwj.mjs → nodes-Dh__NS58.mjs} +56 -2
- package/dist/nodes-Dh__NS58.mjs.map +1 -0
- package/dist/{op-factory-call-D_p5vxwt.mjs → op-factory-call-BKRnMgrB.mjs} +205 -31
- package/dist/op-factory-call-BKRnMgrB.mjs.map +1 -0
- package/dist/{op-factory-call-DmQEc3XV.d.mts → op-factory-call-Dt-Jx5JS.d.mts} +46 -15
- package/dist/op-factory-call-Dt-Jx5JS.d.mts.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 +115 -3
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/planner-BMBRPzsv.mjs +367 -0
- package/dist/planner-BMBRPzsv.mjs.map +1 -0
- package/dist/{planner-ddl-builders-B2wOwLqI.mjs → planner-ddl-builders-B8Nn6nHN.mjs} +12 -27
- package/dist/planner-ddl-builders-B8Nn6nHN.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-produced-postgres-migration-QqHa2C2l.d.mts → planner-produced-postgres-migration-C0a7I1-e.d.mts} +4 -4
- package/dist/{planner-produced-postgres-migration-QqHa2C2l.d.mts.map → planner-produced-postgres-migration-C0a7I1-e.d.mts.map} +1 -1
- package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs → planner-produced-postgres-migration-Dp6IO_gj.mjs} +3 -3
- package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs.map → planner-produced-postgres-migration-Dp6IO_gj.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-Cze3vMfe.mjs} +2 -2
- package/dist/{planner-sql-checks-jqUUGyQR.mjs.map → planner-sql-checks-Cze3vMfe.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 +55 -17
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +3 -2
- package/dist/{postgres-contract-serializer-k3TAcPMY.mjs → postgres-contract-view-3xfUgjnC.mjs} +44 -41
- package/dist/postgres-contract-view-3xfUgjnC.mjs.map +1 -0
- package/dist/postgres-contract-view-C9j5cqP0.d.mts +34 -0
- package/dist/postgres-contract-view-C9j5cqP0.d.mts.map +1 -0
- package/dist/postgres-database-schema-node-C9bTuMrd.d.mts +190 -0
- package/dist/postgres-database-schema-node-C9bTuMrd.d.mts.map +1 -0
- package/dist/{postgres-migration-B5jKrXv3.mjs → postgres-migration-D0jwzYDT.mjs} +21 -2
- package/dist/postgres-migration-D0jwzYDT.mjs.map +1 -0
- package/dist/{postgres-migration-Y4YBJqkS.d.mts → postgres-migration-DFaxuRyI.d.mts} +20 -7
- package/dist/postgres-migration-DFaxuRyI.d.mts.map +1 -0
- package/dist/postgres-native-enum-xdiqmBf_.mjs +41 -0
- package/dist/postgres-native-enum-xdiqmBf_.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-schema-COGZ1ark.mjs → postgres-schema-CajYAwny.mjs} +135 -7
- package/dist/postgres-schema-CajYAwny.mjs.map +1 -0
- package/dist/postgres-schema-DqnhQRvR.d.mts +226 -0
- package/dist/postgres-schema-DqnhQRvR.d.mts.map +1 -0
- package/dist/postgres-table-schema-node-BgaSrxYN.mjs +249 -0
- package/dist/postgres-table-schema-node-BgaSrxYN.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-Bv1ZvjX8.mjs +22 -0
- package/dist/resolve-ddl-schema-Bv1ZvjX8.mjs.map +1 -0
- package/dist/rls-canonicalize.d.mts +2 -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/schema-node-kinds-ClScchhi.mjs +76 -0
- package/dist/schema-node-kinds-ClScchhi.mjs.map +1 -0
- package/dist/types.d.mts +4 -140
- package/dist/types.mjs +3 -2
- package/package.json +23 -17
- package/src/contract-free/checks.ts +73 -0
- package/src/contract-free/ddl.ts +45 -1
- package/src/core/authoring.ts +287 -2
- package/src/core/codec-ids.ts +1 -0
- package/src/core/codec-type-map.ts +2 -0
- package/src/core/codecs.ts +141 -1
- package/src/core/ddl/nodes.ts +94 -2
- package/src/core/default-normalizer.ts +122 -2
- package/src/core/descriptor-meta.ts +6 -1
- package/src/core/entity-kinds.ts +30 -0
- 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 +149 -0
- package/src/core/migrations/control-policy.ts +70 -47
- package/src/core/migrations/diff-database-schema.ts +280 -0
- package/src/core/migrations/issue-planner.ts +647 -652
- package/src/core/migrations/op-factory-call.ts +109 -21
- 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/rls.ts +106 -0
- package/src/core/migrations/operations/shared.ts +0 -30
- package/src/core/migrations/planner-ddl-builders.ts +20 -58
- 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 +297 -59
- package/src/core/migrations/postgres-migration.ts +34 -4
- 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 +10 -16
- package/src/core/migrations/verify-postgres-namespaces.ts +47 -30
- package/src/core/namespace-ids.ts +3 -0
- package/src/core/postgres-contract-serializer.ts +41 -71
- package/src/core/postgres-contract-view.ts +48 -0
- package/src/core/postgres-native-enum.ts +51 -0
- package/src/core/postgres-rls-policy.ts +64 -0
- package/src/core/postgres-role.ts +37 -0
- package/src/core/postgres-schema-verifier.ts +10 -7
- package/src/core/postgres-schema.ts +62 -14
- package/src/core/postgres-validators.ts +27 -0
- package/src/core/psl-infer/infer-psl-contract.ts +1068 -0
- package/src/core/psl-infer/postgres-default-mapping.ts +16 -0
- package/src/core/psl-infer/postgres-type-map.ts +157 -0
- package/src/core/rls/canonicalize.ts +48 -0
- package/src/core/schema-ir/postgres-database-schema-node.ts +60 -0
- package/src/core/schema-ir/postgres-namespace-schema-node.ts +60 -0
- package/src/core/schema-ir/postgres-policy-schema-node.ts +90 -0
- package/src/core/schema-ir/postgres-role-schema-node.ts +63 -0
- package/src/core/schema-ir/postgres-table-schema-node.ts +118 -0
- package/src/core/schema-ir/schema-node-kinds.ts +106 -0
- package/src/exports/contract-free.ts +7 -1
- package/src/exports/control.ts +27 -33
- package/src/exports/ddl.ts +4 -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 +1 -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 +6 -0
- package/src/exports/runtime.ts +1 -0
- package/src/exports/schema-ir-annotations.ts +1 -0
- package/src/exports/types.ts +28 -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/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.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
|
@@ -12,7 +12,6 @@ import type {
|
|
|
12
12
|
SqlMigrationRunnerSuccessValue,
|
|
13
13
|
} from '@prisma-next/family-sql/control';
|
|
14
14
|
import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
|
|
15
|
-
import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
|
|
16
15
|
import type { MigrationRunnerResult } from '@prisma-next/framework-components/control';
|
|
17
16
|
import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
|
|
18
17
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
@@ -23,8 +22,6 @@ import { blindCast } from '@prisma-next/utils/casts';
|
|
|
23
22
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
24
23
|
import type { Result } from '@prisma-next/utils/result';
|
|
25
24
|
import { notOk, ok, okVoid } from '@prisma-next/utils/result';
|
|
26
|
-
import { parsePostgresDefault } from '../default-normalizer';
|
|
27
|
-
import { normalizeSchemaNativeType } from '../native-type-normalizer';
|
|
28
25
|
import type { PostgresPlanTargetDetails } from './planner-target-details';
|
|
29
26
|
|
|
30
27
|
interface ApplyPlanSuccessValue {
|
|
@@ -124,30 +121,27 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
|
|
|
124
121
|
applyValue = applyResult.value;
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
// an extension contract.
|
|
124
|
+
// Verify the schema on app-space only: extension spaces don't own
|
|
125
|
+
// user-facing tables, so verifying the destination contract against the
|
|
126
|
+
// database would flag every app-space table as "extra". Delegates to the
|
|
127
|
+
// family `verifySchema` — the same comparison the CLI verify runs.
|
|
132
128
|
if (space === APP_SPACE_ID) {
|
|
133
|
-
const
|
|
129
|
+
const schemaNode = await this.family.introspect({
|
|
134
130
|
driver,
|
|
135
131
|
contract: options.destinationContract,
|
|
136
132
|
});
|
|
137
|
-
const schemaVerifyResult =
|
|
133
|
+
const schemaVerifyResult = this.family.verifySchema({
|
|
138
134
|
contract: options.destinationContract,
|
|
139
|
-
schema:
|
|
135
|
+
schema: schemaNode,
|
|
140
136
|
strict: options.strictVerification ?? true,
|
|
141
|
-
context: options.context ?? {},
|
|
142
|
-
typeMetadataRegistry: this.family.typeMetadataRegistry,
|
|
143
137
|
frameworkComponents: options.frameworkComponents,
|
|
144
|
-
normalizeDefault: parsePostgresDefault,
|
|
145
|
-
normalizeNativeType: normalizeSchemaNativeType,
|
|
146
138
|
});
|
|
147
139
|
if (!schemaVerifyResult.ok) {
|
|
148
140
|
return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
|
|
149
141
|
why: 'The resulting database schema does not satisfy the destination contract.',
|
|
150
|
-
meta: {
|
|
142
|
+
meta: {
|
|
143
|
+
issues: schemaVerifyResult.schema.issues,
|
|
144
|
+
},
|
|
151
145
|
});
|
|
152
146
|
}
|
|
153
147
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
3
3
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
4
4
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
5
|
-
import type {
|
|
5
|
+
import type { SqlSchemaIRNode } from '@prisma-next/sql-schema-ir/types';
|
|
6
|
+
import { DEFAULT_NAMESPACE_ID } from '../namespace-ids';
|
|
6
7
|
import { isPostgresSchema } from '../postgres-schema';
|
|
8
|
+
import { PostgresDatabaseSchemaNode } from '../schema-ir/postgres-database-schema-node';
|
|
9
|
+
import { PostgresNamespaceSchemaNode } from '../schema-ir/postgres-namespace-schema-node';
|
|
10
|
+
import type { SqlSchemaDiffNode } from '../schema-ir/schema-node-kinds';
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Resolves the live-database schema name for a given namespace
|
|
@@ -23,32 +27,36 @@ function resolveDdlSchemaName(storage: SqlStorage, namespaceId: string): string
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
26
|
-
* Reads the introspected list of schema names from the
|
|
27
|
-
*
|
|
28
|
-
* `
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Reads the introspected list of schema names from the database-root schema
|
|
31
|
+
* node. `existingSchemas` is database-level, so it lives on the
|
|
32
|
+
* `PostgresDatabaseSchemaNode` root — not on the per-schema namespace nodes.
|
|
33
|
+
*
|
|
34
|
+
* Defaults to the always-present `public` schema when the node is not the
|
|
35
|
+
* database root — a fresh Postgres database always carries `public` (unless an
|
|
36
|
+
* operator dropped it manually), so any verifier path that runs without an
|
|
37
|
+
* enriched introspection still suppresses the redundant `CREATE SCHEMA
|
|
38
|
+
* "public"`.
|
|
32
39
|
*
|
|
33
40
|
* Production introspection (`PostgresControlAdapter.introspect`) is the
|
|
34
|
-
* authoritative source: it queries `pg_namespace` and
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* explicitly via the schema IR.
|
|
41
|
+
* authoritative source: it queries `pg_namespace` and sets `existingSchemas`
|
|
42
|
+
* on the returned root. Tests that want to assert against a richer initial
|
|
43
|
+
* state construct a `PostgresDatabaseSchemaNode` explicitly.
|
|
38
44
|
*/
|
|
39
|
-
function existingSchemasFromSchema(schema:
|
|
40
|
-
|
|
41
|
-
.
|
|
42
|
-
const slot = annotations?.pg?.existingSchemas;
|
|
43
|
-
if (Array.isArray(slot)) {
|
|
44
|
-
return slot.filter((s): s is string => typeof s === 'string');
|
|
45
|
+
function existingSchemasFromSchema(schema: SqlSchemaIRNode): readonly string[] {
|
|
46
|
+
if (PostgresDatabaseSchemaNode.is(schema)) {
|
|
47
|
+
return schema.existingSchemas;
|
|
45
48
|
}
|
|
46
|
-
return [
|
|
49
|
+
return [DEFAULT_NAMESPACE_ID];
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
/**
|
|
50
|
-
* Emits a `
|
|
51
|
-
* namespace whose live container does not yet
|
|
53
|
+
* Emits a `postgres-namespace` `not-found` diff issue for every
|
|
54
|
+
* contract-declared Postgres namespace whose live container does not yet
|
|
55
|
+
* exist. The planner prepends these (node-typed, synthesized) to the
|
|
56
|
+
* relational diff issues so a multi-schema plan emits `CREATE SCHEMA`
|
|
57
|
+
* before the tables that need it — a planner-only concern (verify already
|
|
58
|
+
* rejects via the `not-found` table issues a missing schema already
|
|
59
|
+
* produces), so this is not part of the shared diff.
|
|
52
60
|
*
|
|
53
61
|
* A namespace's live container is the schema returned by its
|
|
54
62
|
* polymorphic `ddlSchemaName(storage)` method — named schemas resolve
|
|
@@ -59,28 +67,37 @@ function existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {
|
|
|
59
67
|
* introspected list. `public` is suppressed implicitly because the
|
|
60
68
|
* introspection (or its sensible default) always carries it.
|
|
61
69
|
*
|
|
62
|
-
* Each emitted issue
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
70
|
+
* Each emitted issue's path is `['database', ddlName]` — an ancestor of
|
|
71
|
+
* every table path under that schema, so it must never be run through
|
|
72
|
+
* `coalesceSubtreeIssues` alongside the table diff (it would swallow the
|
|
73
|
+
* table-level `not-found` issues that drive `CREATE TABLE`); the planner
|
|
74
|
+
* adds these AFTER coalescing the relational issues, and they are not
|
|
75
|
+
* subject to sibling-space ownership scoping (mirrors the retired
|
|
76
|
+
* coordinate walk, which prepended namespace issues after that filter).
|
|
66
77
|
*/
|
|
67
78
|
export function verifyPostgresNamespacePresence(input: {
|
|
68
79
|
readonly contract: Contract<SqlStorage>;
|
|
69
|
-
readonly schema:
|
|
70
|
-
}): readonly
|
|
80
|
+
readonly schema: SqlSchemaIRNode;
|
|
81
|
+
}): readonly SchemaDiffIssue<SqlSchemaDiffNode>[] {
|
|
71
82
|
const { contract, schema } = input;
|
|
72
83
|
const existing = new Set(existingSchemasFromSchema(schema));
|
|
73
|
-
const issues:
|
|
84
|
+
const issues: SchemaDiffIssue<SqlSchemaDiffNode>[] = [];
|
|
74
85
|
const namespaceIds = Object.keys(contract.storage.namespaces).sort();
|
|
75
86
|
for (const namespaceId of namespaceIds) {
|
|
76
87
|
if (namespaceId === UNBOUND_NAMESPACE_ID) continue;
|
|
77
88
|
const ddlName = resolveDdlSchemaName(contract.storage, namespaceId);
|
|
78
89
|
if (ddlName === UNBOUND_NAMESPACE_ID) continue;
|
|
79
90
|
if (existing.has(ddlName)) continue;
|
|
91
|
+
const namespace = new PostgresNamespaceSchemaNode({
|
|
92
|
+
schemaName: ddlName,
|
|
93
|
+
tables: {},
|
|
94
|
+
nativeEnumTypeNames: [],
|
|
95
|
+
});
|
|
80
96
|
issues.push({
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
path: ['database', ddlName],
|
|
98
|
+
reason: 'not-found',
|
|
83
99
|
message: `Schema "${ddlName}" is missing from database`,
|
|
100
|
+
expected: namespace,
|
|
84
101
|
});
|
|
85
102
|
}
|
|
86
103
|
return issues;
|
|
@@ -10,20 +10,22 @@ import {
|
|
|
10
10
|
isAuthoringEntityTypeDescriptor,
|
|
11
11
|
} from '@prisma-next/framework-components/authoring';
|
|
12
12
|
import {
|
|
13
|
+
type AnyEntityKindDescriptor,
|
|
13
14
|
type Namespace,
|
|
14
|
-
NamespaceBase,
|
|
15
15
|
UNBOUND_NAMESPACE_ID,
|
|
16
16
|
} from '@prisma-next/framework-components/ir';
|
|
17
|
-
import type {
|
|
17
|
+
import type { SqlNamespaceInput, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
18
18
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
19
19
|
import type { JsonObject } from '@prisma-next/utils/json';
|
|
20
20
|
import { postgresAuthoringEntityTypes } from './authoring';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import { PG_INT_CODEC_ID, PG_TEXT_CODEC_ID } from './codec-ids';
|
|
22
|
+
import { nativeEnumEntityKind, policyEntityKind, roleEntityKind } from './entity-kinds';
|
|
23
|
+
import { PostgresSchema } from './postgres-schema';
|
|
23
24
|
|
|
24
25
|
const POSTGRES_AUTHORING_CTX: AuthoringEntityContext = {
|
|
25
26
|
family: 'sql',
|
|
26
27
|
target: 'postgres',
|
|
28
|
+
enumInferenceCodecs: { text: PG_TEXT_CODEC_ID, int: PG_INT_CODEC_ID },
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
function isAuthoringEntityTypeFactoryOutput(
|
|
@@ -32,7 +34,8 @@ function isAuthoringEntityTypeFactoryOutput(
|
|
|
32
34
|
return (
|
|
33
35
|
typeof output === 'object' &&
|
|
34
36
|
output !== null &&
|
|
35
|
-
|
|
37
|
+
'factory' in output &&
|
|
38
|
+
typeof output.factory === 'function'
|
|
36
39
|
);
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -65,34 +68,34 @@ function collectStorageTypesHydrators(
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
export class PostgresContractSerializer extends SqlContractSerializerBase<Contract<SqlStorage>> {
|
|
68
|
-
constructor() {
|
|
71
|
+
constructor(extraPackEntityKinds: readonly AnyEntityKindDescriptor[] = []) {
|
|
69
72
|
const storageTypesHydrators = collectStorageTypesHydrators(postgresAuthoringEntityTypes);
|
|
70
|
-
super(storageTypesHydrators
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
super(storageTypesHydrators, [
|
|
74
|
+
policyEntityKind,
|
|
75
|
+
roleEntityKind,
|
|
76
|
+
nativeEnumEntityKind,
|
|
77
|
+
...extraPackEntityKinds,
|
|
78
|
+
]);
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
protected override hydrateSqlNamespaceEntry(
|
|
78
82
|
nsId: string,
|
|
79
|
-
raw:
|
|
80
|
-
): Namespace |
|
|
81
|
-
if (raw instanceof NamespaceBase) {
|
|
82
|
-
return raw;
|
|
83
|
-
}
|
|
83
|
+
raw: Record<string, unknown>,
|
|
84
|
+
): Namespace | SqlNamespaceInput {
|
|
84
85
|
const hydrated = blindCast<
|
|
85
|
-
|
|
86
|
-
'
|
|
86
|
+
SqlNamespaceInput,
|
|
87
|
+
'raw is always plain JSON, so super.hydrateSqlNamespaceEntry returns SqlNamespaceInput'
|
|
87
88
|
>(super.hydrateSqlNamespaceEntry(nsId, raw));
|
|
88
89
|
const { id, entries } = hydrated;
|
|
89
90
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (id === UNBOUND_NAMESPACE_ID &&
|
|
91
|
+
const allSlotsEmpty = Object.values(entries).every(
|
|
92
|
+
(slot) => slot === undefined || Object.keys(slot).length === 0,
|
|
93
|
+
);
|
|
94
|
+
if (id === UNBOUND_NAMESPACE_ID && allSlotsEmpty) {
|
|
94
95
|
return PostgresSchema.unbound;
|
|
95
96
|
}
|
|
97
|
+
const valueSetSlot = entries['valueSet'];
|
|
98
|
+
const hasValueSets = valueSetSlot !== undefined && Object.keys(valueSetSlot).length > 0;
|
|
96
99
|
return new PostgresSchema({
|
|
97
100
|
id,
|
|
98
101
|
entries: {
|
|
@@ -106,24 +109,17 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
|
|
|
106
109
|
override serializeContract(contract: Contract<SqlStorage>): JsonObject {
|
|
107
110
|
const { storage, ...rest } = contract;
|
|
108
111
|
const namespacesJson: Record<string, JsonObject> = {};
|
|
112
|
+
// Each namespace serializes to its id, its schema-kind tag, and the
|
|
113
|
+
// base's generic entries walk. Native enums are excluded upstream —
|
|
114
|
+
// carried non-enumerable on `PostgresSchema.entries`, so the walk
|
|
115
|
+
// never sees them.
|
|
109
116
|
for (const [nsId, ns] of Object.entries(storage.namespaces)) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',
|
|
117
|
-
entries: {
|
|
118
|
-
table: Object.fromEntries(
|
|
119
|
-
Object.entries(ns.entries.table ?? {}).map(([tableName, table]) => [
|
|
120
|
-
tableName,
|
|
121
|
-
this.serializeJsonValue(table) as JsonObject,
|
|
122
|
-
]),
|
|
123
|
-
),
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
}
|
|
117
|
+
const isUnboundSlot = ns.id === UNBOUND_NAMESPACE_ID;
|
|
118
|
+
namespacesJson[nsId] = {
|
|
119
|
+
id: ns.id,
|
|
120
|
+
kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',
|
|
121
|
+
entries: this.serializeNamespaceEntries(ns.entries),
|
|
122
|
+
};
|
|
127
123
|
}
|
|
128
124
|
const storageOut: Record<string, unknown> = {
|
|
129
125
|
storageHash: String(storage.storageHash),
|
|
@@ -132,42 +128,16 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
|
|
|
132
128
|
if (storage.types !== undefined) {
|
|
133
129
|
const typesOut: Record<string, JsonObject> = {};
|
|
134
130
|
for (const [name, entry] of Object.entries(storage.types)) {
|
|
135
|
-
typesOut[name] = this.
|
|
131
|
+
typesOut[name] = this.serializeJsonObject(entry);
|
|
136
132
|
}
|
|
137
133
|
storageOut['types'] = typesOut;
|
|
138
134
|
}
|
|
139
|
-
return
|
|
135
|
+
return blindCast<
|
|
136
|
+
JsonObject,
|
|
137
|
+
'contract minus storage plus a JSON-shaped storageOut is a JsonObject'
|
|
138
|
+
>({
|
|
140
139
|
...rest,
|
|
141
140
|
storage: storageOut,
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
private serializePostgresNamespace(ns: PostgresSchema, isUnboundSlot: boolean): JsonObject {
|
|
146
|
-
const tablesOut: Record<string, JsonObject> = {};
|
|
147
|
-
for (const [tableName, table] of Object.entries(ns.table)) {
|
|
148
|
-
tablesOut[tableName] = this.serializeJsonValue(table) as JsonObject;
|
|
149
|
-
}
|
|
150
|
-
const valueSetEntries = ns.valueSet;
|
|
151
|
-
const valueSetOut: Record<string, JsonObject> = {};
|
|
152
|
-
if (valueSetEntries !== undefined) {
|
|
153
|
-
for (const [valueSetName, valueSet] of Object.entries(valueSetEntries)) {
|
|
154
|
-
valueSetOut[valueSetName] = blindCast<
|
|
155
|
-
JsonObject,
|
|
156
|
-
'serializeJsonValue round-trips the value-set node through JSON, yielding a JsonObject'
|
|
157
|
-
>(this.serializeJsonValue(valueSet));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
id: ns.id,
|
|
162
|
-
kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',
|
|
163
|
-
entries: {
|
|
164
|
-
table: tablesOut,
|
|
165
|
-
...(Object.keys(valueSetOut).length > 0 ? { valueSet: valueSetOut } : {}),
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private serializeJsonValue(value: unknown): unknown {
|
|
171
|
-
return JSON.parse(JSON.stringify(value)) as unknown;
|
|
141
|
+
});
|
|
172
142
|
}
|
|
173
143
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
+
import {
|
|
3
|
+
buildSqlSchemaQualifiedView,
|
|
4
|
+
type SqlSchemaQualifiedView,
|
|
5
|
+
} from '@prisma-next/sql-contract/contract-view';
|
|
6
|
+
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
7
|
+
import { PostgresContractSerializer } from './postgres-contract-serializer';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A schema-qualified Postgres contract view: the deserialized contract
|
|
11
|
+
* intersected with a single `namespace` member holding every schema by id. It is
|
|
12
|
+
* substitutable for `Contract` (carries `storage`, `domain`, …) and reaches each
|
|
13
|
+
* schema's entities through `view.namespace.<schema>`:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* const view = PostgresContractView.fromJson<Contract>(contractJson);
|
|
17
|
+
* view.namespace.public.table.users // typed table leaf in the public schema
|
|
18
|
+
* view.namespace.auth.table.users // the auth schema's own users table
|
|
19
|
+
* view.namespace.public.entries.policy.X // pack-contributed kind (RLS / #771 path)
|
|
20
|
+
* view.namespace.__unbound__.table.X // default schema, keyed by its raw id
|
|
21
|
+
* view.storage // the full contract is still present
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* This mirrors the runtime `db.enums.<ns>` keying exactly (the default schema
|
|
25
|
+
* keeps its literal `__unbound__` id). Schema names are NOT promoted to the
|
|
26
|
+
* contract root, so there is no collision with contract envelope fields — a
|
|
27
|
+
* schema named `storage` is `view.namespace.storage`, while `view.storage`
|
|
28
|
+
* stays the contract's `storage`.
|
|
29
|
+
*/
|
|
30
|
+
export type PostgresContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> =
|
|
31
|
+
SqlSchemaQualifiedView<TContract>;
|
|
32
|
+
|
|
33
|
+
export const PostgresContractView = {
|
|
34
|
+
/** Wrap an already-deserialized Postgres contract in a schema-qualified view. */
|
|
35
|
+
from<TContract extends Contract<SqlStorage>>(
|
|
36
|
+
contract: TContract,
|
|
37
|
+
): PostgresContractView<TContract> {
|
|
38
|
+
return buildSqlSchemaQualifiedView(contract);
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/** Deserialize a Postgres contract JSON envelope and wrap it in a view. */
|
|
42
|
+
fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage>>(
|
|
43
|
+
json: unknown,
|
|
44
|
+
): PostgresContractView<TContract> {
|
|
45
|
+
const contract = new PostgresContractSerializer().deserializeContract<TContract>(json);
|
|
46
|
+
return buildSqlSchemaQualifiedView(contract);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ControlPolicy } from '@prisma-next/contract/types';
|
|
2
|
+
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
3
|
+
import { SqlNode } from '@prisma-next/sql-contract/types';
|
|
4
|
+
|
|
5
|
+
export interface PostgresNativeEnumInput {
|
|
6
|
+
/** The Postgres type name (`CREATE TYPE <typeName> AS ENUM (…)`). */
|
|
7
|
+
readonly typeName: string;
|
|
8
|
+
/** Member values in declaration order — this is the Postgres enum sort order. */
|
|
9
|
+
readonly members: readonly string[];
|
|
10
|
+
readonly control?: ControlPolicy;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Postgres contract-IR class for a native enum type (`CREATE TYPE … AS ENUM (…)`).
|
|
15
|
+
*
|
|
16
|
+
* This is an authored, serialized Contract-IR entity — it is registered as an entity
|
|
17
|
+
* kind, extends `SqlNode`, and is stored in `contract.json`. It is NOT a DiffableNode;
|
|
18
|
+
* the schema-diff tree will use `PostgresNativeEnumSchemaNode` when the managed phase
|
|
19
|
+
* builds it.
|
|
20
|
+
*
|
|
21
|
+
* A member is a value, not a name→value pair — matching `CREATE TYPE … AS ENUM
|
|
22
|
+
* ('a', 'b')`, which has no separate member name.
|
|
23
|
+
*
|
|
24
|
+
* Target-only concept — no SQL-family abstract. Extends `SqlNode` directly,
|
|
25
|
+
* frozen at construction via `freezeNode(this)`. The `kind: 'postgres-enum'`
|
|
26
|
+
* discriminant is enumerable so it survives JSON. Lives at
|
|
27
|
+
* `storage.namespaces[ns].entries.native_enum[HandleName]`; the entries key
|
|
28
|
+
* (`native_enum`) is the entity-kind descriptor's `kind`, decoupled from this
|
|
29
|
+
* node's own `kind` literal — the same shape as `table`/`StorageTable` and
|
|
30
|
+
* `valueSet`/`StorageValueSet`.
|
|
31
|
+
*/
|
|
32
|
+
export class PostgresNativeEnum extends SqlNode {
|
|
33
|
+
static is(node: unknown): node is PostgresNativeEnum {
|
|
34
|
+
return (
|
|
35
|
+
typeof node === 'object' && node !== null && 'kind' in node && node.kind === 'postgres-enum'
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override readonly kind = 'postgres-enum' as const;
|
|
40
|
+
readonly typeName: string;
|
|
41
|
+
readonly members: readonly string[];
|
|
42
|
+
declare readonly control?: ControlPolicy;
|
|
43
|
+
|
|
44
|
+
constructor(input: PostgresNativeEnumInput) {
|
|
45
|
+
super();
|
|
46
|
+
this.typeName = input.typeName;
|
|
47
|
+
this.members = Object.freeze([...input.members]);
|
|
48
|
+
if (input.control !== undefined) this.control = input.control;
|
|
49
|
+
freezeNode(this);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
2
|
+
import { SqlNode } from '@prisma-next/sql-contract/types';
|
|
3
|
+
|
|
4
|
+
export type RlsPolicyOperation = 'select' | 'insert' | 'update' | 'delete' | 'all';
|
|
5
|
+
|
|
6
|
+
export interface PostgresRlsPolicyInput {
|
|
7
|
+
/** Full wire name: `<prefix>_<8hex>`. Stored as-is; hashing is not this class's job. */
|
|
8
|
+
readonly name: string;
|
|
9
|
+
/** User-supplied prefix (the part before the `_<8hex>` suffix). */
|
|
10
|
+
readonly prefix: string;
|
|
11
|
+
/** Name of the table this policy attaches to, by name within the same schema. */
|
|
12
|
+
readonly tableName: string;
|
|
13
|
+
/** Namespace coordinate (schema name). Policies are schema-scoped. */
|
|
14
|
+
readonly namespaceId: string;
|
|
15
|
+
readonly operation: RlsPolicyOperation;
|
|
16
|
+
/** Sorted role names rendered in `TO <roles>`. Plain strings in this slice. */
|
|
17
|
+
readonly roles: readonly string[];
|
|
18
|
+
/** USING predicate SQL string, if present. */
|
|
19
|
+
readonly using?: string;
|
|
20
|
+
/** WITH CHECK predicate SQL string, if present. */
|
|
21
|
+
readonly withCheck?: string;
|
|
22
|
+
/** `true` = `AS PERMISSIVE`, `false` = `AS RESTRICTIVE`. */
|
|
23
|
+
readonly permissive: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Postgres contract-IR class for a row-level security policy (`CREATE POLICY … ON …`).
|
|
28
|
+
*
|
|
29
|
+
* This is an authored, serialized Contract-IR entity — it is registered as an entity
|
|
30
|
+
* kind, extends `SqlNode`, and is stored in `contract.json`. It is NOT a DiffableNode;
|
|
31
|
+
* the schema-diff tree uses `PostgresPolicySchemaNode` for that role.
|
|
32
|
+
*
|
|
33
|
+
* Target-only concept — no SQL-family abstract. Extends `SqlNode` directly.
|
|
34
|
+
* Frozen at construction via `freezeNode(this)`. The `kind: 'policy'`
|
|
35
|
+
* discriminant is enumerable (overrides SqlNode's non-enumerable `'sql'`) so it
|
|
36
|
+
* survives JSON serialization and enables dispatch. The literal matches the
|
|
37
|
+
* entries key (one-string rule: node.kind === entries key === entity kind).
|
|
38
|
+
*/
|
|
39
|
+
export class PostgresRlsPolicy extends SqlNode {
|
|
40
|
+
override readonly kind = 'policy' as const;
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly prefix: string;
|
|
43
|
+
readonly tableName: string;
|
|
44
|
+
readonly namespaceId: string;
|
|
45
|
+
readonly operation: RlsPolicyOperation;
|
|
46
|
+
readonly roles: readonly string[];
|
|
47
|
+
declare readonly using?: string;
|
|
48
|
+
declare readonly withCheck?: string;
|
|
49
|
+
readonly permissive: boolean;
|
|
50
|
+
|
|
51
|
+
constructor(input: PostgresRlsPolicyInput) {
|
|
52
|
+
super();
|
|
53
|
+
this.name = input.name;
|
|
54
|
+
this.prefix = input.prefix;
|
|
55
|
+
this.tableName = input.tableName;
|
|
56
|
+
this.namespaceId = input.namespaceId;
|
|
57
|
+
this.operation = input.operation;
|
|
58
|
+
this.roles = Object.freeze([...input.roles]);
|
|
59
|
+
if (input.using !== undefined) this.using = input.using;
|
|
60
|
+
if (input.withCheck !== undefined) this.withCheck = input.withCheck;
|
|
61
|
+
this.permissive = input.permissive;
|
|
62
|
+
freezeNode(this);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
2
|
+
import { SqlNode } from '@prisma-next/sql-contract/types';
|
|
3
|
+
|
|
4
|
+
export interface PostgresRoleInput {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
/**
|
|
7
|
+
* Namespace coordinate. Roles are cluster-scoped; pass `UNBOUND_NAMESPACE_ID`
|
|
8
|
+
* from `@prisma-next/framework-components/ir`.
|
|
9
|
+
*/
|
|
10
|
+
readonly namespaceId: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Postgres contract-IR class for a database role (`CREATE ROLE …`).
|
|
15
|
+
*
|
|
16
|
+
* This is an authored, serialized Contract-IR entity — it is registered as an entity
|
|
17
|
+
* kind, extends `SqlNode`, and is stored in `contract.json`. It is NOT a DiffableNode;
|
|
18
|
+
* the schema-diff tree uses `PostgresRoleSchemaNode` for that role.
|
|
19
|
+
*
|
|
20
|
+
* Roles are cluster-scoped, so their namespace coordinate is always
|
|
21
|
+
* `UNBOUND_NAMESPACE_ID`. Target-only concept — no SQL-family abstract.
|
|
22
|
+
* Extends `SqlNode` directly, frozen at construction via `freezeNode(this)`.
|
|
23
|
+
* The `kind: 'role'` discriminant is enumerable so it survives JSON.
|
|
24
|
+
* Matches the entries key (one-string rule).
|
|
25
|
+
*/
|
|
26
|
+
export class PostgresRole extends SqlNode {
|
|
27
|
+
override readonly kind = 'role' as const;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly namespaceId: string;
|
|
30
|
+
|
|
31
|
+
constructor(input: PostgresRoleInput) {
|
|
32
|
+
super();
|
|
33
|
+
this.name = input.name;
|
|
34
|
+
this.namespaceId = input.namespaceId;
|
|
35
|
+
freezeNode(this);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
2
|
import { SqlSchemaVerifierBase } from '@prisma-next/family-sql/ir';
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
SchemaDiffIssue,
|
|
5
|
+
SchemaVerifyOptions,
|
|
6
|
+
} from '@prisma-next/framework-components/control';
|
|
4
7
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
5
8
|
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Postgres target `SchemaVerifier` concretion. Plugs into the
|
|
9
12
|
* SQL-shared verification surface; production verification today still
|
|
10
|
-
* routes through the
|
|
11
|
-
* carries options (codec hooks,
|
|
12
|
-
* that the framework-level
|
|
13
|
-
* surface.
|
|
13
|
+
* routes through the family verify verdict (`verifySqlSchemaByDiff` over
|
|
14
|
+
* `diffPostgresSchema`), which carries options (codec hooks,
|
|
15
|
+
* normalizers, framework components) that the framework-level
|
|
16
|
+
* `SchemaVerifyOptions` shape does not yet surface.
|
|
14
17
|
*
|
|
15
18
|
* The hooks return the empty list pending the call-site migration that
|
|
16
19
|
* routes the existing verifier behaviour through the SPI — at that
|
|
@@ -25,13 +28,13 @@ export class PostgresSchemaVerifier extends SqlSchemaVerifierBase<
|
|
|
25
28
|
> {
|
|
26
29
|
protected verifyCommonSqlSchema(
|
|
27
30
|
_options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,
|
|
28
|
-
): readonly
|
|
31
|
+
): readonly SchemaDiffIssue[] {
|
|
29
32
|
return [];
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
protected verifyTargetExtensions(
|
|
33
36
|
_options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,
|
|
34
|
-
): readonly
|
|
37
|
+
): readonly SchemaDiffIssue[] {
|
|
35
38
|
return [];
|
|
36
39
|
}
|
|
37
40
|
}
|