@prisma-next/target-postgres 0.14.0-dev.31 → 0.14.0-dev.33
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/{descriptor-meta-runtime-D5zHFKUz.mjs → authoring-CZmSQriw.mjs} +2 -10
- package/dist/authoring-CZmSQriw.mjs.map +1 -0
- package/dist/control.mjs +4 -4
- package/dist/{descriptor-meta-Dvvpu_jU.mjs → descriptor-meta-Du6olWQI.mjs} +3 -2
- package/dist/{descriptor-meta-Dvvpu_jU.mjs.map → descriptor-meta-Du6olWQI.mjs.map} +1 -1
- package/dist/descriptor-meta-runtime-UwYdV8fD.mjs +12 -0
- package/dist/descriptor-meta-runtime-UwYdV8fD.mjs.map +1 -0
- package/dist/migration.d.mts +1 -1
- package/dist/migration.mjs +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-BnNEtGYM.mjs → planner-D3Pl8LXU.mjs} +2 -2
- package/dist/{planner-BnNEtGYM.mjs.map → planner-D3Pl8LXU.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-BO-frvvN.d.mts → planner-produced-postgres-migration-BauTSigX.d.mts} +3 -3
- package/dist/{planner-produced-postgres-migration-BO-frvvN.d.mts.map → planner-produced-postgres-migration-BauTSigX.d.mts.map} +1 -1
- package/dist/{planner-produced-postgres-migration-DzvdQ-7K.mjs → planner-produced-postgres-migration-Bbv8RYKJ.mjs} +3 -3
- package/dist/{planner-produced-postgres-migration-DzvdQ-7K.mjs.map → planner-produced-postgres-migration-Bbv8RYKJ.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.d.mts +1 -1
- package/dist/planner.mjs +1 -1
- 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-tGMiJcl4.mjs → postgres-contract-view-D12LEXT5.mjs} +16 -3
- package/dist/postgres-contract-view-D12LEXT5.mjs.map +1 -0
- package/dist/{postgres-migration-C8JZyTSJ.mjs → postgres-migration-DEefginX.mjs} +20 -1
- package/dist/postgres-migration-DEefginX.mjs.map +1 -0
- package/dist/{postgres-migration-Cs7zMOe1.d.mts → postgres-migration-UtGCjw5j.d.mts} +15 -2
- package/dist/postgres-migration-UtGCjw5j.d.mts.map +1 -0
- 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/runtime.d.mts +2 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +3 -3
- package/dist/runtime.mjs.map +1 -1
- package/package.json +19 -19
- package/src/core/migrations/postgres-migration.ts +34 -4
- package/src/core/migrations/render-typescript.ts +42 -15
- package/src/core/postgres-contract-view.ts +48 -0
- package/src/exports/runtime.ts +1 -0
- package/dist/descriptor-meta-runtime-D5zHFKUz.mjs.map +0 -1
- package/dist/postgres-contract-serializer-tGMiJcl4.mjs.map +0 -1
- package/dist/postgres-migration-C8JZyTSJ.mjs.map +0 -1
- package/dist/postgres-migration-Cs7zMOe1.d.mts.map +0 -1
- package/dist/render-typescript-KMgosran.mjs.map +0 -1
|
@@ -214,15 +214,7 @@ const postgresAuthoringFieldPresets = {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
|
-
const postgresTargetDescriptorMetaRuntime = {
|
|
218
|
-
kind: "target",
|
|
219
|
-
familyId: "sql",
|
|
220
|
-
targetId: "postgres",
|
|
221
|
-
id: "postgres",
|
|
222
|
-
version: "0.0.1",
|
|
223
|
-
capabilities: {}
|
|
224
|
-
};
|
|
225
217
|
//#endregion
|
|
226
|
-
export { postgresAuthoringTypes as
|
|
218
|
+
export { postgresAuthoringTypes as i, postgresAuthoringFieldPresets as n, postgresAuthoringPslBlockDescriptors as r, postgresAuthoringEntityTypes as t };
|
|
227
219
|
|
|
228
|
-
//# sourceMappingURL=
|
|
220
|
+
//# sourceMappingURL=authoring-CZmSQriw.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring-CZmSQriw.mjs","names":[],"sources":["../src/core/authoring.ts"],"sourcesContent":["import { temporalAuthoringPresets } from '@prisma-next/family-sql/control';\nimport type {\n AuthoringEntityContext,\n AuthoringEntityTypeNamespace,\n AuthoringFieldNamespace,\n AuthoringPslBlockDescriptorNamespace,\n AuthoringTypeNamespace,\n PslExtensionBlock,\n} from '@prisma-next/framework-components/authoring';\nimport { PostgresRlsPolicySchema, PostgresRoleSchema } from './postgres-validators';\nimport { computeContentHash, normalizePredicate } from './rls/canonicalize';\nimport { PostgresRlsPolicy } from './schema-ir/postgres-rls-policy';\nimport { PostgresRole, type PostgresRoleInput } from './schema-ir/postgres-role';\n\nexport const postgresAuthoringTypes = {} as const satisfies AuthoringTypeNamespace;\n\nexport interface RlsPolicyExtensionBlock extends PslExtensionBlock {\n readonly namespaceId: string;\n}\n\nfunction readRefParam(block: PslExtensionBlock, key: string): string | undefined {\n const param = block.parameters[key];\n return param?.kind === 'ref' ? param.identifier : undefined;\n}\n\nfunction readValueParam(block: PslExtensionBlock, key: string): string | undefined {\n const param = block.parameters[key];\n return param?.kind === 'value' ? param.raw : undefined;\n}\n\nfunction readListRefParams(block: PslExtensionBlock, key: string): string[] {\n const param = block.parameters[key];\n if (param?.kind !== 'list') return [];\n return param.items.flatMap((item) => (item.kind === 'ref' ? [item.identifier] : []));\n}\n\nfunction unwrapQuotedString(raw: string): string {\n if (raw.startsWith('\"') && raw.endsWith('\"') && raw.length >= 2) {\n return raw.slice(1, -1).replace(/\\\\\"/g, '\"');\n }\n return raw;\n}\n\nfunction lowerRlsPolicyFromBlock(\n block: RlsPolicyExtensionBlock,\n _ctx: AuthoringEntityContext,\n): PostgresRlsPolicy {\n const prefix = block.name;\n const targetModelName = readRefParam(block, 'target') ?? '';\n const tableName = targetModelName.charAt(0).toLowerCase() + targetModelName.slice(1);\n const roles = [...readListRefParams(block, 'roles')].sort();\n const using = unwrapQuotedString(readValueParam(block, 'using') ?? '');\n\n const wireHash = computeContentHash({\n using: normalizePredicate(using),\n roles,\n operation: 'select',\n permissive: true,\n });\n const wireName = `${prefix}_${wireHash}`;\n\n return new PostgresRlsPolicy({\n name: wireName,\n prefix,\n tableName,\n namespaceId: block.namespaceId,\n operation: 'select',\n roles,\n using,\n permissive: true,\n });\n}\n\nexport const postgresAuthoringEntityTypes = {\n role: {\n kind: 'entity',\n discriminator: 'role',\n validatorSchema: PostgresRoleSchema,\n output: {\n factory: (input: PostgresRoleInput): PostgresRole => new PostgresRole(input),\n },\n },\n policy: {\n kind: 'entity',\n discriminator: 'policy',\n validatorSchema: PostgresRlsPolicySchema,\n output: {\n factory: lowerRlsPolicyFromBlock,\n },\n },\n} as const satisfies AuthoringEntityTypeNamespace;\n\n/**\n * Field presets contributed by the Postgres target pack.\n *\n * These mirror the PSL scalar-to-codec mapping used by the Postgres adapter\n * (see `createPostgresPslScalarTypeDescriptors`), so that authoring a field\n * via the TS callback surface (e.g. `field.int()`) and via the PSL scalar\n * surface (e.g. `Int`) lowers to byte-identical contracts.\n *\n * The `uuidNative` / `id.uuidv4Native` / `id.uuidv7Native` presets use the\n * native Postgres `uuid` type (codecId `pg/uuid@1`). For cross-target\n * portability use `uuidString` / `id.uuidv4String` / `id.uuidv7String` from\n * the family pack instead.\n */\n/**\n * PSL block descriptor for `policy_select`.\n *\n * The parser learns the block shape from this descriptor; lowering from\n * `PslExtensionBlock` to `PostgresRlsPolicy` is wired in the PSL\n * interpreter (a later dispatch). The `discriminator` matches\n * `PostgresRlsPolicy.kind` so the parsed block node carries the same\n * discriminant as the IR class it will lower to.\n *\n * The `roles` list uses `scope:'cross-space'` because same-namespace\n * role ref resolution requires PSL namespace entries keyed by `refKind`\n * (i.e. `'role'`), which in turn requires the role block discriminator to\n * equal `'role'`. Aligning discriminator with refKind is tracked for\n * slice 4 (cross-space roles). Until then cross-space passes validation\n * unconditionally and the authored role names flow through unchanged.\n */\nexport const postgresAuthoringPslBlockDescriptors = {\n policy_select: {\n kind: 'pslBlock',\n keyword: 'policy_select',\n discriminator: 'policy',\n name: { required: true },\n parameters: {\n target: { kind: 'ref', refKind: 'model', scope: 'same-namespace', required: true },\n roles: {\n kind: 'list',\n of: { kind: 'ref', refKind: 'role', scope: 'cross-space' },\n },\n using: { kind: 'value', codecId: 'pg/text@1', required: true },\n },\n },\n} as const satisfies AuthoringPslBlockDescriptorNamespace;\n\nexport const postgresAuthoringFieldPresets = {\n text: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/text@1',\n nativeType: 'text',\n },\n },\n int: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/int4@1',\n nativeType: 'int4',\n },\n },\n bigint: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/int8@1',\n nativeType: 'int8',\n },\n },\n float: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/float8@1',\n nativeType: 'float8',\n },\n },\n decimal: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/numeric@1',\n nativeType: 'numeric',\n },\n },\n boolean: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/bool@1',\n nativeType: 'bool',\n },\n },\n json: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/jsonb@1',\n nativeType: 'jsonb',\n },\n },\n bytes: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/bytea@1',\n nativeType: 'bytea',\n },\n },\n dateTime: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n },\n },\n temporal: /* @__PURE__ */ temporalAuthoringPresets({\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n }),\n uuidNative: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/uuid@1',\n nativeType: 'uuid',\n },\n },\n id: {\n uuidv4Native: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/uuid@1',\n nativeType: 'uuid',\n executionDefaults: {\n onCreate: {\n kind: 'generator',\n id: 'uuidv4',\n },\n },\n id: true,\n },\n },\n uuidv7Native: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/uuid@1',\n nativeType: 'uuid',\n executionDefaults: {\n onCreate: {\n kind: 'generator',\n id: 'uuidv7',\n },\n },\n id: true,\n },\n },\n },\n} as const satisfies AuthoringFieldNamespace;\n"],"mappings":"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"}
|
package/dist/control.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as postgresTargetDescriptorMeta } from "./descriptor-meta-
|
|
2
|
-
import { i as contractToPostgresSchemaIR, t as createPostgresMigrationPlanner } from "./planner-
|
|
1
|
+
import { t as postgresTargetDescriptorMeta } from "./descriptor-meta-Du6olWQI.mjs";
|
|
2
|
+
import { i as contractToPostgresSchemaIR, t as createPostgresMigrationPlanner } from "./planner-D3Pl8LXU.mjs";
|
|
3
3
|
import { t as parsePostgresDefault } from "./default-normalizer-CzV8-QSu.mjs";
|
|
4
4
|
import { t as normalizeSchemaNativeType } from "./native-type-normalizer-Bc9XJzWC.mjs";
|
|
5
5
|
import { r as renderDefaultLiteral } from "./planner-ddl-builders-B8Nn6nHN.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { n as PostgresContractSerializer } from "./postgres-contract-view-D12LEXT5.mjs";
|
|
7
7
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
8
8
|
import { extractCodecControlHooks, runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
|
|
9
9
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
@@ -11,8 +11,8 @@ import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
|
11
11
|
import { verifySqlSchema } from "@prisma-next/family-sql/schema-verify";
|
|
12
12
|
import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
|
|
13
13
|
import { notOk, ok, okVoid } from "@prisma-next/utils/result";
|
|
14
|
-
import { SqlQueryError } from "@prisma-next/sql-errors";
|
|
15
14
|
import { SqlSchemaVerifierBase } from "@prisma-next/family-sql/ir";
|
|
15
|
+
import { SqlQueryError } from "@prisma-next/sql-errors";
|
|
16
16
|
//#region src/core/migrations/runner.ts
|
|
17
17
|
const LOCK_DOMAIN = "prisma_next.contract.marker";
|
|
18
18
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { i as postgresCreateNamespace } from "./postgres-schema-DLcc3W2-.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { i as postgresAuthoringTypes, n as postgresAuthoringFieldPresets, r as postgresAuthoringPslBlockDescriptors, t as postgresAuthoringEntityTypes } from "./authoring-CZmSQriw.mjs";
|
|
3
|
+
import { t as postgresTargetDescriptorMetaRuntime } from "./descriptor-meta-runtime-UwYdV8fD.mjs";
|
|
3
4
|
const postgresTargetDescriptorMeta = {
|
|
4
5
|
...postgresTargetDescriptorMetaRuntime,
|
|
5
6
|
defaultNamespaceId: "public",
|
|
@@ -14,4 +15,4 @@ const postgresTargetDescriptorMeta = {
|
|
|
14
15
|
//#endregion
|
|
15
16
|
export { postgresTargetDescriptorMeta as t };
|
|
16
17
|
|
|
17
|
-
//# sourceMappingURL=descriptor-meta-
|
|
18
|
+
//# sourceMappingURL=descriptor-meta-Du6olWQI.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-meta-
|
|
1
|
+
{"version":3,"file":"descriptor-meta-Du6olWQI.mjs","names":[],"sources":["../src/core/descriptor-meta.ts"],"sourcesContent":["import type { CodecTypes } from '../exports/codec-types';\nimport {\n postgresAuthoringEntityTypes,\n postgresAuthoringFieldPresets,\n postgresAuthoringPslBlockDescriptors,\n postgresAuthoringTypes,\n} from './authoring';\nimport { postgresTargetDescriptorMetaRuntime } from './descriptor-meta-runtime';\nimport { postgresCreateNamespace } from './postgres-schema';\n\nconst postgresTargetDescriptorMetaBase = {\n ...postgresTargetDescriptorMetaRuntime,\n defaultNamespaceId: 'public',\n authoring: {\n type: postgresAuthoringTypes,\n field: postgresAuthoringFieldPresets,\n entityTypes: postgresAuthoringEntityTypes,\n pslBlockDescriptors: postgresAuthoringPslBlockDescriptors,\n createNamespace: postgresCreateNamespace,\n },\n} as const;\n\nexport const postgresTargetDescriptorMeta: typeof postgresTargetDescriptorMetaBase & {\n readonly __codecTypes?: CodecTypes;\n} = postgresTargetDescriptorMetaBase;\n"],"mappings":";;;AAsBA,MAAa,+BAET;CAbF,GAAG;CACH,oBAAoB;CACpB,WAAW;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,qBAAqB;EACrB,iBAAiB;CACnB;AAKE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const postgresTargetDescriptorMetaRuntime = {
|
|
2
|
+
kind: "target",
|
|
3
|
+
familyId: "sql",
|
|
4
|
+
targetId: "postgres",
|
|
5
|
+
id: "postgres",
|
|
6
|
+
version: "0.0.1",
|
|
7
|
+
capabilities: {}
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { postgresTargetDescriptorMetaRuntime as t };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=descriptor-meta-runtime-UwYdV8fD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptor-meta-runtime-UwYdV8fD.mjs","names":[],"sources":["../src/core/descriptor-meta-runtime.ts"],"sourcesContent":["// Runtime-safe slice of the postgres target descriptor metadata.\n//\n// This file exists separately from ./descriptor-meta on purpose: the runtime\n// plane reads only `kind/familyId/targetId/id/version/capabilities` (plus the\n// `__codecTypes` phantom). The `authoring` slot lives on the pack/control\n// descriptor only, because authoring contributions are consumed at\n// contract-construction time by `assembleAuthoringContributions` (control\n// plane) and the PSL interpreter — never at runtime.\n//\n// Keeping the runtime closure free of the `./authoring` import is what lets\n// the bundler tree-shake `@prisma-next/family-sql/control` (and its\n// transitive `verify-sql-schema` chunk) out of the runtime entry. Do not\n// add an `authoring` field here — if you need to, the pack/control meta in\n// `./descriptor-meta` is the right place. See TML-2766 for context.\nimport type { CodecTypes } from '../exports/codec-types';\n\nconst postgresTargetDescriptorMetaRuntimeBase = {\n kind: 'target',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {},\n} as const;\n\nexport const postgresTargetDescriptorMetaRuntime: typeof postgresTargetDescriptorMetaRuntimeBase & {\n readonly __codecTypes?: CodecTypes;\n} = postgresTargetDescriptorMetaRuntimeBase;\n"],"mappings":"AAyBA,MAAa,sCAET;CAVF,MAAM;CACN,UAAU;CACV,UAAU;CACV,IAAI;CACJ,SAAS;CACT,cAAc,CAAC;AAKb"}
|
package/dist/migration.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as DataTransformOptions, r as dataTransform, t as DataTransformClosure } from "./data-transform-qKy1U5V9.mjs";
|
|
2
2
|
import { T as Op } from "./op-factory-call-DPJR7tJc.mjs";
|
|
3
|
-
import { t as PostgresMigration } from "./postgres-migration-
|
|
3
|
+
import { t as PostgresMigration } from "./postgres-migration-UtGCjw5j.mjs";
|
|
4
4
|
import { col, fn, foreignKey, lit, primaryKey, unique } from "@prisma-next/sql-relational-core/contract-free";
|
|
5
5
|
import { placeholder } from "@prisma-next/errors/migration";
|
|
6
6
|
import { MigrationCLI } from "@prisma-next/cli/migration-cli";
|
package/dist/migration.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { k as createExtension } from "./op-factory-call-DIdBDwmO.mjs";
|
|
2
2
|
import { t as dataTransform } from "./data-transform-BOWpliq8.mjs";
|
|
3
|
-
import { t as PostgresMigration } from "./postgres-migration-
|
|
3
|
+
import { t as PostgresMigration } from "./postgres-migration-DEefginX.mjs";
|
|
4
4
|
import { col, fn, foreignKey, lit, primaryKey, unique } from "@prisma-next/sql-relational-core/contract-free";
|
|
5
5
|
import { placeholder } from "@prisma-next/errors/migration";
|
|
6
6
|
import { MigrationCLI } from "@prisma-next/cli/migration-cli";
|
package/dist/pack.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as postgresTargetDescriptorMeta } from "./descriptor-meta-
|
|
1
|
+
import { t as postgresTargetDescriptorMeta } from "./descriptor-meta-Du6olWQI.mjs";
|
|
2
2
|
export { postgresTargetDescriptorMeta as default };
|
|
@@ -5,7 +5,7 @@ import { t as parsePostgresDefault } from "./default-normalizer-CzV8-QSu.mjs";
|
|
|
5
5
|
import { t as normalizeSchemaNativeType } from "./native-type-normalizer-Bc9XJzWC.mjs";
|
|
6
6
|
import { C as EnableRowLevelSecurityCall, d as CreatePostgresRlsPolicyCall, x as DropPostgresRlsPolicyCall } from "./op-factory-call-DIdBDwmO.mjs";
|
|
7
7
|
import { n as postgresPlannerStrategies, t as planIssues } from "./issue-planner-D5H1VuVP.mjs";
|
|
8
|
-
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-
|
|
8
|
+
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-Bbv8RYKJ.mjs";
|
|
9
9
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
10
10
|
import { contractToSchemaIR, extractCodecControlHooks, partitionCallsByControlPolicy, partitionIssuesByControlPolicy, planFieldEventOperations, plannerFailure } from "@prisma-next/family-sql/control";
|
|
11
11
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
@@ -453,4 +453,4 @@ var PostgresMigrationPlanner = class {
|
|
|
453
453
|
//#endregion
|
|
454
454
|
export { contractToPostgresSchemaIR as i, diffPostgresSchema as n, filterIssuesByOwnership as r, createPostgresMigrationPlanner as t };
|
|
455
455
|
|
|
456
|
-
//# sourceMappingURL=planner-
|
|
456
|
+
//# sourceMappingURL=planner-D3Pl8LXU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-BnNEtGYM.mjs","names":["#lowerer"],"sources":["../src/core/migrations/contract-to-postgres-schema-ir.ts","../src/core/migrations/control-policy.ts","../src/core/migrations/diff-postgres-schema.ts","../src/core/migrations/verify-postgres-namespaces.ts","../src/core/migrations/planner.ts"],"sourcesContent":["import type { ContractToSchemaIROptions } from '@prisma-next/family-sql/control';\nimport { contractToSchemaIR } from '@prisma-next/family-sql/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { PostgresContract } from '../postgres-schema';\nimport { isPostgresSchema } from '../postgres-schema';\nimport { PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\nimport { resolveDdlSchemaForNamespaceStorage } from '../schema-ir/postgres-schema-ir-annotations';\nimport { PostgresTableIR } from '../schema-ir/postgres-table-ir';\n\nexport function contractToPostgresSchemaIR(\n contract: PostgresContract | null,\n options: ContractToSchemaIROptions,\n): PostgresSchemaIR {\n const sqlIr = contractToSchemaIR(contract, options);\n const ownedSchemas =\n contract === null\n ? []\n : Object.values(contract.storage.namespaces)\n .filter((ns) => isPostgresSchema(ns))\n .map((ns) => resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id));\n\n // Build a map of tableName → PostgresRlsPolicy[], resolving the DDL schema\n // name once per namespace (not per policy).\n const policiesByTable = new Map<string, PostgresRlsPolicy[]>();\n if (contract !== null) {\n for (const ns of Object.values(contract.storage.namespaces)) {\n if (!isPostgresSchema(ns)) continue;\n const resolvedSchema = resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id);\n for (const policy of Object.values(ns.policy)) {\n const resolved =\n resolvedSchema === policy.namespaceId\n ? policy\n : new PostgresRlsPolicy({\n name: policy.name,\n prefix: policy.prefix,\n tableName: policy.tableName,\n namespaceId: resolvedSchema,\n operation: policy.operation,\n roles: [...policy.roles],\n ...ifDefined('using', policy.using),\n ...ifDefined('withCheck', policy.withCheck),\n permissive: policy.permissive,\n });\n const list = policiesByTable.get(policy.tableName) ?? [];\n list.push(resolved);\n policiesByTable.set(policy.tableName, list);\n }\n }\n }\n\n // Attach policies to each table from the relational projection. A policy that\n // references a table absent from the schema IR is a malformed contract — the\n // loop below throws rather than fabricating a stub table.\n const tables: Record<string, PostgresTableIR> = {};\n for (const [tableName, sqlTable] of Object.entries(sqlIr.tables)) {\n tables[tableName] = new PostgresTableIR({\n name: sqlTable.name,\n columns: sqlTable.columns,\n foreignKeys: sqlTable.foreignKeys,\n uniques: sqlTable.uniques,\n indexes: sqlTable.indexes,\n ...(sqlTable.primaryKey !== undefined ? { primaryKey: sqlTable.primaryKey } : {}),\n ...(sqlTable.annotations !== undefined ? { annotations: sqlTable.annotations } : {}),\n ...(sqlTable.checks !== undefined ? { checks: sqlTable.checks } : {}),\n rlsPolicies: policiesByTable.get(tableName) ?? [],\n });\n }\n for (const [tableName, policies] of policiesByTable) {\n if (!(tableName in tables)) {\n const policyName = policies[0]?.name ?? '(unknown)';\n throw new Error(\n `contract-to-postgres-schema-ir: policy \"${policyName}\" references table \"${tableName}\" not present in the schema`,\n );\n }\n }\n\n return new PostgresSchemaIR({\n tables,\n roles:\n contract === null\n ? []\n : Object.values(contract.storage.namespaces).flatMap((ns) =>\n isPostgresSchema(ns) ? Object.values(ns.role) : [],\n ),\n pgSchemaName: 'public',\n pgVersion: '',\n existingSchemas: ownedSchemas,\n nativeEnumTypeNames: [],\n });\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlPolicySubject } from '@prisma-next/family-sql/control';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { entityAt, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { isPostgresSchema } from '../postgres-schema';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\n\n/**\n * Factory calls that create a whole, previously-absent top-level storage\n * object. Used to decide whether `tolerated` permits a call (it only allows\n * creating absent objects, never modifying existing ones).\n *\n * Deliberately an explicit, closed set rather than a `factoryName`\n * create/alter/drop classification: it answers exactly one yes/no question\n * and is fail-closed. Any call not listed here — including future or\n * extension-contributed factories — is treated as NOT object-creation, so it\n * is suppressed under `tolerated` rather than permissively emitted.\n */\nconst OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([\n 'createTable',\n 'createSchema',\n 'createRlsPolicy',\n 'enableRowLevelSecurity',\n]);\n\nfunction createsNewTopLevelObject(call: PostgresOpFactoryCall): boolean {\n return OBJECT_CREATION_FACTORIES.has(call.factoryName);\n}\n\nfunction ddlSchemaNameForNamespace(contract: Contract<SqlStorage>, namespaceId: string): string {\n const namespace = contract.storage.namespaces[namespaceId];\n return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;\n}\n\nfunction resolveNamespaceIdForTable(\n contract: Contract<SqlStorage>,\n tableName: string,\n ddlSchemaName: string | undefined,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const table = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) continue;\n if (\n ddlSchemaName === undefined ||\n ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName\n ) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\nfunction resolveNamespaceIdForDdlSchema(\n contract: Contract<SqlStorage>,\n ddlSchemaName: string,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const ns = contract.storage.namespaces[namespaceId];\n if (isPostgresSchema(ns) && ns.ddlSchemaName(contract.storage) === ddlSchemaName) {\n return namespaceId;\n }\n if (namespaceId === ddlSchemaName) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\ninterface PostgresCallFields {\n readonly schemaName?: string;\n readonly tableName?: string;\n readonly columnName?: string;\n}\n\nfunction postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {\n return {\n ...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),\n ...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),\n ...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),\n };\n}\n\nexport function formatPostgresControlPolicySubjectLabel(\n factoryName: string,\n subject: ControlPolicySubject | undefined,\n contract: Contract<SqlStorage>,\n): string {\n if (subject?.table) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.table})`;\n }\n return factoryName;\n}\n\nexport function resolvePostgresCallControlPolicySubject(\n call: PostgresOpFactoryCall,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const callFields = postgresCallFields(call);\n const createsNewObject = createsNewTopLevelObject(call);\n\n if (call.factoryName === 'createSchema' && callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n if (callFields.tableName) {\n const namespaceId = resolveNamespaceIdForTable(\n contract,\n callFields.tableName,\n callFields.schemaName,\n );\n const tableControlPolicy = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: callFields.tableName,\n })?.control;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', tableControlPolicy),\n table: callFields.tableName,\n ...ifDefined('column', callFields.columnName),\n createsNewObject,\n };\n }\n\n if (callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n\n/**\n * Issue kinds that describe the absence of a whole, top-level Postgres\n * object — the same kinds `createsNewTopLevelObject` recognises for calls.\n * Used by {@link resolvePostgresIssueCreationFactoryName} to decide whether\n * a `tolerated` subject permits the issue to flow into the planner\n * (create-if-absent) and to seed the suppressed-subject warning's\n * `factoryName` when the planner is skipped.\n */\nconst POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({\n missing_schema: 'createSchema',\n missing_table: 'createTable',\n missing_rls_policy: 'createRlsPolicy',\n});\n\nexport function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {\n return POSTGRES_ISSUE_CREATION_FACTORY[issue.kind];\n}\n\n/**\n * Resolve the control-policy subject coordinate for a single\n * {@link SchemaIssue}. Mirrors the resolution `resolvePostgresCallControlPolicySubject`\n * performs for a generated DDL call, but works *off the issue* — so the\n * planner can partition issues by effective policy before the diff engine\n * runs. `createsNewObject` is derived from the issue's kind: schema/table/\n * type-missing issues describe a brand-new top-level object; everything else\n * touches an existing object.\n *\n * An `extra_table` issue carries no contract namespace coordinate (the table\n * isn't in any contract namespace), so the subject's `namespaceId` falls\n * back to {@link UNBOUND_NAMESPACE_ID}; the call-side resolver does the same\n * for the `DropTableCall` it produces.\n */\nexport function resolvePostgresIssueControlPolicySubject(\n issue: SchemaIssue,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const createsNewObject = POSTGRES_ISSUE_CREATION_FACTORY[issue.kind] !== undefined;\n\n if (issue.kind === 'missing_schema' && issue.namespaceId) {\n return { namespaceId: issue.namespaceId, createsNewObject };\n }\n\n if ('table' in issue && issue.table) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId\n ? issue.namespaceId\n : resolveNamespaceIdForTable(contract, issue.table, undefined);\n const table = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: issue.table,\n });\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', table?.control),\n table: issue.table,\n ...ifDefined('column', 'column' in issue ? issue.column : undefined),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n","import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';\nimport { diffSchemas } from '@prisma-next/framework-components/control';\nimport { isPostgresRlsPolicy, type PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { ensurePostgresSchemaIR, type PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\n\n// Renders a display-only reference string for the diff message. If policy\n// rendering grows, route it through the adapter's SQL renderer so the message\n// can't diverge from the emitted policy SQL.\nfunction renderPostgresPolicyReference(policy: PostgresRlsPolicy): string {\n return `policy \"${policy.name}\" on \"${policy.namespaceId}\".\"${policy.tableName}\"`;\n}\n\n/**\n * Computes schema drift between two derived schema IRs.\n *\n * 1. Runs the framework total diff.\n * 2. Filters to policy-subject issues only — this is transitional: the generic\n * differ walks the whole tree, but the legacy relational verifier still owns\n * table/column drift, so non-policy issues are dropped here.\n * 3. Remaps the message to a human-readable policy reference.\n *\n * Ownership filtering (dropping `extra` issues in namespaces a contract doesn't\n * own) is the caller's responsibility — use `filterIssuesByOwnership`.\n */\nexport function diffPostgresSchema(\n expected: PostgresSchemaIR,\n actual: PostgresSchemaIR,\n): readonly SchemaDiffIssue[] {\n const safeActual = ensurePostgresSchemaIR(actual);\n const issues = diffSchemas(expected, safeActual);\n\n return issues\n .filter((i) => isPostgresRlsPolicy(i.expected ?? i.actual))\n .map((i) => {\n const policy = i.expected ?? i.actual;\n if (!isPostgresRlsPolicy(policy)) return i;\n return { ...i, message: `${i.outcome}: ${renderPostgresPolicyReference(policy)}` };\n });\n}\n\n/**\n * Filters `extra` policy issues to those in owned namespaces. Call after\n * `diffPostgresSchema` with the union of namespace ids from the expected IR's\n * policies and its `existingSchemas`.\n */\nexport function filterIssuesByOwnership(\n issues: readonly SchemaDiffIssue[],\n ownedSchemaNames: ReadonlySet<string>,\n): readonly SchemaDiffIssue[] {\n return issues.filter(\n (i) =>\n i.outcome !== 'extra' ||\n (isPostgresRlsPolicy(i.actual) && ownedSchemaNames.has(i.actual.namespaceId)),\n );\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { isPostgresSchema } from '../postgres-schema';\nimport { isPostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\n\n/**\n * Resolves the live-database schema name for a given namespace\n * coordinate. Mirrors `resolveDdlSchemaForNamespace` in\n * `planner-strategies.ts` so the verifier's projection and the\n * planner's projection always agree — Postgres-aware namespaces (the\n * production path) dispatch to `ddlSchemaName(storage)`, and bare\n * object payloads (used by some tests) fall back to the coordinate\n * itself.\n */\nfunction resolveDdlSchemaName(storage: SqlStorage, namespaceId: string): string {\n const namespace = storage.namespaces[namespaceId];\n if (isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n\n/**\n * Reads the introspected list of schema names from a `PostgresSchemaIR`.\n * Defaults to the always-present `public` schema when the schema IR is not a\n * `PostgresSchemaIR` — a fresh Postgres database always carries `public`\n * (unless an operator dropped it manually), so any verifier path that runs\n * without an enriched introspection still suppresses the redundant\n * `CREATE SCHEMA \"public\"`.\n *\n * Production introspection (`PostgresControlAdapter.introspect`) is the\n * authoritative source: it queries `pg_namespace` and sets `existingSchemas`\n * on the returned `PostgresSchemaIR`. Tests that want to assert against a\n * richer initial state construct a `PostgresSchemaIR` explicitly.\n */\nfunction existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {\n if (isPostgresSchemaIR(schema)) {\n return schema.existingSchemas;\n }\n return ['public'];\n}\n\n/**\n * Emits a `missing_schema` issue for every contract-declared Postgres\n * namespace whose live container does not yet exist.\n *\n * A namespace's live container is the schema returned by its\n * polymorphic `ddlSchemaName(storage)` method — named schemas resolve\n * to their own id; the unbound singleton returns `UNBOUND_NAMESPACE_ID`\n * and is skipped explicitly (late-bound namespaces have no fixed DDL\n * schema). Issues are emitted only when the resolved name is a real,\n * creatable schema (not the unbound sentinel) and is missing from the\n * introspected list. `public` is suppressed implicitly because the\n * introspection (or its sensible default) always carries it.\n *\n * Each emitted issue stamps `namespaceId` with the contract namespace\n * coordinate so the downstream `mapIssueToCall` re-resolves the DDL\n * schema name through the same polymorphic path — keeping the\n * coordinate, not the resolved name, as the issue's stable identity.\n */\nexport function verifyPostgresNamespacePresence(input: {\n readonly contract: Contract<SqlStorage>;\n readonly schema: SqlSchemaIR;\n}): readonly SchemaIssue[] {\n const { contract, schema } = input;\n const existing = new Set(existingSchemasFromSchema(schema));\n const issues: SchemaIssue[] = [];\n const namespaceIds = Object.keys(contract.storage.namespaces).sort();\n for (const namespaceId of namespaceIds) {\n if (namespaceId === UNBOUND_NAMESPACE_ID) continue;\n const ddlName = resolveDdlSchemaName(contract.storage, namespaceId);\n if (ddlName === UNBOUND_NAMESPACE_ID) continue;\n if (existing.has(ddlName)) continue;\n issues.push({\n kind: 'missing_schema',\n namespaceId,\n message: `Schema \"${ddlName}\" is missing from database`,\n });\n }\n return issues;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlMigrationPlannerPlanOptions,\n SqlPlannerConflict,\n SqlPlannerFailureResult,\n} from '@prisma-next/family-sql/control';\nimport {\n extractCodecControlHooks,\n partitionCallsByControlPolicy,\n partitionIssuesByControlPolicy,\n planFieldEventOperations,\n plannerFailure,\n} from '@prisma-next/family-sql/control';\nimport type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';\nimport { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanner,\n MigrationPlanWithAuthoringSurface,\n MigrationScaffoldContext,\n SchemaIssue,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { parsePostgresDefault } from '../default-normalizer';\nimport { normalizeSchemaNativeType } from '../native-type-normalizer';\nimport type { PostgresContract } from '../postgres-schema';\nimport { assertPostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { assertPostgresSchemaIR, ensurePostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\nimport { resolveDdlSchemaForNamespaceStorage } from '../schema-ir/postgres-schema-ir-annotations';\nimport { contractToPostgresSchemaIR } from './contract-to-postgres-schema-ir';\nimport {\n formatPostgresControlPolicySubjectLabel,\n resolvePostgresCallControlPolicySubject,\n resolvePostgresIssueControlPolicySubject,\n resolvePostgresIssueCreationFactoryName,\n} from './control-policy';\nimport { diffPostgresSchema, filterIssuesByOwnership } from './diff-postgres-schema';\nimport { planIssues } from './issue-planner';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\nimport {\n CreatePostgresRlsPolicyCall,\n DropPostgresRlsPolicyCall,\n EnableRowLevelSecurityCall,\n} from './op-factory-call';\nimport { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';\nimport { postgresPlannerStrategies } from './planner-strategies';\nimport { verifyPostgresNamespacePresence } from './verify-postgres-namespaces';\n\ntype PlannerFrameworkComponents = SqlMigrationPlannerPlanOptions extends {\n readonly frameworkComponents: infer T;\n}\n ? T\n : ReadonlyArray<unknown>;\n\ntype PlannerOptionsWithComponents = SqlMigrationPlannerPlanOptions & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\ntype VerifySqlSchemaOptionsWithComponents = Parameters<typeof verifySqlSchema>[0] & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\nexport function createPostgresMigrationPlanner(\n lowerer: ExecuteRequestLowerer,\n): PostgresMigrationPlanner {\n return new PostgresMigrationPlanner(lowerer);\n}\n\n/**\n * Result of `PostgresMigrationPlanner.plan()`. A discriminated union whose\n * success variant carries a `TypeScriptRenderablePostgresMigration` — a\n * migration object that both the CLI (via `renderTypeScript()`) and the\n * SQL-typed callers (via `operations`, `describe()`, etc.) consume\n * uniformly.\n */\nexport type PostgresPlanResult =\n | {\n readonly kind: 'success';\n readonly plan: TypeScriptRenderablePostgresMigration;\n readonly warnings?: readonly SqlPlannerConflict[];\n }\n | SqlPlannerFailureResult;\n\n/**\n * Postgres migration planner — a thin wrapper over `planIssues`.\n *\n * `plan()` verifies the live schema against the target contract (producing\n * `SchemaIssue[]`) and delegates to `planIssues` with the unified\n * `postgresPlannerStrategies` list: enum-change, NOT-NULL backfill,\n * type-change, nullable-tightening, codec-hook storage types,\n * component-declared dependency installs, and shared-temp-default /\n * empty-table-guarded NOT-NULL add-column. The same strategy list runs for\n * `migration plan`, `db update`, and `db init`; behavior diverges purely on\n * `policy.allowedOperationClasses` (the data-safe strategies short-circuit\n * when `'data'` is excluded). The issue planner applies operation-class\n * policy gates and emits a single `PostgresOpFactoryCall[]` that drives both\n * the runtime-ops view (via `renderOps`) and the `renderTypeScript()`\n * authoring surface.\n */\nexport class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgres'> {\n readonly #lowerer: ExecuteRequestLowerer | undefined;\n\n constructor(lowerer?: ExecuteRequestLowerer) {\n this.#lowerer = lowerer;\n }\n\n plan(options: {\n readonly contract: unknown;\n readonly schema: unknown;\n readonly policy: MigrationOperationPolicy;\n /**\n * The \"from\" contract (state the planner assumes the database starts\n * at), or `null` for reconciliation flows. Only `migration plan` ever\n * supplies a non-null value; `db update` / `db init` reconcile against\n * the live schema and pass `null`. When present alongside the\n * `'data'` operation class, strategies that need from/to column-shape\n * comparisons (unsafe type change, nullability tightening) activate.\n *\n * Typed as the framework `Contract | null` to satisfy the\n * `MigrationPlanner` interface contract; `planSql` narrows to the SQL\n * shape via `SqlMigrationPlannerPlanOptions`. Used to populate\n * `describe().from` on the produced plan as\n * `fromContract?.storage.storageHash ?? null`.\n */\n readonly fromContract: Contract | null;\n readonly schemaName?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Contract space this plan applies to. Stamped onto the produced\n * {@link TypeScriptRenderablePostgresMigration.spaceId} so the runner keys\n * the marker row by the right space.\n */\n readonly spaceId: string;\n }): PostgresPlanResult {\n return this.planSql(options as SqlMigrationPlannerPlanOptions);\n }\n\n emptyMigration(\n context: MigrationScaffoldContext,\n spaceId: string,\n ): MigrationPlanWithAuthoringSurface {\n return new TypeScriptRenderablePostgresMigration(\n [],\n {\n from: context.fromHash,\n to: context.toHash,\n },\n spaceId,\n this.#lowerer,\n );\n }\n\n private planSql(options: SqlMigrationPlannerPlanOptions): PostgresPlanResult {\n const schemaName =\n options.schemaName ??\n Object.keys(options.contract.storage.namespaces).find((id) => id !== UNBOUND_NAMESPACE_ID) ??\n UNBOUND_NAMESPACE_ID;\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) {\n return policyResult;\n }\n\n const schemaIssues = this.collectSchemaIssues(options);\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n const storageTypes = options.contract.storage.types ?? {};\n\n // Input-side control-policy partition. `external` / `observed` subjects\n // — and non-creation issues for `tolerated` subjects — are dropped from\n // the planner's input entirely; the planner never observes them, never\n // diffs them, never generates DDL for them. Suppression warnings are\n // built directly from the suppressed partition (one per subject), so the\n // user-visible message survives even when the planner would have failed\n // to model the subject's live shape.\n const issuePartition = partitionIssuesByControlPolicy({\n issues: schemaIssues,\n contract: options.contract,\n resolveControlPolicySubject: (issue) =>\n resolvePostgresIssueControlPolicySubject(issue, options.contract),\n resolveCreationFactoryName: resolvePostgresIssueCreationFactoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n const result = planIssues({\n issues: issuePartition.plannable,\n toContract: options.contract,\n // `fromContract` is only supplied by `migration plan`. It is `null` for\n // `db update` / `db init`, which means data-safety strategies needing\n // from/to comparisons (unsafe type change, nullable tightening) are\n // inapplicable there — reconciliation falls through to\n // `mapIssueToCall`'s direct destructive handlers.\n fromContract: options.fromContract,\n schemaName,\n codecHooks,\n storageTypes,\n schema: options.schema,\n policy: options.policy,\n frameworkComponents: options.frameworkComponents,\n strategies: postgresPlannerStrategies,\n });\n\n if (!result.ok) {\n return plannerFailure(result.failure);\n }\n\n const schemaDiffCalls = this.planPostgresSchemaDiff(options);\n const schemaDiffPartition = partitionCallsByControlPolicy({\n calls: schemaDiffCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n // Inline `onFieldEvent`-emitted ops after structural DDL. The fixed\n // ordering is `structural → added → dropped → altered`, with\n // within-group sorting by `(tableName, fieldName)` so re-emits are\n // byte-stable. The hook fires only at the application emitter —\n // extension-space planning never reaches this helper.\n const fieldEventOps = planFieldEventOperations({\n priorContract: options.fromContract,\n newContract: options.contract,\n codecHooks,\n });\n // Codec hook ops are target-agnostic `OpFactoryCall`; Postgres planning\n // lifts them at this integration boundary (see field-event-planner JSDoc).\n const fieldEventPostgresCalls = blindCast<\n readonly PostgresOpFactoryCall[],\n 'Codec hook ops conform to PostgresOpFactoryCall at the app emitter boundary'\n >(fieldEventOps);\n const fieldEventPartition = partitionCallsByControlPolicy({\n calls: fieldEventPostgresCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n const calls = [...result.value.calls, ...schemaDiffPartition.kept, ...fieldEventPartition.kept];\n const warnings: SqlPlannerConflict[] = [\n ...issuePartition.warnings,\n ...schemaDiffPartition.warnings,\n ...fieldEventPartition.warnings,\n ];\n\n return Object.freeze({\n kind: 'success' as const,\n plan: new TypeScriptRenderablePostgresMigration(\n calls,\n {\n from: options.fromContract?.storage.storageHash ?? null,\n to: options.contract.storage.storageHash,\n },\n options.spaceId,\n this.#lowerer,\n ),\n ...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),\n });\n }\n\n private planPostgresSchemaDiff(\n options: PlannerOptionsWithComponents,\n ): readonly PostgresOpFactoryCall[] {\n assertPostgresSchemaIR(options.schema);\n const expected = contractToPostgresSchemaIR(\n blindCast<PostgresContract, 'planPostgresSchemaDiff is only called with a postgres contract'>(\n options.contract,\n ),\n { annotationNamespace: 'pg' },\n );\n const actual = ensurePostgresSchemaIR(options.schema);\n const rawIssues = diffPostgresSchema(expected, actual);\n const ownedSchemaNames = new Set([\n ...expected.rlsPolicies.map((p) => p.namespaceId),\n ...expected.existingSchemas,\n ]);\n const filteredDiffIssues = filterIssuesByOwnership(rawIssues, ownedSchemaNames);\n\n const allowsDestructive = options.policy.allowedOperationClasses.includes('destructive');\n const calls: PostgresOpFactoryCall[] = [];\n const seenEnableTables = new Set<string>();\n\n for (const issue of filteredDiffIssues) {\n // 'mismatch' is unreachable for content-addressed policies: the wire name\n // encodes the body hash, so two policies sharing a local key (same name)\n // are always equal and isEqualTo never returns false.\n if (issue.outcome === 'missing') {\n assertPostgresRlsPolicy(issue.expected);\n // issue.expected.namespaceId is the DDL schema name (resolved during projection);\n // this re-resolution is a no-op as long as PostgresSchema.ddlSchemaName() returns this.id.\n const schemaForTable = resolveDdlSchemaForNamespaceStorage(\n options.contract.storage,\n issue.expected.namespaceId,\n options.schema,\n );\n const tableKey = `${schemaForTable}.${issue.expected.tableName}`;\n if (!seenEnableTables.has(tableKey)) {\n seenEnableTables.add(tableKey);\n calls.push(new EnableRowLevelSecurityCall(schemaForTable, issue.expected.tableName));\n }\n calls.push(\n new CreatePostgresRlsPolicyCall(schemaForTable, issue.expected.tableName, issue.expected),\n );\n } else if (issue.outcome === 'extra' && allowsDestructive) {\n assertPostgresRlsPolicy(issue.actual);\n const schemaForTable = resolveDdlSchemaForNamespaceStorage(\n options.contract.storage,\n issue.actual.namespaceId,\n options.schema,\n );\n calls.push(\n new DropPostgresRlsPolicyCall(schemaForTable, issue.actual.tableName, issue.actual.name),\n );\n }\n }\n\n return calls;\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy) {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Migration planner requires additive operations be allowed',\n why: 'The planner requires the \"additive\" operation class to be allowed in the policy.',\n },\n ]);\n }\n return null;\n }\n\n private collectSchemaIssues(options: PlannerOptionsWithComponents): readonly SchemaIssue[] {\n // `db init` uses additive-only policy and intentionally ignores extra\n // schema objects. Any reconciliation-capable policy (widening or\n // destructive) must inspect extras to reconcile strict equality.\n const allowed = options.policy.allowedOperationClasses;\n const strict = allowed.includes('widening') || allowed.includes('destructive');\n const verifyOptions: VerifySqlSchemaOptionsWithComponents = {\n contract: options.contract,\n schema: options.schema,\n strict,\n typeMetadataRegistry: new Map(),\n frameworkComponents: options.frameworkComponents,\n normalizeDefault: parsePostgresDefault,\n normalizeNativeType: normalizeSchemaNativeType,\n };\n const verifyResult = verifySqlSchema(verifyOptions);\n // Schema presence is a Postgres-specific concern (no equivalent in\n // SQLite / Mongo), so the issue emission lives in the target layer\n // rather than in the family verifier. Stitch it in here so a single\n // `SchemaIssue[]` flows through `planIssues` and the planner emits\n // CREATE SCHEMA in the dep bucket before any CreateTableCall.\n // Schema drift is handled separately via diffPostgresSchema → planPostgresSchemaDiff.\n const namespaceIssues = verifyPostgresNamespacePresence({\n contract: options.contract,\n schema: options.schema,\n });\n if (namespaceIssues.length === 0) {\n return verifyResult.schema.issues;\n }\n return [...namespaceIssues, ...verifyResult.schema.issues];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"planner-D3Pl8LXU.mjs","names":["#lowerer"],"sources":["../src/core/migrations/contract-to-postgres-schema-ir.ts","../src/core/migrations/control-policy.ts","../src/core/migrations/diff-postgres-schema.ts","../src/core/migrations/verify-postgres-namespaces.ts","../src/core/migrations/planner.ts"],"sourcesContent":["import type { ContractToSchemaIROptions } from '@prisma-next/family-sql/control';\nimport { contractToSchemaIR } from '@prisma-next/family-sql/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { PostgresContract } from '../postgres-schema';\nimport { isPostgresSchema } from '../postgres-schema';\nimport { PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\nimport { resolveDdlSchemaForNamespaceStorage } from '../schema-ir/postgres-schema-ir-annotations';\nimport { PostgresTableIR } from '../schema-ir/postgres-table-ir';\n\nexport function contractToPostgresSchemaIR(\n contract: PostgresContract | null,\n options: ContractToSchemaIROptions,\n): PostgresSchemaIR {\n const sqlIr = contractToSchemaIR(contract, options);\n const ownedSchemas =\n contract === null\n ? []\n : Object.values(contract.storage.namespaces)\n .filter((ns) => isPostgresSchema(ns))\n .map((ns) => resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id));\n\n // Build a map of tableName → PostgresRlsPolicy[], resolving the DDL schema\n // name once per namespace (not per policy).\n const policiesByTable = new Map<string, PostgresRlsPolicy[]>();\n if (contract !== null) {\n for (const ns of Object.values(contract.storage.namespaces)) {\n if (!isPostgresSchema(ns)) continue;\n const resolvedSchema = resolveDdlSchemaForNamespaceStorage(contract.storage, ns.id);\n for (const policy of Object.values(ns.policy)) {\n const resolved =\n resolvedSchema === policy.namespaceId\n ? policy\n : new PostgresRlsPolicy({\n name: policy.name,\n prefix: policy.prefix,\n tableName: policy.tableName,\n namespaceId: resolvedSchema,\n operation: policy.operation,\n roles: [...policy.roles],\n ...ifDefined('using', policy.using),\n ...ifDefined('withCheck', policy.withCheck),\n permissive: policy.permissive,\n });\n const list = policiesByTable.get(policy.tableName) ?? [];\n list.push(resolved);\n policiesByTable.set(policy.tableName, list);\n }\n }\n }\n\n // Attach policies to each table from the relational projection. A policy that\n // references a table absent from the schema IR is a malformed contract — the\n // loop below throws rather than fabricating a stub table.\n const tables: Record<string, PostgresTableIR> = {};\n for (const [tableName, sqlTable] of Object.entries(sqlIr.tables)) {\n tables[tableName] = new PostgresTableIR({\n name: sqlTable.name,\n columns: sqlTable.columns,\n foreignKeys: sqlTable.foreignKeys,\n uniques: sqlTable.uniques,\n indexes: sqlTable.indexes,\n ...(sqlTable.primaryKey !== undefined ? { primaryKey: sqlTable.primaryKey } : {}),\n ...(sqlTable.annotations !== undefined ? { annotations: sqlTable.annotations } : {}),\n ...(sqlTable.checks !== undefined ? { checks: sqlTable.checks } : {}),\n rlsPolicies: policiesByTable.get(tableName) ?? [],\n });\n }\n for (const [tableName, policies] of policiesByTable) {\n if (!(tableName in tables)) {\n const policyName = policies[0]?.name ?? '(unknown)';\n throw new Error(\n `contract-to-postgres-schema-ir: policy \"${policyName}\" references table \"${tableName}\" not present in the schema`,\n );\n }\n }\n\n return new PostgresSchemaIR({\n tables,\n roles:\n contract === null\n ? []\n : Object.values(contract.storage.namespaces).flatMap((ns) =>\n isPostgresSchema(ns) ? Object.values(ns.role) : [],\n ),\n pgSchemaName: 'public',\n pgVersion: '',\n existingSchemas: ownedSchemas,\n nativeEnumTypeNames: [],\n });\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlPolicySubject } from '@prisma-next/family-sql/control';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { entityAt, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { isPostgresSchema } from '../postgres-schema';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\n\n/**\n * Factory calls that create a whole, previously-absent top-level storage\n * object. Used to decide whether `tolerated` permits a call (it only allows\n * creating absent objects, never modifying existing ones).\n *\n * Deliberately an explicit, closed set rather than a `factoryName`\n * create/alter/drop classification: it answers exactly one yes/no question\n * and is fail-closed. Any call not listed here — including future or\n * extension-contributed factories — is treated as NOT object-creation, so it\n * is suppressed under `tolerated` rather than permissively emitted.\n */\nconst OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([\n 'createTable',\n 'createSchema',\n 'createRlsPolicy',\n 'enableRowLevelSecurity',\n]);\n\nfunction createsNewTopLevelObject(call: PostgresOpFactoryCall): boolean {\n return OBJECT_CREATION_FACTORIES.has(call.factoryName);\n}\n\nfunction ddlSchemaNameForNamespace(contract: Contract<SqlStorage>, namespaceId: string): string {\n const namespace = contract.storage.namespaces[namespaceId];\n return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;\n}\n\nfunction resolveNamespaceIdForTable(\n contract: Contract<SqlStorage>,\n tableName: string,\n ddlSchemaName: string | undefined,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const table = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) continue;\n if (\n ddlSchemaName === undefined ||\n ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName\n ) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\nfunction resolveNamespaceIdForDdlSchema(\n contract: Contract<SqlStorage>,\n ddlSchemaName: string,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const ns = contract.storage.namespaces[namespaceId];\n if (isPostgresSchema(ns) && ns.ddlSchemaName(contract.storage) === ddlSchemaName) {\n return namespaceId;\n }\n if (namespaceId === ddlSchemaName) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\ninterface PostgresCallFields {\n readonly schemaName?: string;\n readonly tableName?: string;\n readonly columnName?: string;\n}\n\nfunction postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {\n return {\n ...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),\n ...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),\n ...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),\n };\n}\n\nexport function formatPostgresControlPolicySubjectLabel(\n factoryName: string,\n subject: ControlPolicySubject | undefined,\n contract: Contract<SqlStorage>,\n): string {\n if (subject?.table) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.table})`;\n }\n return factoryName;\n}\n\nexport function resolvePostgresCallControlPolicySubject(\n call: PostgresOpFactoryCall,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const callFields = postgresCallFields(call);\n const createsNewObject = createsNewTopLevelObject(call);\n\n if (call.factoryName === 'createSchema' && callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n if (callFields.tableName) {\n const namespaceId = resolveNamespaceIdForTable(\n contract,\n callFields.tableName,\n callFields.schemaName,\n );\n const tableControlPolicy = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: callFields.tableName,\n })?.control;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', tableControlPolicy),\n table: callFields.tableName,\n ...ifDefined('column', callFields.columnName),\n createsNewObject,\n };\n }\n\n if (callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n\n/**\n * Issue kinds that describe the absence of a whole, top-level Postgres\n * object — the same kinds `createsNewTopLevelObject` recognises for calls.\n * Used by {@link resolvePostgresIssueCreationFactoryName} to decide whether\n * a `tolerated` subject permits the issue to flow into the planner\n * (create-if-absent) and to seed the suppressed-subject warning's\n * `factoryName` when the planner is skipped.\n */\nconst POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({\n missing_schema: 'createSchema',\n missing_table: 'createTable',\n missing_rls_policy: 'createRlsPolicy',\n});\n\nexport function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {\n return POSTGRES_ISSUE_CREATION_FACTORY[issue.kind];\n}\n\n/**\n * Resolve the control-policy subject coordinate for a single\n * {@link SchemaIssue}. Mirrors the resolution `resolvePostgresCallControlPolicySubject`\n * performs for a generated DDL call, but works *off the issue* — so the\n * planner can partition issues by effective policy before the diff engine\n * runs. `createsNewObject` is derived from the issue's kind: schema/table/\n * type-missing issues describe a brand-new top-level object; everything else\n * touches an existing object.\n *\n * An `extra_table` issue carries no contract namespace coordinate (the table\n * isn't in any contract namespace), so the subject's `namespaceId` falls\n * back to {@link UNBOUND_NAMESPACE_ID}; the call-side resolver does the same\n * for the `DropTableCall` it produces.\n */\nexport function resolvePostgresIssueControlPolicySubject(\n issue: SchemaIssue,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const createsNewObject = POSTGRES_ISSUE_CREATION_FACTORY[issue.kind] !== undefined;\n\n if (issue.kind === 'missing_schema' && issue.namespaceId) {\n return { namespaceId: issue.namespaceId, createsNewObject };\n }\n\n if ('table' in issue && issue.table) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId\n ? issue.namespaceId\n : resolveNamespaceIdForTable(contract, issue.table, undefined);\n const table = entityAt<StorageTable>(contract.storage, {\n namespaceId,\n entityKind: 'table',\n entityName: issue.table,\n });\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', table?.control),\n table: issue.table,\n ...ifDefined('column', 'column' in issue ? issue.column : undefined),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n","import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';\nimport { diffSchemas } from '@prisma-next/framework-components/control';\nimport { isPostgresRlsPolicy, type PostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { ensurePostgresSchemaIR, type PostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\n\n// Renders a display-only reference string for the diff message. If policy\n// rendering grows, route it through the adapter's SQL renderer so the message\n// can't diverge from the emitted policy SQL.\nfunction renderPostgresPolicyReference(policy: PostgresRlsPolicy): string {\n return `policy \"${policy.name}\" on \"${policy.namespaceId}\".\"${policy.tableName}\"`;\n}\n\n/**\n * Computes schema drift between two derived schema IRs.\n *\n * 1. Runs the framework total diff.\n * 2. Filters to policy-subject issues only — this is transitional: the generic\n * differ walks the whole tree, but the legacy relational verifier still owns\n * table/column drift, so non-policy issues are dropped here.\n * 3. Remaps the message to a human-readable policy reference.\n *\n * Ownership filtering (dropping `extra` issues in namespaces a contract doesn't\n * own) is the caller's responsibility — use `filterIssuesByOwnership`.\n */\nexport function diffPostgresSchema(\n expected: PostgresSchemaIR,\n actual: PostgresSchemaIR,\n): readonly SchemaDiffIssue[] {\n const safeActual = ensurePostgresSchemaIR(actual);\n const issues = diffSchemas(expected, safeActual);\n\n return issues\n .filter((i) => isPostgresRlsPolicy(i.expected ?? i.actual))\n .map((i) => {\n const policy = i.expected ?? i.actual;\n if (!isPostgresRlsPolicy(policy)) return i;\n return { ...i, message: `${i.outcome}: ${renderPostgresPolicyReference(policy)}` };\n });\n}\n\n/**\n * Filters `extra` policy issues to those in owned namespaces. Call after\n * `diffPostgresSchema` with the union of namespace ids from the expected IR's\n * policies and its `existingSchemas`.\n */\nexport function filterIssuesByOwnership(\n issues: readonly SchemaDiffIssue[],\n ownedSchemaNames: ReadonlySet<string>,\n): readonly SchemaDiffIssue[] {\n return issues.filter(\n (i) =>\n i.outcome !== 'extra' ||\n (isPostgresRlsPolicy(i.actual) && ownedSchemaNames.has(i.actual.namespaceId)),\n );\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { isPostgresSchema } from '../postgres-schema';\nimport { isPostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\n\n/**\n * Resolves the live-database schema name for a given namespace\n * coordinate. Mirrors `resolveDdlSchemaForNamespace` in\n * `planner-strategies.ts` so the verifier's projection and the\n * planner's projection always agree — Postgres-aware namespaces (the\n * production path) dispatch to `ddlSchemaName(storage)`, and bare\n * object payloads (used by some tests) fall back to the coordinate\n * itself.\n */\nfunction resolveDdlSchemaName(storage: SqlStorage, namespaceId: string): string {\n const namespace = storage.namespaces[namespaceId];\n if (isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n\n/**\n * Reads the introspected list of schema names from a `PostgresSchemaIR`.\n * Defaults to the always-present `public` schema when the schema IR is not a\n * `PostgresSchemaIR` — a fresh Postgres database always carries `public`\n * (unless an operator dropped it manually), so any verifier path that runs\n * without an enriched introspection still suppresses the redundant\n * `CREATE SCHEMA \"public\"`.\n *\n * Production introspection (`PostgresControlAdapter.introspect`) is the\n * authoritative source: it queries `pg_namespace` and sets `existingSchemas`\n * on the returned `PostgresSchemaIR`. Tests that want to assert against a\n * richer initial state construct a `PostgresSchemaIR` explicitly.\n */\nfunction existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {\n if (isPostgresSchemaIR(schema)) {\n return schema.existingSchemas;\n }\n return ['public'];\n}\n\n/**\n * Emits a `missing_schema` issue for every contract-declared Postgres\n * namespace whose live container does not yet exist.\n *\n * A namespace's live container is the schema returned by its\n * polymorphic `ddlSchemaName(storage)` method — named schemas resolve\n * to their own id; the unbound singleton returns `UNBOUND_NAMESPACE_ID`\n * and is skipped explicitly (late-bound namespaces have no fixed DDL\n * schema). Issues are emitted only when the resolved name is a real,\n * creatable schema (not the unbound sentinel) and is missing from the\n * introspected list. `public` is suppressed implicitly because the\n * introspection (or its sensible default) always carries it.\n *\n * Each emitted issue stamps `namespaceId` with the contract namespace\n * coordinate so the downstream `mapIssueToCall` re-resolves the DDL\n * schema name through the same polymorphic path — keeping the\n * coordinate, not the resolved name, as the issue's stable identity.\n */\nexport function verifyPostgresNamespacePresence(input: {\n readonly contract: Contract<SqlStorage>;\n readonly schema: SqlSchemaIR;\n}): readonly SchemaIssue[] {\n const { contract, schema } = input;\n const existing = new Set(existingSchemasFromSchema(schema));\n const issues: SchemaIssue[] = [];\n const namespaceIds = Object.keys(contract.storage.namespaces).sort();\n for (const namespaceId of namespaceIds) {\n if (namespaceId === UNBOUND_NAMESPACE_ID) continue;\n const ddlName = resolveDdlSchemaName(contract.storage, namespaceId);\n if (ddlName === UNBOUND_NAMESPACE_ID) continue;\n if (existing.has(ddlName)) continue;\n issues.push({\n kind: 'missing_schema',\n namespaceId,\n message: `Schema \"${ddlName}\" is missing from database`,\n });\n }\n return issues;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlMigrationPlannerPlanOptions,\n SqlPlannerConflict,\n SqlPlannerFailureResult,\n} from '@prisma-next/family-sql/control';\nimport {\n extractCodecControlHooks,\n partitionCallsByControlPolicy,\n partitionIssuesByControlPolicy,\n planFieldEventOperations,\n plannerFailure,\n} from '@prisma-next/family-sql/control';\nimport type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';\nimport { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanner,\n MigrationPlanWithAuthoringSurface,\n MigrationScaffoldContext,\n SchemaIssue,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { parsePostgresDefault } from '../default-normalizer';\nimport { normalizeSchemaNativeType } from '../native-type-normalizer';\nimport type { PostgresContract } from '../postgres-schema';\nimport { assertPostgresRlsPolicy } from '../schema-ir/postgres-rls-policy';\nimport { assertPostgresSchemaIR, ensurePostgresSchemaIR } from '../schema-ir/postgres-schema-ir';\nimport { resolveDdlSchemaForNamespaceStorage } from '../schema-ir/postgres-schema-ir-annotations';\nimport { contractToPostgresSchemaIR } from './contract-to-postgres-schema-ir';\nimport {\n formatPostgresControlPolicySubjectLabel,\n resolvePostgresCallControlPolicySubject,\n resolvePostgresIssueControlPolicySubject,\n resolvePostgresIssueCreationFactoryName,\n} from './control-policy';\nimport { diffPostgresSchema, filterIssuesByOwnership } from './diff-postgres-schema';\nimport { planIssues } from './issue-planner';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\nimport {\n CreatePostgresRlsPolicyCall,\n DropPostgresRlsPolicyCall,\n EnableRowLevelSecurityCall,\n} from './op-factory-call';\nimport { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';\nimport { postgresPlannerStrategies } from './planner-strategies';\nimport { verifyPostgresNamespacePresence } from './verify-postgres-namespaces';\n\ntype PlannerFrameworkComponents = SqlMigrationPlannerPlanOptions extends {\n readonly frameworkComponents: infer T;\n}\n ? T\n : ReadonlyArray<unknown>;\n\ntype PlannerOptionsWithComponents = SqlMigrationPlannerPlanOptions & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\ntype VerifySqlSchemaOptionsWithComponents = Parameters<typeof verifySqlSchema>[0] & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\nexport function createPostgresMigrationPlanner(\n lowerer: ExecuteRequestLowerer,\n): PostgresMigrationPlanner {\n return new PostgresMigrationPlanner(lowerer);\n}\n\n/**\n * Result of `PostgresMigrationPlanner.plan()`. A discriminated union whose\n * success variant carries a `TypeScriptRenderablePostgresMigration` — a\n * migration object that both the CLI (via `renderTypeScript()`) and the\n * SQL-typed callers (via `operations`, `describe()`, etc.) consume\n * uniformly.\n */\nexport type PostgresPlanResult =\n | {\n readonly kind: 'success';\n readonly plan: TypeScriptRenderablePostgresMigration;\n readonly warnings?: readonly SqlPlannerConflict[];\n }\n | SqlPlannerFailureResult;\n\n/**\n * Postgres migration planner — a thin wrapper over `planIssues`.\n *\n * `plan()` verifies the live schema against the target contract (producing\n * `SchemaIssue[]`) and delegates to `planIssues` with the unified\n * `postgresPlannerStrategies` list: enum-change, NOT-NULL backfill,\n * type-change, nullable-tightening, codec-hook storage types,\n * component-declared dependency installs, and shared-temp-default /\n * empty-table-guarded NOT-NULL add-column. The same strategy list runs for\n * `migration plan`, `db update`, and `db init`; behavior diverges purely on\n * `policy.allowedOperationClasses` (the data-safe strategies short-circuit\n * when `'data'` is excluded). The issue planner applies operation-class\n * policy gates and emits a single `PostgresOpFactoryCall[]` that drives both\n * the runtime-ops view (via `renderOps`) and the `renderTypeScript()`\n * authoring surface.\n */\nexport class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgres'> {\n readonly #lowerer: ExecuteRequestLowerer | undefined;\n\n constructor(lowerer?: ExecuteRequestLowerer) {\n this.#lowerer = lowerer;\n }\n\n plan(options: {\n readonly contract: unknown;\n readonly schema: unknown;\n readonly policy: MigrationOperationPolicy;\n /**\n * The \"from\" contract (state the planner assumes the database starts\n * at), or `null` for reconciliation flows. Only `migration plan` ever\n * supplies a non-null value; `db update` / `db init` reconcile against\n * the live schema and pass `null`. When present alongside the\n * `'data'` operation class, strategies that need from/to column-shape\n * comparisons (unsafe type change, nullability tightening) activate.\n *\n * Typed as the framework `Contract | null` to satisfy the\n * `MigrationPlanner` interface contract; `planSql` narrows to the SQL\n * shape via `SqlMigrationPlannerPlanOptions`. Used to populate\n * `describe().from` on the produced plan as\n * `fromContract?.storage.storageHash ?? null`.\n */\n readonly fromContract: Contract | null;\n readonly schemaName?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Contract space this plan applies to. Stamped onto the produced\n * {@link TypeScriptRenderablePostgresMigration.spaceId} so the runner keys\n * the marker row by the right space.\n */\n readonly spaceId: string;\n }): PostgresPlanResult {\n return this.planSql(options as SqlMigrationPlannerPlanOptions);\n }\n\n emptyMigration(\n context: MigrationScaffoldContext,\n spaceId: string,\n ): MigrationPlanWithAuthoringSurface {\n return new TypeScriptRenderablePostgresMigration(\n [],\n {\n from: context.fromHash,\n to: context.toHash,\n },\n spaceId,\n this.#lowerer,\n );\n }\n\n private planSql(options: SqlMigrationPlannerPlanOptions): PostgresPlanResult {\n const schemaName =\n options.schemaName ??\n Object.keys(options.contract.storage.namespaces).find((id) => id !== UNBOUND_NAMESPACE_ID) ??\n UNBOUND_NAMESPACE_ID;\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) {\n return policyResult;\n }\n\n const schemaIssues = this.collectSchemaIssues(options);\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n const storageTypes = options.contract.storage.types ?? {};\n\n // Input-side control-policy partition. `external` / `observed` subjects\n // — and non-creation issues for `tolerated` subjects — are dropped from\n // the planner's input entirely; the planner never observes them, never\n // diffs them, never generates DDL for them. Suppression warnings are\n // built directly from the suppressed partition (one per subject), so the\n // user-visible message survives even when the planner would have failed\n // to model the subject's live shape.\n const issuePartition = partitionIssuesByControlPolicy({\n issues: schemaIssues,\n contract: options.contract,\n resolveControlPolicySubject: (issue) =>\n resolvePostgresIssueControlPolicySubject(issue, options.contract),\n resolveCreationFactoryName: resolvePostgresIssueCreationFactoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n const result = planIssues({\n issues: issuePartition.plannable,\n toContract: options.contract,\n // `fromContract` is only supplied by `migration plan`. It is `null` for\n // `db update` / `db init`, which means data-safety strategies needing\n // from/to comparisons (unsafe type change, nullable tightening) are\n // inapplicable there — reconciliation falls through to\n // `mapIssueToCall`'s direct destructive handlers.\n fromContract: options.fromContract,\n schemaName,\n codecHooks,\n storageTypes,\n schema: options.schema,\n policy: options.policy,\n frameworkComponents: options.frameworkComponents,\n strategies: postgresPlannerStrategies,\n });\n\n if (!result.ok) {\n return plannerFailure(result.failure);\n }\n\n const schemaDiffCalls = this.planPostgresSchemaDiff(options);\n const schemaDiffPartition = partitionCallsByControlPolicy({\n calls: schemaDiffCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n // Inline `onFieldEvent`-emitted ops after structural DDL. The fixed\n // ordering is `structural → added → dropped → altered`, with\n // within-group sorting by `(tableName, fieldName)` so re-emits are\n // byte-stable. The hook fires only at the application emitter —\n // extension-space planning never reaches this helper.\n const fieldEventOps = planFieldEventOperations({\n priorContract: options.fromContract,\n newContract: options.contract,\n codecHooks,\n });\n // Codec hook ops are target-agnostic `OpFactoryCall`; Postgres planning\n // lifts them at this integration boundary (see field-event-planner JSDoc).\n const fieldEventPostgresCalls = blindCast<\n readonly PostgresOpFactoryCall[],\n 'Codec hook ops conform to PostgresOpFactoryCall at the app emitter boundary'\n >(fieldEventOps);\n const fieldEventPartition = partitionCallsByControlPolicy({\n calls: fieldEventPostgresCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n const calls = [...result.value.calls, ...schemaDiffPartition.kept, ...fieldEventPartition.kept];\n const warnings: SqlPlannerConflict[] = [\n ...issuePartition.warnings,\n ...schemaDiffPartition.warnings,\n ...fieldEventPartition.warnings,\n ];\n\n return Object.freeze({\n kind: 'success' as const,\n plan: new TypeScriptRenderablePostgresMigration(\n calls,\n {\n from: options.fromContract?.storage.storageHash ?? null,\n to: options.contract.storage.storageHash,\n },\n options.spaceId,\n this.#lowerer,\n ),\n ...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),\n });\n }\n\n private planPostgresSchemaDiff(\n options: PlannerOptionsWithComponents,\n ): readonly PostgresOpFactoryCall[] {\n assertPostgresSchemaIR(options.schema);\n const expected = contractToPostgresSchemaIR(\n blindCast<PostgresContract, 'planPostgresSchemaDiff is only called with a postgres contract'>(\n options.contract,\n ),\n { annotationNamespace: 'pg' },\n );\n const actual = ensurePostgresSchemaIR(options.schema);\n const rawIssues = diffPostgresSchema(expected, actual);\n const ownedSchemaNames = new Set([\n ...expected.rlsPolicies.map((p) => p.namespaceId),\n ...expected.existingSchemas,\n ]);\n const filteredDiffIssues = filterIssuesByOwnership(rawIssues, ownedSchemaNames);\n\n const allowsDestructive = options.policy.allowedOperationClasses.includes('destructive');\n const calls: PostgresOpFactoryCall[] = [];\n const seenEnableTables = new Set<string>();\n\n for (const issue of filteredDiffIssues) {\n // 'mismatch' is unreachable for content-addressed policies: the wire name\n // encodes the body hash, so two policies sharing a local key (same name)\n // are always equal and isEqualTo never returns false.\n if (issue.outcome === 'missing') {\n assertPostgresRlsPolicy(issue.expected);\n // issue.expected.namespaceId is the DDL schema name (resolved during projection);\n // this re-resolution is a no-op as long as PostgresSchema.ddlSchemaName() returns this.id.\n const schemaForTable = resolveDdlSchemaForNamespaceStorage(\n options.contract.storage,\n issue.expected.namespaceId,\n options.schema,\n );\n const tableKey = `${schemaForTable}.${issue.expected.tableName}`;\n if (!seenEnableTables.has(tableKey)) {\n seenEnableTables.add(tableKey);\n calls.push(new EnableRowLevelSecurityCall(schemaForTable, issue.expected.tableName));\n }\n calls.push(\n new CreatePostgresRlsPolicyCall(schemaForTable, issue.expected.tableName, issue.expected),\n );\n } else if (issue.outcome === 'extra' && allowsDestructive) {\n assertPostgresRlsPolicy(issue.actual);\n const schemaForTable = resolveDdlSchemaForNamespaceStorage(\n options.contract.storage,\n issue.actual.namespaceId,\n options.schema,\n );\n calls.push(\n new DropPostgresRlsPolicyCall(schemaForTable, issue.actual.tableName, issue.actual.name),\n );\n }\n }\n\n return calls;\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy) {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Migration planner requires additive operations be allowed',\n why: 'The planner requires the \"additive\" operation class to be allowed in the policy.',\n },\n ]);\n }\n return null;\n }\n\n private collectSchemaIssues(options: PlannerOptionsWithComponents): readonly SchemaIssue[] {\n // `db init` uses additive-only policy and intentionally ignores extra\n // schema objects. Any reconciliation-capable policy (widening or\n // destructive) must inspect extras to reconcile strict equality.\n const allowed = options.policy.allowedOperationClasses;\n const strict = allowed.includes('widening') || allowed.includes('destructive');\n const verifyOptions: VerifySqlSchemaOptionsWithComponents = {\n contract: options.contract,\n schema: options.schema,\n strict,\n typeMetadataRegistry: new Map(),\n frameworkComponents: options.frameworkComponents,\n normalizeDefault: parsePostgresDefault,\n normalizeNativeType: normalizeSchemaNativeType,\n };\n const verifyResult = verifySqlSchema(verifyOptions);\n // Schema presence is a Postgres-specific concern (no equivalent in\n // SQLite / Mongo), so the issue emission lives in the target layer\n // rather than in the family verifier. Stitch it in here so a single\n // `SchemaIssue[]` flows through `planIssues` and the planner emits\n // CREATE SCHEMA in the dep bucket before any CreateTableCall.\n // Schema drift is handled separately via diffPostgresSchema → planPostgresSchemaDiff.\n const namespaceIssues = verifyPostgresNamespacePresence({\n contract: options.contract,\n schema: options.schema,\n });\n if (namespaceIssues.length === 0) {\n return verifyResult.schema.issues;\n }\n return [...namespaceIssues, ...verifyResult.schema.issues];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAUA,SAAgB,2BACd,UACA,SACkB;CAClB,MAAM,QAAQ,mBAAmB,UAAU,OAAO;CAClD,MAAM,eACJ,aAAa,OACT,CAAC,IACD,OAAO,OAAO,SAAS,QAAQ,UAAU,CAAC,CACvC,QAAQ,OAAO,iBAAiB,EAAE,CAAC,CAAC,CACpC,KAAK,OAAO,oCAAoC,SAAS,SAAS,GAAG,EAAE,CAAC;CAIjF,MAAM,kCAAkB,IAAI,IAAiC;CAC7D,IAAI,aAAa,MACf,KAAK,MAAM,MAAM,OAAO,OAAO,SAAS,QAAQ,UAAU,GAAG;EAC3D,IAAI,CAAC,iBAAiB,EAAE,GAAG;EAC3B,MAAM,iBAAiB,oCAAoC,SAAS,SAAS,GAAG,EAAE;EAClF,KAAK,MAAM,UAAU,OAAO,OAAO,GAAG,MAAM,GAAG;GAC7C,MAAM,WACJ,mBAAmB,OAAO,cACtB,SACA,IAAI,kBAAkB;IACpB,MAAM,OAAO;IACb,QAAQ,OAAO;IACf,WAAW,OAAO;IAClB,aAAa;IACb,WAAW,OAAO;IAClB,OAAO,CAAC,GAAG,OAAO,KAAK;IACvB,GAAG,UAAU,SAAS,OAAO,KAAK;IAClC,GAAG,UAAU,aAAa,OAAO,SAAS;IAC1C,YAAY,OAAO;GACrB,CAAC;GACP,MAAM,OAAO,gBAAgB,IAAI,OAAO,SAAS,KAAK,CAAC;GACvD,KAAK,KAAK,QAAQ;GAClB,gBAAgB,IAAI,OAAO,WAAW,IAAI;EAC5C;CACF;CAMF,MAAM,SAA0C,CAAC;CACjD,KAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,MAAM,MAAM,GAC7D,OAAO,aAAa,IAAI,gBAAgB;EACtC,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,aAAa,SAAS;EACtB,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,GAAI,SAAS,eAAe,KAAA,IAAY,EAAE,YAAY,SAAS,WAAW,IAAI,CAAC;EAC/E,GAAI,SAAS,gBAAgB,KAAA,IAAY,EAAE,aAAa,SAAS,YAAY,IAAI,CAAC;EAClF,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,SAAS,OAAO,IAAI,CAAC;EACnE,aAAa,gBAAgB,IAAI,SAAS,KAAK,CAAC;CAClD,CAAC;CAEH,KAAK,MAAM,CAAC,WAAW,aAAa,iBAClC,IAAI,EAAE,aAAa,SAAS;EAC1B,MAAM,aAAa,SAAS,EAAE,EAAE,QAAQ;EACxC,MAAM,IAAI,MACR,2CAA2C,WAAW,sBAAsB,UAAU,4BACxF;CACF;CAGF,OAAO,IAAI,iBAAiB;EAC1B;EACA,OACE,aAAa,OACT,CAAC,IACD,OAAO,OAAO,SAAS,QAAQ,UAAU,CAAC,CAAC,SAAS,OAClD,iBAAiB,EAAE,IAAI,OAAO,OAAO,GAAG,IAAI,IAAI,CAAC,CACnD;EACN,cAAc;EACd,WAAW;EACX,iBAAiB;EACjB,qBAAqB,CAAC;CACxB,CAAC;AACH;;;;;;;;;;;;;;ACtEA,MAAM,4BAAiD,IAAI,IAAY;CACrE;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,yBAAyB,MAAsC;CACtE,OAAO,0BAA0B,IAAI,KAAK,WAAW;AACvD;AAEA,SAAS,0BAA0B,UAAgC,aAA6B;CAC9F,MAAM,YAAY,SAAS,QAAQ,WAAW;CAC9C,OAAO,iBAAiB,SAAS,IAAI,UAAU,cAAc,SAAS,OAAO,IAAI;AACnF;AAEA,SAAS,2BACP,UACA,WACA,eACQ;CACR,KAAK,MAAM,eAAe,OAAO,KAAK,SAAS,QAAQ,UAAU,GAAG;EAMlE,IAAI,CALU,SAAuB,SAAS,SAAS;GACrD;GACA,YAAY;GACZ,YAAY;EACd,CACS,GAAG;EACZ,IACE,kBAAkB,KAAA,KAClB,0BAA0B,UAAU,WAAW,MAAM,eAErD,OAAO;CAEX;CACA,OAAO;AACT;AAEA,SAAS,+BACP,UACA,eACQ;CACR,KAAK,MAAM,eAAe,OAAO,KAAK,SAAS,QAAQ,UAAU,GAAG;EAClE,MAAM,KAAK,SAAS,QAAQ,WAAW;EACvC,IAAI,iBAAiB,EAAE,KAAK,GAAG,cAAc,SAAS,OAAO,MAAM,eACjE,OAAO;EAET,IAAI,gBAAgB,eAClB,OAAO;CAEX;CACA,OAAO;AACT;AAQA,SAAS,mBAAmB,MAAiD;CAC3E,OAAO;EACL,GAAG,UAAU,cAAc,gBAAgB,OAAO,KAAK,aAAa,KAAA,CAAS;EAC7E,GAAG,UAAU,aAAa,eAAe,OAAO,KAAK,YAAY,KAAA,CAAS;EAC1E,GAAG,UAAU,cAAc,gBAAgB,OAAO,KAAK,aAAa,KAAA,CAAS;CAC/E;AACF;AAEA,SAAgB,wCACd,aACA,SACA,UACQ;CACR,IAAI,SAAS,OAEX,OAAO,GAAG,YAAY,GADJ,0BAA0B,UAAU,QAAQ,WAC7B,EAAE,GAAG,QAAQ,MAAM;CAEtD,OAAO;AACT;AAEA,SAAgB,wCACd,MACA,UACkC;CAClC,MAAM,aAAa,mBAAmB,IAAI;CAC1C,MAAM,mBAAmB,yBAAyB,IAAI;CAEtD,IAAI,KAAK,gBAAgB,kBAAkB,WAAW,YACpD,OAAO;EACL,aAAa,+BAA+B,UAAU,WAAW,UAAU;EAC3E;CACF;CAGF,IAAI,WAAW,WAAW;EACxB,MAAM,cAAc,2BAClB,UACA,WAAW,WACX,WAAW,UACb;EACA,MAAM,qBAAqB,SAAuB,SAAS,SAAS;GAClE;GACA,YAAY;GACZ,YAAY,WAAW;EACzB,CAAC,CAAC,EAAE;EACJ,OAAO;GACL;GACA,GAAG,UAAU,6BAA6B,kBAAkB;GAC5D,OAAO,WAAW;GAClB,GAAG,UAAU,UAAU,WAAW,UAAU;GAC5C;EACF;CACF;CAEA,IAAI,WAAW,YACb,OAAO;EACL,aAAa,+BAA+B,UAAU,WAAW,UAAU;EAC3E;CACF;AAIJ;;;;;;;;;AAUA,MAAM,kCAAoE,OAAO,OAAO;CACtF,gBAAgB;CAChB,eAAe;CACf,oBAAoB;AACtB,CAAC;AAED,SAAgB,wCAAwC,OAAwC;CAC9F,OAAO,gCAAgC,MAAM;AAC/C;;;;;;;;;;;;;;;AAgBA,SAAgB,yCACd,OACA,UACkC;CAClC,MAAM,mBAAmB,gCAAgC,MAAM,UAAU,KAAA;CAEzE,IAAI,MAAM,SAAS,oBAAoB,MAAM,aAC3C,OAAO;EAAE,aAAa,MAAM;EAAa;CAAiB;CAG5D,IAAI,WAAW,SAAS,MAAM,OAAO;EACnC,MAAM,cACJ,iBAAiB,SAAS,MAAM,cAC5B,MAAM,cACN,2BAA2B,UAAU,MAAM,OAAO,KAAA,CAAS;EAMjE,OAAO;GACL;GACA,GAAG,UAAU,6BAPD,SAAuB,SAAS,SAAS;IACrD;IACA,YAAY;IACZ,YAAY,MAAM;GACpB,CAGgD,CAAC,EAAE,OAAO;GACxD,OAAO,MAAM;GACb,GAAG,UAAU,UAAU,YAAY,QAAQ,MAAM,SAAS,KAAA,CAAS;GACnE;EACF;CACF;AAGF;;;ACtMA,SAAS,8BAA8B,QAAmC;CACxE,OAAO,WAAW,OAAO,KAAK,QAAQ,OAAO,YAAY,KAAK,OAAO,UAAU;AACjF;;;;;;;;;;;;;AAcA,SAAgB,mBACd,UACA,QAC4B;CAI5B,OAFe,YAAY,UADR,uBAAuB,MACI,CAElC,CAAC,CACV,QAAQ,MAAM,oBAAoB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAC1D,KAAK,MAAM;EACV,MAAM,SAAS,EAAE,YAAY,EAAE;EAC/B,IAAI,CAAC,oBAAoB,MAAM,GAAG,OAAO;EACzC,OAAO;GAAE,GAAG;GAAG,SAAS,GAAG,EAAE,QAAQ,IAAI,8BAA8B,MAAM;EAAI;CACnF,CAAC;AACL;;;;;;AAOA,SAAgB,wBACd,QACA,kBAC4B;CAC5B,OAAO,OAAO,QACX,MACC,EAAE,YAAY,WACb,oBAAoB,EAAE,MAAM,KAAK,iBAAiB,IAAI,EAAE,OAAO,WAAW,CAC/E;AACF;;;;;;;;;;;;ACrCA,SAAS,qBAAqB,SAAqB,aAA6B;CAC9E,MAAM,YAAY,QAAQ,WAAW;CACrC,IAAI,iBAAiB,SAAS,GAC5B,OAAO,UAAU,cAAc,OAAO;CAExC,OAAO;AACT;;;;;;;;;;;;;;AAeA,SAAS,0BAA0B,QAAwC;CACzE,IAAI,mBAAmB,MAAM,GAC3B,OAAO,OAAO;CAEhB,OAAO,CAAC,QAAQ;AAClB;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,gCAAgC,OAGrB;CACzB,MAAM,EAAE,UAAU,WAAW;CAC7B,MAAM,WAAW,IAAI,IAAI,0BAA0B,MAAM,CAAC;CAC1D,MAAM,SAAwB,CAAC;CAC/B,MAAM,eAAe,OAAO,KAAK,SAAS,QAAQ,UAAU,CAAC,CAAC,KAAK;CACnE,KAAK,MAAM,eAAe,cAAc;EACtC,IAAI,gBAAgB,sBAAsB;EAC1C,MAAM,UAAU,qBAAqB,SAAS,SAAS,WAAW;EAClE,IAAI,YAAY,sBAAsB;EACtC,IAAI,SAAS,IAAI,OAAO,GAAG;EAC3B,OAAO,KAAK;GACV,MAAM;GACN;GACA,SAAS,WAAW,QAAQ;EAC9B,CAAC;CACH;CACA,OAAO;AACT;;;ACnBA,SAAgB,+BACd,SAC0B;CAC1B,OAAO,IAAI,yBAAyB,OAAO;AAC7C;;;;;;;;;;;;;;;;;AAiCA,IAAa,2BAAb,MAAqF;CACnF;CAEA,YAAY,SAAiC;EAC3C,KAAKA,WAAW;CAClB;CAEA,KAAK,SA2BkB;EACrB,OAAO,KAAK,QAAQ,OAAyC;CAC/D;CAEA,eACE,SACA,SACmC;EACnC,OAAO,IAAI,sCACT,CAAC,GACD;GACE,MAAM,QAAQ;GACd,IAAI,QAAQ;EACd,GACA,SACA,KAAKA,QACP;CACF;CAEA,QAAgB,SAA6D;EAC3E,MAAM,aACJ,QAAQ,cACR,OAAO,KAAK,QAAQ,SAAS,QAAQ,UAAU,CAAC,CAAC,MAAM,OAAO,OAAO,oBAAoB,KACzF;EACF,MAAM,eAAe,KAAK,qBAAqB,QAAQ,MAAM;EAC7D,IAAI,cACF,OAAO;EAGT,MAAM,eAAe,KAAK,oBAAoB,OAAO;EACrD,MAAM,aAAa,yBAAyB,QAAQ,mBAAmB;EACvE,MAAM,eAAe,QAAQ,SAAS,QAAQ,SAAS,CAAC;EASxD,MAAM,iBAAiB,+BAA+B;GACpD,QAAQ;GACR,UAAU,QAAQ;GAClB,8BAA8B,UAC5B,yCAAyC,OAAO,QAAQ,QAAQ;GAClE,4BAA4B;GAC5B,qBAAqB,aAAa,YAChC,wCAAwC,aAAa,SAAS,QAAQ,QAAQ;EAClF,CAAC;EAED,MAAM,SAAS,WAAW;GACxB,QAAQ,eAAe;GACvB,YAAY,QAAQ;GAMpB,cAAc,QAAQ;GACtB;GACA;GACA;GACA,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB,qBAAqB,QAAQ;GAC7B,YAAY;EACd,CAAC;EAED,IAAI,CAAC,OAAO,IACV,OAAO,eAAe,OAAO,OAAO;EAItC,MAAM,sBAAsB,8BAA8B;GACxD,OAFsB,KAAK,uBAAuB,OAE7B;GACrB,UAAU,QAAQ;GAClB,8BAA8B,SAC5B,wCAAwC,MAAM,QAAQ,QAAQ;GAChE,qBAAqB,SAAS,KAAK;GACnC,qBAAqB,aAAa,YAChC,wCAAwC,aAAa,SAAS,QAAQ,QAAQ;EAClF,CAAC;EAkBD,MAAM,sBAAsB,8BAA8B;GACxD,OAL8B,UAPV,yBAAyB;IAC7C,eAAe,QAAQ;IACvB,aAAa,QAAQ;IACrB;GACF,CAMc,CAEiB;GAC7B,UAAU,QAAQ;GAClB,8BAA8B,SAC5B,wCAAwC,MAAM,QAAQ,QAAQ;GAChE,qBAAqB,SAAS,KAAK;GACnC,qBAAqB,aAAa,YAChC,wCAAwC,aAAa,SAAS,QAAQ,QAAQ;EAClF,CAAC;EACD,MAAM,QAAQ;GAAC,GAAG,OAAO,MAAM;GAAO,GAAG,oBAAoB;GAAM,GAAG,oBAAoB;EAAI;EAC9F,MAAM,WAAiC;GACrC,GAAG,eAAe;GAClB,GAAG,oBAAoB;GACvB,GAAG,oBAAoB;EACzB;EAEA,OAAO,OAAO,OAAO;GACnB,MAAM;GACN,MAAM,IAAI,sCACR,OACA;IACE,MAAM,QAAQ,cAAc,QAAQ,eAAe;IACnD,IAAI,QAAQ,SAAS,QAAQ;GAC/B,GACA,QAAQ,SACR,KAAKA,QACP;GACA,GAAI,SAAS,SAAS,IAAI,EAAE,UAAU,OAAO,OAAO,QAAQ,EAAE,IAAI,CAAC;EACrE,CAAC;CACH;CAEA,uBACE,SACkC;EAClC,uBAAuB,QAAQ,MAAM;EACrC,MAAM,WAAW,2BACf,UACE,QAAQ,QACV,GACA,EAAE,qBAAqB,KAAK,CAC9B;EAOA,MAAM,qBAAqB,wBALT,mBAAmB,UADtB,uBAAuB,QAAQ,MACM,CAKO,GAAG,IAJjC,IAAI,CAC/B,GAAG,SAAS,YAAY,KAAK,MAAM,EAAE,WAAW,GAChD,GAAG,SAAS,eACd,CAC6E,CAAC;EAE9E,MAAM,oBAAoB,QAAQ,OAAO,wBAAwB,SAAS,aAAa;EACvF,MAAM,QAAiC,CAAC;EACxC,MAAM,mCAAmB,IAAI,IAAY;EAEzC,KAAK,MAAM,SAAS,oBAIlB,IAAI,MAAM,YAAY,WAAW;GAC/B,wBAAwB,MAAM,QAAQ;GAGtC,MAAM,iBAAiB,oCACrB,QAAQ,SAAS,SACjB,MAAM,SAAS,aACf,QAAQ,MACV;GACA,MAAM,WAAW,GAAG,eAAe,GAAG,MAAM,SAAS;GACrD,IAAI,CAAC,iBAAiB,IAAI,QAAQ,GAAG;IACnC,iBAAiB,IAAI,QAAQ;IAC7B,MAAM,KAAK,IAAI,2BAA2B,gBAAgB,MAAM,SAAS,SAAS,CAAC;GACrF;GACA,MAAM,KACJ,IAAI,4BAA4B,gBAAgB,MAAM,SAAS,WAAW,MAAM,QAAQ,CAC1F;EACF,OAAO,IAAI,MAAM,YAAY,WAAW,mBAAmB;GACzD,wBAAwB,MAAM,MAAM;GACpC,MAAM,iBAAiB,oCACrB,QAAQ,SAAS,SACjB,MAAM,OAAO,aACb,QAAQ,MACV;GACA,MAAM,KACJ,IAAI,0BAA0B,gBAAgB,MAAM,OAAO,WAAW,MAAM,OAAO,IAAI,CACzF;EACF;EAGF,OAAO;CACT;CAEA,qBAA6B,QAAkC;EAC7D,IAAI,CAAC,OAAO,wBAAwB,SAAS,UAAU,GACrD,OAAO,eAAe,CACpB;GACE,MAAM;GACN,SAAS;GACT,KAAK;EACP,CACF,CAAC;EAEH,OAAO;CACT;CAEA,oBAA4B,SAA+D;EAIzF,MAAM,UAAU,QAAQ,OAAO;EAC/B,MAAM,SAAS,QAAQ,SAAS,UAAU,KAAK,QAAQ,SAAS,aAAa;EAU7E,MAAM,eAAe,gBAAgB;GARnC,UAAU,QAAQ;GAClB,QAAQ,QAAQ;GAChB;GACA,sCAAsB,IAAI,IAAI;GAC9B,qBAAqB,QAAQ;GAC7B,kBAAkB;GAClB,qBAAqB;EAE0B,CAAC;EAOlD,MAAM,kBAAkB,gCAAgC;GACtD,UAAU,QAAQ;GAClB,QAAQ,QAAQ;EAClB,CAAC;EACD,IAAI,gBAAgB,WAAW,GAC7B,OAAO,aAAa,OAAO;EAE7B,OAAO,CAAC,GAAG,iBAAiB,GAAG,aAAa,OAAO,MAAM;CAC3D;AACF"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as PostgresPlanTargetDetails } from "./planner-target-details-HkP4RrRO.mjs";
|
|
2
|
-
import { t as PostgresMigration } from "./postgres-migration-
|
|
2
|
+
import { t as PostgresMigration } from "./postgres-migration-UtGCjw5j.mjs";
|
|
3
3
|
import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
|
|
4
4
|
import { MigrationPlanWithAuthoringSurface, OpFactoryCall } from "@prisma-next/framework-components/control";
|
|
5
|
-
import { ExecuteRequestLowerer } from "@prisma-next/family-sql/control-adapter";
|
|
6
5
|
import { MigrationMeta } from "@prisma-next/migration-tools/migration";
|
|
6
|
+
import { ExecuteRequestLowerer } from "@prisma-next/family-sql/control-adapter";
|
|
7
7
|
|
|
8
8
|
//#region src/core/migrations/planner-produced-postgres-migration.d.ts
|
|
9
9
|
declare class TypeScriptRenderablePostgresMigration extends PostgresMigration implements MigrationPlanWithAuthoringSurface {
|
|
@@ -21,4 +21,4 @@ declare class TypeScriptRenderablePostgresMigration extends PostgresMigration im
|
|
|
21
21
|
}
|
|
22
22
|
//#endregion
|
|
23
23
|
export { TypeScriptRenderablePostgresMigration as t };
|
|
24
|
-
//# sourceMappingURL=planner-produced-postgres-migration-
|
|
24
|
+
//# sourceMappingURL=planner-produced-postgres-migration-BauTSigX.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-produced-postgres-migration-
|
|
1
|
+
{"version":3,"file":"planner-produced-postgres-migration-BauTSigX.d.mts","names":[],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"mappings":";;;;;;;;cAqCa,qCAAA,SACH,iBAAA,YACG,iCAAA;EAAA;cAcT,KAAA,WAAgB,aAAA,IAChB,IAAA,EAAM,aAAA,EACN,OAAA,UACA,OAAA,GAAU,qBAAA;EAAA,IASC,UAAA,cACT,yBAAA,CAA0B,yBAAA,IAC1B,OAAA,CAAQ,yBAAA,CAA0B,yBAAA;EAM7B,QAAA,IAAY,aAAA;EARR;;;;;EAAA,IAiBT,OAAA;EAIJ,gBAAA;AAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as PostgresMigration } from "./postgres-migration-
|
|
1
|
+
import { t as PostgresMigration } from "./postgres-migration-DEefginX.mjs";
|
|
2
2
|
import { t as renderOps } from "./render-ops-BREh1kHe.mjs";
|
|
3
|
-
import { t as renderCallsToTypeScript } from "./render-typescript-
|
|
3
|
+
import { t as renderCallsToTypeScript } from "./render-typescript-7yqILcwr.mjs";
|
|
4
4
|
//#region src/core/migrations/planner-produced-postgres-migration.ts
|
|
5
5
|
var TypeScriptRenderablePostgresMigration = class extends PostgresMigration {
|
|
6
6
|
#calls;
|
|
@@ -40,4 +40,4 @@ var TypeScriptRenderablePostgresMigration = class extends PostgresMigration {
|
|
|
40
40
|
//#endregion
|
|
41
41
|
export { TypeScriptRenderablePostgresMigration as t };
|
|
42
42
|
|
|
43
|
-
//# sourceMappingURL=planner-produced-postgres-migration-
|
|
43
|
+
//# sourceMappingURL=planner-produced-postgres-migration-Bbv8RYKJ.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-produced-postgres-migration-
|
|
1
|
+
{"version":3,"file":"planner-produced-postgres-migration-Bbv8RYKJ.mjs","names":["#calls","#meta","#spaceId","#lowerer","#operationsCache"],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"sourcesContent":["/**\n * Planner-produced Postgres migration.\n *\n * Returned by `PostgresMigrationPlanner.plan(...)` and `emptyMigration(...)`.\n * Holds the migration IR (`PostgresOpFactoryCall[]`) alongside\n * `MigrationMeta` and exposes both the runtime-ops view (`get operations`)\n * and the TypeScript authoring view (`renderTypeScript()`). Satisfies\n * `MigrationPlanWithAuthoringSurface` so the CLI can uniformly serialize any\n * planner result back to `migration.ts`.\n *\n * Extends the family-level `SqlMigration` alias rather than the target-local\n * migration base directly — mirrors Mongo's `PlannerProducedMongoMigration`\n * shape and keeps CLI wiring one step removed from target internals.\n *\n * Placeholder-bearing plans: `renderTypeScript()` always succeeds and embeds\n * `() => placeholder(\"slot\")` at each stub. `operations`, in contrast, is\n * _not safe to enumerate_ on a stub-bearing plan — `DataTransformCall.toOp()`\n * throws `PN-MIG-2001` because a planner-stubbed closure cannot be lowered\n * to a runtime op. Callers that know a plan may carry stubs must render to\n * `migration.ts`, let the user fill the slots, and re-load the edited\n * migration before enumerating ops. The walk-schema planner does not emit\n * `DataTransformCall`s today, so this asymmetry is invisible until the\n * issue-planner integration lands in Phase 2.\n */\n\nimport type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';\nimport type {\n MigrationPlanWithAuthoringSurface,\n OpFactoryCall,\n} from '@prisma-next/framework-components/control';\nimport type { MigrationMeta } from '@prisma-next/migration-tools/migration';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\nimport { PostgresMigration } from './postgres-migration';\nimport { renderOps } from './render-ops';\nimport { renderCallsToTypeScript } from './render-typescript';\n\nexport class TypeScriptRenderablePostgresMigration\n extends PostgresMigration\n implements MigrationPlanWithAuthoringSurface\n{\n readonly #calls: readonly OpFactoryCall[];\n readonly #meta: MigrationMeta;\n readonly #spaceId: string;\n readonly #lowerer: ExecuteRequestLowerer | undefined;\n #operationsCache:\n | readonly (\n | SqlMigrationPlanOperation<PostgresPlanTargetDetails>\n | Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>>\n )[]\n | undefined;\n\n constructor(\n calls: readonly OpFactoryCall[],\n meta: MigrationMeta,\n spaceId: string,\n lowerer?: ExecuteRequestLowerer,\n ) {\n super();\n this.#calls = calls;\n this.#meta = meta;\n this.#spaceId = spaceId;\n this.#lowerer = lowerer;\n }\n\n override get operations(): readonly (\n | SqlMigrationPlanOperation<PostgresPlanTargetDetails>\n | Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>>\n )[] {\n this.#operationsCache ??= renderOps(this.#calls, this.#lowerer);\n return this.#operationsCache;\n }\n\n override describe(): MigrationMeta {\n return this.#meta;\n }\n\n /**\n * Contract space this planner-produced plan applies to. Threaded\n * from the planner options so the runner keys the marker row by\n * the right space when executing the plan.\n */\n get spaceId(): string {\n return this.#spaceId;\n }\n\n renderTypeScript(): string {\n return renderCallsToTypeScript(this.#calls, { from: this.#meta.from, to: this.#meta.to });\n }\n}\n"],"mappings":";;;;AAqCA,IAAa,wCAAb,cACU,kBAEV;CACE;CACA;CACA;CACA;CACA;CAOA,YACE,OACA,MACA,SACA,SACA;EACA,MAAM;EACN,KAAKA,SAAS;EACd,KAAKC,QAAQ;EACb,KAAKC,WAAW;EAChB,KAAKC,WAAW;CAClB;CAEA,IAAa,aAGT;EACF,KAAKC,qBAAqB,UAAU,KAAKJ,QAAQ,KAAKG,QAAQ;EAC9D,OAAO,KAAKC;CACd;CAEA,WAAmC;EACjC,OAAO,KAAKH;CACd;;;;;;CAOA,IAAI,UAAkB;EACpB,OAAO,KAAKC;CACd;CAEA,mBAA2B;EACzB,OAAO,wBAAwB,KAAKF,QAAQ;GAAE,MAAM,KAAKC,MAAM;GAAM,IAAI,KAAKA,MAAM;EAAG,CAAC;CAC1F;AACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-
|
|
1
|
+
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-BauTSigX.mjs";
|
|
2
2
|
export { TypeScriptRenderablePostgresMigration };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-
|
|
1
|
+
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-Bbv8RYKJ.mjs";
|
|
2
2
|
export { TypeScriptRenderablePostgresMigration };
|
package/dist/planner.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as PostgresContract } from "./postgres-schema-DJUEkWg-.mjs";
|
|
2
|
-
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-
|
|
2
|
+
import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-BauTSigX.mjs";
|
|
3
3
|
import { t as PostgresSchemaIR } from "./postgres-schema-ir-BJl_a3J7.mjs";
|
|
4
4
|
import { ContractToSchemaIROptions, MigrationOperationPolicy, SqlPlannerConflict, SqlPlannerFailureResult } from "@prisma-next/family-sql/control";
|
|
5
5
|
import { MigrationPlanWithAuthoringSurface, MigrationPlanner, MigrationScaffoldContext, SchemaDiffIssue } from "@prisma-next/framework-components/control";
|
package/dist/planner.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as contractToPostgresSchemaIR, n as diffPostgresSchema, r as filterIssuesByOwnership, t as createPostgresMigrationPlanner } from "./planner-
|
|
1
|
+
import { i as contractToPostgresSchemaIR, n as diffPostgresSchema, r as filterIssuesByOwnership, t as createPostgresMigrationPlanner } from "./planner-D3Pl8LXU.mjs";
|
|
2
2
|
export { contractToPostgresSchemaIR, createPostgresMigrationPlanner, diffPostgresSchema, filterIssuesByOwnership };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SqlStorage } from "@prisma-next/sql-contract/types";
|
|
2
|
+
import { SqlSchemaQualifiedView } from "@prisma-next/sql-contract/contract-view";
|
|
3
|
+
import { Contract } from "@prisma-next/contract/types";
|
|
4
|
+
|
|
5
|
+
//#region src/core/postgres-contract-view.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A schema-qualified Postgres contract view: the deserialized contract
|
|
8
|
+
* intersected with a single `namespace` member holding every schema by id. It is
|
|
9
|
+
* substitutable for `Contract` (carries `storage`, `domain`, …) and reaches each
|
|
10
|
+
* schema's entities through `view.namespace.<schema>`:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const view = PostgresContractView.fromJson<Contract>(contractJson);
|
|
14
|
+
* view.namespace.public.table.users // typed table leaf in the public schema
|
|
15
|
+
* view.namespace.auth.table.users // the auth schema's own users table
|
|
16
|
+
* view.namespace.public.entries.policy.X // pack-contributed kind (RLS / #771 path)
|
|
17
|
+
* view.namespace.__unbound__.table.X // default schema, keyed by its raw id
|
|
18
|
+
* view.storage // the full contract is still present
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* This mirrors the runtime `db.enums.<ns>` keying exactly (the default schema
|
|
22
|
+
* keeps its literal `__unbound__` id). Schema names are NOT promoted to the
|
|
23
|
+
* contract root, so there is no collision with contract envelope fields — a
|
|
24
|
+
* schema named `storage` is `view.namespace.storage`, while `view.storage`
|
|
25
|
+
* stays the contract's `storage`.
|
|
26
|
+
*/
|
|
27
|
+
type PostgresContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> = SqlSchemaQualifiedView<TContract>;
|
|
28
|
+
declare const PostgresContractView: {
|
|
29
|
+
/** Wrap an already-deserialized Postgres contract in a schema-qualified view. */from<TContract extends Contract<SqlStorage>>(contract: TContract): PostgresContractView<TContract>; /** Deserialize a Postgres contract JSON envelope and wrap it in a view. */
|
|
30
|
+
fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage<string>>>(json: unknown): PostgresContractView<TContract>;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PostgresContractView as t };
|
|
34
|
+
//# sourceMappingURL=postgres-contract-view-C9j5cqP0.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-contract-view-C9j5cqP0.d.mts","names":[],"sources":["../src/core/postgres-contract-view.ts"],"mappings":";;;;;;;AA6BA;;;;;;;;;;;;;;;;;;;KAAY,oBAAA,mBAAuC,QAAA,CAAS,UAAA,IAAc,QAAA,CAAS,UAAA,KACjF,sBAAA,CAAuB,SAAA;AAAA,cAEZ,oBAAA;EAeZ,wGAbwB,QAAA,CAAS,UAAA,GAAW,QAAA,EAC/B,SAAA,GACT,oBAAA,CAAqB,SAAA,GAFQ;6BAOL,QAAA,CAAS,UAAA,IAAW,QAAA,CAAA,UAAA,WAAA,IAAA,YAE5C,oBAAA,CAAqB,SAAA;AAAA"}
|
package/dist/{postgres-contract-serializer-tGMiJcl4.mjs → postgres-contract-view-D12LEXT5.mjs}
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { a as policyEntityKind, o as roleEntityKind, r as isPostgresSchema, t as PostgresSchema } from "./postgres-schema-DLcc3W2-.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { t as postgresAuthoringEntityTypes } from "./authoring-CZmSQriw.mjs";
|
|
3
3
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
4
4
|
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
5
|
+
import { buildSqlSchemaQualifiedView } from "@prisma-next/sql-contract/contract-view";
|
|
5
6
|
import { SqlContractSerializerBase } from "@prisma-next/family-sql/ir";
|
|
6
7
|
import { isAuthoringEntityTypeDescriptor } from "@prisma-next/framework-components/authoring";
|
|
7
8
|
//#region src/core/postgres-contract-serializer.ts
|
|
@@ -111,6 +112,18 @@ var PostgresContractSerializer = class extends SqlContractSerializerBase {
|
|
|
111
112
|
}
|
|
112
113
|
};
|
|
113
114
|
//#endregion
|
|
114
|
-
|
|
115
|
+
//#region src/core/postgres-contract-view.ts
|
|
116
|
+
const PostgresContractView = {
|
|
117
|
+
/** Wrap an already-deserialized Postgres contract in a schema-qualified view. */
|
|
118
|
+
from(contract) {
|
|
119
|
+
return buildSqlSchemaQualifiedView(contract);
|
|
120
|
+
},
|
|
121
|
+
/** Deserialize a Postgres contract JSON envelope and wrap it in a view. */
|
|
122
|
+
fromJson(json) {
|
|
123
|
+
return buildSqlSchemaQualifiedView(new PostgresContractSerializer().deserializeContract(json));
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
export { PostgresContractSerializer as n, PostgresContractView as t };
|
|
115
128
|
|
|
116
|
-
//# sourceMappingURL=postgres-contract-
|
|
129
|
+
//# sourceMappingURL=postgres-contract-view-D12LEXT5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-contract-view-D12LEXT5.mjs","names":[],"sources":["../src/core/postgres-contract-serializer.ts","../src/core/postgres-contract-view.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport {\n SqlContractSerializerBase,\n type SqlEntityHydrationFactory,\n} from '@prisma-next/family-sql/ir';\nimport {\n type AuthoringEntityContext,\n type AuthoringEntityTypeFactoryOutput,\n type AuthoringEntityTypeNamespace,\n isAuthoringEntityTypeDescriptor,\n} from '@prisma-next/framework-components/authoring';\nimport {\n type AnyEntityKindDescriptor,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport type { SqlNamespaceInput, SqlStorage } from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { JsonObject, JsonValue } from '@prisma-next/utils/json';\nimport { postgresAuthoringEntityTypes } from './authoring';\nimport { policyEntityKind, roleEntityKind } from './entity-kinds';\nimport { isPostgresSchema, PostgresSchema } from './postgres-schema';\n\nconst POSTGRES_AUTHORING_CTX: AuthoringEntityContext = {\n family: 'sql',\n target: 'postgres',\n};\n\nfunction isAuthoringEntityTypeFactoryOutput(\n output: unknown,\n): output is AuthoringEntityTypeFactoryOutput<unknown, unknown> {\n return (\n typeof output === 'object' &&\n output !== null &&\n 'factory' in output &&\n typeof output.factory === 'function'\n );\n}\n\n/**\n * Walks a pack's entity-type namespace tree and emits hydration factories\n * keyed by the descriptor's `discriminator`. Used for `storage.types`\n * (codec-triple hydration). Namespace entries hydration dispatches by\n * entries key, not discriminator — handled by `hydrateNamespaceEntities`.\n */\nfunction collectStorageTypesHydrators(\n namespace: AuthoringEntityTypeNamespace,\n): ReadonlyMap<string, SqlEntityHydrationFactory> {\n const registry = new Map<string, SqlEntityHydrationFactory>();\n const walk = (node: AuthoringEntityTypeNamespace): void => {\n for (const value of Object.values(node)) {\n if (isAuthoringEntityTypeDescriptor(value)) {\n if (isAuthoringEntityTypeFactoryOutput(value.output)) {\n const { factory } = value.output;\n registry.set(value.discriminator, (raw) => factory(raw, POSTGRES_AUTHORING_CTX));\n }\n continue;\n }\n if (typeof value === 'object' && value !== null) {\n walk(value);\n }\n }\n };\n walk(namespace);\n return registry;\n}\n\nexport class PostgresContractSerializer extends SqlContractSerializerBase<Contract<SqlStorage>> {\n constructor(extraPackEntityKinds: readonly AnyEntityKindDescriptor[] = []) {\n const storageTypesHydrators = collectStorageTypesHydrators(postgresAuthoringEntityTypes);\n super(storageTypesHydrators, [policyEntityKind, roleEntityKind, ...extraPackEntityKinds]);\n }\n\n protected override hydrateSqlNamespaceEntry(\n nsId: string,\n raw: Record<string, unknown>,\n ): Namespace | SqlNamespaceInput {\n const hydrated = blindCast<\n SqlNamespaceInput,\n 'raw is always plain JSON, so super.hydrateSqlNamespaceEntry returns SqlNamespaceInput'\n >(super.hydrateSqlNamespaceEntry(nsId, raw));\n const { id, entries } = hydrated;\n\n const allSlotsEmpty = Object.values(entries).every(\n (slot) => slot === undefined || Object.keys(slot).length === 0,\n );\n if (id === UNBOUND_NAMESPACE_ID && allSlotsEmpty) {\n return PostgresSchema.unbound;\n }\n const valueSetSlot = entries['valueSet'];\n const hasValueSets = valueSetSlot !== undefined && Object.keys(valueSetSlot).length > 0;\n return new PostgresSchema({\n id,\n entries: {\n ...entries,\n table: entries['table'] ?? {},\n ...(hasValueSets ? { valueSet: valueSetSlot } : {}),\n },\n });\n }\n\n override serializeContract(contract: Contract<SqlStorage>): JsonObject {\n const { storage, ...rest } = contract;\n const namespacesJson: Record<string, JsonObject> = {};\n for (const [nsId, ns] of Object.entries(storage.namespaces)) {\n if (isPostgresSchema(ns)) {\n namespacesJson[nsId] = this.serializePostgresNamespace(ns, ns.id === UNBOUND_NAMESPACE_ID);\n } else {\n const isUnboundSlot = nsId === UNBOUND_NAMESPACE_ID;\n namespacesJson[nsId] = {\n id: nsId,\n kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',\n entries: {\n table: Object.fromEntries(\n Object.entries(ns.entries.table ?? {}).map(([tableName, table]) => [\n tableName,\n this.serializeJsonObject(table),\n ]),\n ),\n },\n };\n }\n }\n const storageOut: Record<string, unknown> = {\n storageHash: String(storage.storageHash),\n namespaces: namespacesJson,\n };\n if (storage.types !== undefined) {\n const typesOut: Record<string, JsonObject> = {};\n for (const [name, entry] of Object.entries(storage.types)) {\n typesOut[name] = this.serializeJsonObject(entry);\n }\n storageOut['types'] = typesOut;\n }\n return blindCast<\n JsonObject,\n 'contract minus storage plus a JSON-shaped storageOut is a JsonObject'\n >({\n ...rest,\n storage: storageOut,\n });\n }\n\n private serializePostgresNamespace(ns: PostgresSchema, isUnboundSlot: boolean): JsonObject {\n const tablesOut: Record<string, JsonObject> = {};\n for (const [tableName, table] of Object.entries(ns.table)) {\n tablesOut[tableName] = this.serializeJsonObject(table);\n }\n const valueSetEntries = ns.valueSet;\n const valueSetOut: Record<string, JsonObject> = {};\n if (valueSetEntries !== undefined) {\n for (const [valueSetName, valueSet] of Object.entries(valueSetEntries)) {\n valueSetOut[valueSetName] = this.serializeJsonObject(valueSet);\n }\n }\n const roleOut: Record<string, JsonObject> = {};\n for (const [roleName, role] of Object.entries(ns.role)) {\n roleOut[roleName] = this.serializeJsonObject(role);\n }\n const policyOut: Record<string, JsonObject> = {};\n for (const [policyName, policy] of Object.entries(ns.policy)) {\n policyOut[policyName] = this.serializeJsonObject(policy);\n }\n return {\n id: ns.id,\n kind: isUnboundSlot ? 'postgres-unbound-schema' : 'postgres-schema',\n entries: {\n table: tablesOut,\n ...(Object.keys(valueSetOut).length > 0 ? { valueSet: valueSetOut } : {}),\n ...(Object.keys(roleOut).length > 0 ? { role: roleOut } : {}),\n ...(Object.keys(policyOut).length > 0 ? { policy: policyOut } : {}),\n },\n };\n }\n\n private serializeJsonObject(value: unknown): JsonObject {\n return blindCast<\n JsonObject,\n 'serializeJsonValue round-trips an IR node through JSON, yielding a JsonObject'\n >(this.serializeJsonValue(value));\n }\n\n private serializeJsonValue(value: unknown): JsonValue {\n return blindCast<JsonValue, 'JSON.parse(JSON.stringify(x)) yields a JsonValue'>(\n JSON.parse(JSON.stringify(value)),\n );\n }\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport {\n buildSqlSchemaQualifiedView,\n type SqlSchemaQualifiedView,\n} from '@prisma-next/sql-contract/contract-view';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport { PostgresContractSerializer } from './postgres-contract-serializer';\n\n/**\n * A schema-qualified Postgres contract view: the deserialized contract\n * intersected with a single `namespace` member holding every schema by id. It is\n * substitutable for `Contract` (carries `storage`, `domain`, …) and reaches each\n * schema's entities through `view.namespace.<schema>`:\n *\n * ```ts\n * const view = PostgresContractView.fromJson<Contract>(contractJson);\n * view.namespace.public.table.users // typed table leaf in the public schema\n * view.namespace.auth.table.users // the auth schema's own users table\n * view.namespace.public.entries.policy.X // pack-contributed kind (RLS / #771 path)\n * view.namespace.__unbound__.table.X // default schema, keyed by its raw id\n * view.storage // the full contract is still present\n * ```\n *\n * This mirrors the runtime `db.enums.<ns>` keying exactly (the default schema\n * keeps its literal `__unbound__` id). Schema names are NOT promoted to the\n * contract root, so there is no collision with contract envelope fields — a\n * schema named `storage` is `view.namespace.storage`, while `view.storage`\n * stays the contract's `storage`.\n */\nexport type PostgresContractView<TContract extends Contract<SqlStorage> = Contract<SqlStorage>> =\n SqlSchemaQualifiedView<TContract>;\n\nexport const PostgresContractView = {\n /** Wrap an already-deserialized Postgres contract in a schema-qualified view. */\n from<TContract extends Contract<SqlStorage>>(\n contract: TContract,\n ): PostgresContractView<TContract> {\n return buildSqlSchemaQualifiedView(contract);\n },\n\n /** Deserialize a Postgres contract JSON envelope and wrap it in a view. */\n fromJson<TContract extends Contract<SqlStorage> = Contract<SqlStorage>>(\n json: unknown,\n ): PostgresContractView<TContract> {\n const contract = new PostgresContractSerializer().deserializeContract<TContract>(json);\n return buildSqlSchemaQualifiedView(contract);\n },\n};\n"],"mappings":"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"}
|