@prisma-next/target-postgres 0.13.0-dev.3 → 0.13.0-dev.31
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/{codec-ids-CTikp1if.mjs → codec-ids-BvytN2P8.mjs} +3 -3
- package/dist/codec-ids-BvytN2P8.mjs.map +1 -0
- package/dist/{codec-ids-B1vOchLE.d.mts → codec-ids-CnXu9Qy3.d.mts} +3 -3
- package/dist/codec-ids-CnXu9Qy3.d.mts.map +1 -0
- package/dist/codec-ids.d.mts +2 -2
- package/dist/codec-ids.mjs +2 -2
- package/dist/{codec-types-CnFiNML4.d.mts → codec-types-DHCkwPKE.d.mts} +3 -3
- package/dist/{codec-types-CnFiNML4.d.mts.map → codec-types-DHCkwPKE.d.mts.map} +1 -1
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs-CBpEv4s5.d.mts → codecs--0A5_4Bq.d.mts} +26 -23
- package/dist/codecs--0A5_4Bq.d.mts.map +1 -0
- package/dist/codecs.d.mts +2 -2
- package/dist/codecs.mjs +28 -35
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.d.mts +17 -2
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +3 -3
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +21 -27
- package/dist/control.mjs.map +1 -1
- package/dist/{data-transform-D25tLeYU.mjs → data-transform-BOWpliq8.mjs} +9 -17
- package/dist/data-transform-BOWpliq8.mjs.map +1 -0
- package/dist/{data-transform-DGOqcLrf.d.mts → data-transform-DDgWdB5o.d.mts} +2 -2
- package/dist/data-transform-DDgWdB5o.d.mts.map +1 -0
- package/dist/data-transform.d.mts +1 -1
- package/dist/data-transform.mjs +1 -1
- package/dist/{ddl-77SyXgFt.mjs → ddl-DY2R_Yqz.mjs} +18 -3
- package/dist/ddl-DY2R_Yqz.mjs.map +1 -0
- package/dist/ddl.d.mts +2 -2
- package/dist/ddl.mjs +2 -2
- package/dist/{descriptor-meta-DKmj-IMN.mjs → descriptor-meta-BKma_hQ5.mjs} +2 -2
- package/dist/{descriptor-meta-DKmj-IMN.mjs.map → descriptor-meta-BKma_hQ5.mjs.map} +1 -1
- package/dist/descriptor-meta-runtime-e5f2tscJ.mjs +131 -0
- package/dist/descriptor-meta-runtime-e5f2tscJ.mjs.map +1 -0
- package/dist/{issue-planner-Br0pt1Ea.mjs → issue-planner-DsjB7xDj.mjs} +48 -252
- package/dist/issue-planner-DsjB7xDj.mjs.map +1 -0
- package/dist/issue-planner.d.mts +8 -11
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +4 -15
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +4 -4
- package/dist/{nodes-DZk2JZG3.mjs → nodes-Bbhs2rwj.mjs} +31 -2
- package/dist/nodes-Bbhs2rwj.mjs.map +1 -0
- package/dist/{nodes-779hmCfL.d.mts → nodes-pLeLgdis.d.mts} +30 -3
- package/dist/nodes-pLeLgdis.d.mts.map +1 -0
- package/dist/{op-factory-call-DMA86_2D.d.mts → op-factory-call-CdtMyrlU.d.mts} +12 -56
- package/dist/op-factory-call-CdtMyrlU.d.mts.map +1 -0
- package/dist/{op-factory-call-D2aAUhmS.mjs → op-factory-call-CjR846f7.mjs} +70 -198
- package/dist/op-factory-call-CjR846f7.mjs.map +1 -0
- package/dist/op-factory-call.d.mts +2 -2
- package/dist/op-factory-call.mjs +2 -2
- package/dist/pack.d.mts +36 -15
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-CAYPJObw.mjs → planner-_FOL4I21.mjs} +25 -45
- package/dist/planner-_FOL4I21.mjs.map +1 -0
- package/dist/{planner-ddl-builders-Cw2n2llW.mjs → planner-ddl-builders-B2wOwLqI.mjs} +2 -2
- package/dist/planner-ddl-builders-B2wOwLqI.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts +4 -4
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-ddl-builders.mjs +1 -1
- package/dist/{planner-identity-values-BIpa5p2I.mjs → planner-identity-values-CJPha2Sz.mjs} +3 -9
- package/dist/planner-identity-values-CJPha2Sz.mjs.map +1 -0
- package/dist/planner-identity-values.d.mts +1 -1
- package/dist/planner-identity-values.d.mts.map +1 -1
- package/dist/planner-identity-values.mjs +1 -1
- package/dist/{planner-produced-postgres-migration-NSEhWL0L.mjs → planner-produced-postgres-migration-BmCpyWLJ.mjs} +6 -4
- package/dist/planner-produced-postgres-migration-BmCpyWLJ.mjs.map +1 -0
- package/dist/{planner-produced-postgres-migration-B4EDvLdz.d.mts → planner-produced-postgres-migration-wLhnJMMA.d.mts} +5 -6
- package/dist/planner-produced-postgres-migration-wLhnJMMA.d.mts.map +1 -0
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-sql-checks-DAdhnI2c.mjs → planner-sql-checks-CJJtPfDH.mjs} +3 -3
- package/dist/planner-sql-checks-CJJtPfDH.mjs.map +1 -0
- package/dist/planner-sql-checks.d.mts +2 -2
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/{planner-type-resolution-836DExFN.mjs → planner-type-resolution-Bt2f_q-F.mjs} +1 -6
- package/dist/planner-type-resolution-Bt2f_q-F.mjs.map +1 -0
- package/dist/planner.d.mts +4 -4
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/{postgres-contract-serializer-DYTyXjPf.mjs → postgres-contract-serializer-CyAe8ZFv.mjs} +27 -37
- package/dist/postgres-contract-serializer-CyAe8ZFv.mjs.map +1 -0
- package/dist/{postgres-migration-DZ_gLUOW.d.mts → postgres-migration-DLXL0GBf.d.mts} +10 -5
- package/dist/postgres-migration-DLXL0GBf.d.mts.map +1 -0
- package/dist/{postgres-migration-COore9Mz.mjs → postgres-migration-dG-J0aI8.mjs} +7 -3
- package/dist/postgres-migration-dG-J0aI8.mjs.map +1 -0
- package/dist/{postgres-schema-BuxCxbvB.mjs → postgres-schema-CTKYiTHu.mjs} +30 -13
- package/dist/postgres-schema-CTKYiTHu.mjs.map +1 -0
- package/dist/{render-ops-BpjstrKQ.mjs → render-ops-BREh1kHe.mjs} +10 -5
- package/dist/render-ops-BREh1kHe.mjs.map +1 -0
- package/dist/render-ops.d.mts +2 -2
- package/dist/render-ops.d.mts.map +1 -1
- package/dist/render-ops.mjs +1 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/{shared-DarONYBZ.d.mts → shared-jcsbXxiW.d.mts} +2 -20
- package/dist/shared-jcsbXxiW.d.mts.map +1 -0
- package/dist/types.d.mts +8 -13
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -3
- package/package.json +17 -18
- package/src/contract-free/ddl.ts +28 -1
- package/src/core/authoring.ts +43 -44
- package/src/core/codec-helpers.ts +0 -17
- package/src/core/codec-ids.ts +1 -1
- package/src/core/codec-type-map.ts +2 -2
- package/src/core/codecs.ts +43 -48
- package/src/core/ddl/nodes.ts +59 -1
- package/src/core/migrations/control-policy.ts +17 -47
- package/src/core/migrations/issue-planner.ts +34 -70
- package/src/core/migrations/op-factory-call.ts +89 -142
- package/src/core/migrations/operations/data-transform.ts +15 -18
- package/src/core/migrations/planner-ddl-builders.ts +3 -4
- package/src/core/migrations/planner-identity-values.ts +4 -28
- package/src/core/migrations/planner-produced-postgres-migration.ts +15 -7
- package/src/core/migrations/planner-recipes.ts +2 -6
- package/src/core/migrations/planner-sql-checks.ts +2 -6
- package/src/core/migrations/planner-strategies.ts +51 -376
- package/src/core/migrations/planner-type-resolution.ts +2 -20
- package/src/core/migrations/planner.ts +6 -6
- package/src/core/migrations/postgres-migration.ts +19 -4
- package/src/core/migrations/render-ops.ts +26 -13
- package/src/core/migrations/runner.ts +26 -20
- package/src/core/postgres-contract-serializer.ts +32 -54
- package/src/core/postgres-enum-type-schema.ts +17 -0
- package/src/core/postgres-schema.ts +56 -34
- package/src/exports/codecs.ts +2 -2
- package/src/exports/contract-free.ts +1 -1
- package/src/exports/control.ts +0 -22
- package/src/exports/ddl.ts +4 -0
- package/src/exports/migration.ts +0 -7
- package/src/exports/op-factory-call.ts +0 -4
- package/src/exports/types.ts +0 -1
- package/dist/codec-ids-B1vOchLE.d.mts.map +0 -1
- package/dist/codec-ids-CTikp1if.mjs.map +0 -1
- package/dist/codecs-CBpEv4s5.d.mts.map +0 -1
- package/dist/data-transform-D25tLeYU.mjs.map +0 -1
- package/dist/data-transform-DGOqcLrf.d.mts.map +0 -1
- package/dist/ddl-77SyXgFt.mjs.map +0 -1
- package/dist/descriptor-meta-runtime-My8_s4cs.mjs +0 -130
- package/dist/descriptor-meta-runtime-My8_s4cs.mjs.map +0 -1
- package/dist/enum-planning-BCyvlFHk.mjs +0 -0
- package/dist/enum-planning-BCyvlFHk.mjs.map +0 -1
- package/dist/enum-planning.d.mts +0 -86
- package/dist/enum-planning.d.mts.map +0 -1
- package/dist/enum-planning.mjs +0 -2
- package/dist/issue-planner-Br0pt1Ea.mjs.map +0 -1
- package/dist/nodes-779hmCfL.d.mts.map +0 -1
- package/dist/nodes-DZk2JZG3.mjs.map +0 -1
- package/dist/op-factory-call-D2aAUhmS.mjs.map +0 -1
- package/dist/op-factory-call-DMA86_2D.d.mts.map +0 -1
- package/dist/planner-CAYPJObw.mjs.map +0 -1
- package/dist/planner-ddl-builders-Cw2n2llW.mjs.map +0 -1
- package/dist/planner-identity-values-BIpa5p2I.mjs.map +0 -1
- package/dist/planner-produced-postgres-migration-B4EDvLdz.d.mts.map +0 -1
- package/dist/planner-produced-postgres-migration-NSEhWL0L.mjs.map +0 -1
- package/dist/planner-sql-checks-DAdhnI2c.mjs.map +0 -1
- package/dist/planner-type-resolution-836DExFN.mjs.map +0 -1
- package/dist/postgres-contract-serializer-DYTyXjPf.mjs.map +0 -1
- package/dist/postgres-enum-type-BVn63a89.d.mts +0 -72
- package/dist/postgres-enum-type-BVn63a89.d.mts.map +0 -1
- package/dist/postgres-enum-type-DPKqCBem.mjs +0 -62
- package/dist/postgres-enum-type-DPKqCBem.mjs.map +0 -1
- package/dist/postgres-migration-COore9Mz.mjs.map +0 -1
- package/dist/postgres-migration-DZ_gLUOW.d.mts.map +0 -1
- package/dist/postgres-schema-BuxCxbvB.mjs.map +0 -1
- package/dist/render-ops-BpjstrKQ.mjs.map +0 -1
- package/dist/shared-DarONYBZ.d.mts.map +0 -1
- package/src/core/migrations/enum-planning.ts +0 -213
- package/src/core/migrations/operations/enums.ts +0 -114
- package/src/core/postgres-enum-type.ts +0 -89
- package/src/exports/enum-planning.ts +0 -11
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure planning helpers for Postgres enum types: the diff/rebuild logic
|
|
3
|
-
* that the verifier and planner use to walk `PostgresEnumType` instances
|
|
4
|
-
* natively. Op builders live in `./operations/enums.ts`.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { arraysEqual } from '@prisma-next/family-sql/schema-verify';
|
|
8
|
-
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
9
|
-
import type { PostgresEnumStorageEntry, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
10
|
-
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
11
|
-
import { PG_ENUM_CODEC_ID } from '../codec-ids';
|
|
12
|
-
import type { PostgresEnumType } from '../postgres-enum-type';
|
|
13
|
-
import { isPostgresSchema } from '../postgres-schema';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Codec-typed enum entry shape stored under
|
|
17
|
-
* `schema.annotations.pg.storageTypes[(schemaName, nativeType)]`.
|
|
18
|
-
*/
|
|
19
|
-
interface PgStorageTypeEntry {
|
|
20
|
-
readonly codecId?: string;
|
|
21
|
-
readonly typeParams?: { readonly values?: unknown };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Postgres-specific subtree on family `SqlSchemaIR.annotations`. */
|
|
25
|
-
export interface PostgresSchemaIrAnnotations {
|
|
26
|
-
readonly schema?: string;
|
|
27
|
-
readonly storageTypes?: Readonly<Record<string, PgStorageTypeEntry>>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function readOptionalString(value: unknown): string | undefined {
|
|
31
|
-
return typeof value === 'string' ? value : undefined;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function readPgStorageTypeEntry(value: unknown): PgStorageTypeEntry | undefined {
|
|
35
|
-
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
const codecId = Reflect.get(value, 'codecId');
|
|
39
|
-
const typeParamsRaw = Reflect.get(value, 'typeParams');
|
|
40
|
-
const typeParams =
|
|
41
|
-
typeParamsRaw !== undefined &&
|
|
42
|
-
typeParamsRaw !== null &&
|
|
43
|
-
typeof typeParamsRaw === 'object' &&
|
|
44
|
-
!Array.isArray(typeParamsRaw)
|
|
45
|
-
? { values: Reflect.get(typeParamsRaw, 'values') }
|
|
46
|
-
: undefined;
|
|
47
|
-
return {
|
|
48
|
-
...(typeof codecId === 'string' ? { codecId } : {}),
|
|
49
|
-
...(typeParams !== undefined ? { typeParams } : {}),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function readPgStorageTypesMap(
|
|
54
|
-
value: unknown,
|
|
55
|
-
): Readonly<Record<string, PgStorageTypeEntry>> | undefined {
|
|
56
|
-
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
const entries: Record<string, PgStorageTypeEntry> = {};
|
|
60
|
-
for (const [key, entryValue] of Object.entries(value)) {
|
|
61
|
-
const entry = readPgStorageTypeEntry(entryValue);
|
|
62
|
-
if (entry !== undefined) {
|
|
63
|
-
entries[key] = entry;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return Object.keys(entries).length > 0 ? entries : undefined;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Reads the Postgres annotation envelope (`schema.annotations.pg`) from
|
|
71
|
-
* family Schema IR. `SqlAnnotations` is an open target-pack extensibility
|
|
72
|
-
* map (`Record<string, unknown>`); this accessor narrows the `pg` slot at
|
|
73
|
-
* runtime so Postgres code can read introspection fields without casts.
|
|
74
|
-
*/
|
|
75
|
-
export function readPostgresSchemaIrAnnotations(schema: SqlSchemaIR): PostgresSchemaIrAnnotations {
|
|
76
|
-
const raw = schema.annotations?.['pg'];
|
|
77
|
-
if (raw === undefined || raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
78
|
-
return {};
|
|
79
|
-
}
|
|
80
|
-
const schemaField = readOptionalString(Reflect.get(raw, 'schema'));
|
|
81
|
-
const storageTypes = readPgStorageTypesMap(Reflect.get(raw, 'storageTypes'));
|
|
82
|
-
return {
|
|
83
|
-
...(schemaField !== undefined ? { schema: schemaField } : {}),
|
|
84
|
-
...(storageTypes !== undefined ? { storageTypes } : {}),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Separator for `(schemaName, nativeType)` keys in introspected
|
|
90
|
-
* `schema.annotations.pg.storageTypes`. NUL cannot appear in Postgres
|
|
91
|
-
* identifiers, so the pair is unambiguous.
|
|
92
|
-
*/
|
|
93
|
-
export const ENUM_STORAGE_KEY_SEP = '\u0000';
|
|
94
|
-
|
|
95
|
-
/** Builds the schema-qualified storageTypes map key for a live Postgres enum. */
|
|
96
|
-
export function enumStorageCompoundKey(schemaName: string, nativeType: string): string {
|
|
97
|
-
return `${schemaName}${ENUM_STORAGE_KEY_SEP}${nativeType}`;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Resolves the live-schema name a namespace's enums are introspected under,
|
|
102
|
-
* for keying `readExistingEnumValues` lookups. The unbound namespace's
|
|
103
|
-
* `ddlSchemaName` is a planner-emit sentinel (`__unbound__`) that never names a
|
|
104
|
-
* real schema, so for the unbound coordinate we read the *introspected* schema
|
|
105
|
-
* recorded on `annotations.pg.schema` (the live `current_schema()` the adapter
|
|
106
|
-
* walked) — that is the schema the enum's `storageTypes` entry is keyed under.
|
|
107
|
-
* Named namespaces resolve to their own DDL schema, which matches the
|
|
108
|
-
* per-schema introspection key directly.
|
|
109
|
-
*/
|
|
110
|
-
export function resolveDdlSchemaForNamespaceStorage(
|
|
111
|
-
storage: SqlStorage,
|
|
112
|
-
namespaceId: string,
|
|
113
|
-
schemaIr?: SqlSchemaIR,
|
|
114
|
-
): string {
|
|
115
|
-
if (namespaceId === UNBOUND_NAMESPACE_ID) {
|
|
116
|
-
return (schemaIr ? readPostgresSchemaIrAnnotations(schemaIr).schema : undefined) ?? 'public';
|
|
117
|
-
}
|
|
118
|
-
const namespace = storage.namespaces[namespaceId];
|
|
119
|
-
if (namespace && isPostgresSchema(namespace)) {
|
|
120
|
-
return namespace.ddlSchemaName(storage);
|
|
121
|
-
}
|
|
122
|
-
return namespaceId;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** Contract-scoped bridge for the family verifier's enum value resolver. */
|
|
126
|
-
export function createResolveExistingEnumValues(
|
|
127
|
-
storage: SqlStorage,
|
|
128
|
-
): (
|
|
129
|
-
schema: SqlSchemaIR,
|
|
130
|
-
enumType: PostgresEnumStorageEntry,
|
|
131
|
-
namespaceId: string,
|
|
132
|
-
) => readonly string[] | null {
|
|
133
|
-
return (schema, enumType, namespaceId) =>
|
|
134
|
-
readExistingEnumValues(
|
|
135
|
-
schema,
|
|
136
|
-
resolveDdlSchemaForNamespaceStorage(storage, namespaceId, schema),
|
|
137
|
-
enumType.nativeType,
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Categorisation of how an existing enum type's values relate to the
|
|
143
|
-
* desired set in the contract.
|
|
144
|
-
*/
|
|
145
|
-
export type EnumDiff =
|
|
146
|
-
| { readonly kind: 'unchanged' }
|
|
147
|
-
| { readonly kind: 'add_values'; readonly values: readonly string[] }
|
|
148
|
-
| { readonly kind: 'rebuild'; readonly removedValues: readonly string[] };
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Reads existing enum values for `(schemaName, nativeType)` from the
|
|
152
|
-
* Postgres-introspected `schema.annotations.pg.storageTypes` map.
|
|
153
|
-
*
|
|
154
|
-
* Schema IR's `storageTypes` slots are always codec-typed
|
|
155
|
-
* (`{codecId: PG_ENUM_CODEC_ID, typeParams.values}`): the introspector
|
|
156
|
-
* writes that shape, and the Contract→Schema IR projector resolves
|
|
157
|
-
* `PostgresEnumType` instances down to the same codec-typed triple before
|
|
158
|
-
* they ever land in Schema IR. There is no second on-disk shape to
|
|
159
|
-
* accept here.
|
|
160
|
-
*
|
|
161
|
-
* Returns `null` when no enum entry exists for the given native type.
|
|
162
|
-
*/
|
|
163
|
-
export function readExistingEnumValues(
|
|
164
|
-
schema: SqlSchemaIR,
|
|
165
|
-
schemaName: string,
|
|
166
|
-
nativeType: string,
|
|
167
|
-
): readonly string[] | null {
|
|
168
|
-
const storageTypes = readPostgresSchemaIrAnnotations(schema).storageTypes;
|
|
169
|
-
const existing = storageTypes?.[enumStorageCompoundKey(schemaName, nativeType)];
|
|
170
|
-
if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
const enumValues = existing.typeParams?.values;
|
|
174
|
-
if (!Array.isArray(enumValues) || !enumValues.every((v) => typeof v === 'string')) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
return enumValues;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Determines what changes are needed to transform existing enum values to
|
|
182
|
-
* desired values.
|
|
183
|
-
*
|
|
184
|
-
* Postgres enums can only have values added (not removed or reordered)
|
|
185
|
-
* without a full type rebuild involving temp type creation and column
|
|
186
|
-
* migration; `'rebuild'` covers the value-removal and reorder cases.
|
|
187
|
-
*/
|
|
188
|
-
export function determineEnumDiff(
|
|
189
|
-
existing: readonly string[],
|
|
190
|
-
desired: readonly string[],
|
|
191
|
-
): EnumDiff {
|
|
192
|
-
if (arraysEqual(existing, desired)) {
|
|
193
|
-
return { kind: 'unchanged' };
|
|
194
|
-
}
|
|
195
|
-
const existingSet = new Set(existing);
|
|
196
|
-
const desiredSet = new Set(desired);
|
|
197
|
-
const missingValues = desired.filter((value) => !existingSet.has(value));
|
|
198
|
-
const removedValues = existing.filter((value) => !desiredSet.has(value));
|
|
199
|
-
const orderMismatch =
|
|
200
|
-
missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);
|
|
201
|
-
if (removedValues.length > 0 || orderMismatch) {
|
|
202
|
-
return { kind: 'rebuild', removedValues };
|
|
203
|
-
}
|
|
204
|
-
return { kind: 'add_values', values: missingValues };
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Convenience accessor — returns the enum's desired values from a
|
|
209
|
-
* `PostgresEnumType` IR instance.
|
|
210
|
-
*/
|
|
211
|
-
export function getDesiredEnumValues(typeInstance: PostgresEnumType): readonly string[] {
|
|
212
|
-
return typeInstance.values;
|
|
213
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { escapeLiteral, qualifyName, quoteIdentifier } from '../../sql-utils';
|
|
2
|
-
import { type Op, step, targetDetails } from './shared';
|
|
3
|
-
|
|
4
|
-
function enumTypeExistsCheck(schemaName: string, nativeType: string, exists = true): string {
|
|
5
|
-
const clause = exists ? 'EXISTS' : 'NOT EXISTS';
|
|
6
|
-
return `SELECT ${clause} (
|
|
7
|
-
SELECT 1
|
|
8
|
-
FROM pg_type t
|
|
9
|
-
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
10
|
-
WHERE n.nspname = '${escapeLiteral(schemaName)}'
|
|
11
|
-
AND t.typname = '${escapeLiteral(nativeType)}'
|
|
12
|
-
)`;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createEnumType(
|
|
16
|
-
schemaName: string,
|
|
17
|
-
typeName: string,
|
|
18
|
-
values: readonly string[],
|
|
19
|
-
nativeType: string = typeName,
|
|
20
|
-
): Op {
|
|
21
|
-
const qualifiedType = qualifyName(schemaName, nativeType);
|
|
22
|
-
const literalValues = values.map((v) => `'${escapeLiteral(v)}'`).join(', ');
|
|
23
|
-
return {
|
|
24
|
-
id: `type.${typeName}`,
|
|
25
|
-
label: `Create enum type "${typeName}"`,
|
|
26
|
-
operationClass: 'additive',
|
|
27
|
-
target: targetDetails('type', typeName, schemaName),
|
|
28
|
-
precheck: [
|
|
29
|
-
step(
|
|
30
|
-
`ensure type "${nativeType}" does not exist`,
|
|
31
|
-
enumTypeExistsCheck(schemaName, nativeType, false),
|
|
32
|
-
),
|
|
33
|
-
],
|
|
34
|
-
execute: [
|
|
35
|
-
step(
|
|
36
|
-
`create enum type "${typeName}"`,
|
|
37
|
-
`CREATE TYPE ${qualifiedType} AS ENUM (${literalValues})`,
|
|
38
|
-
),
|
|
39
|
-
],
|
|
40
|
-
postcheck: [
|
|
41
|
-
step(`verify type "${nativeType}" exists`, enumTypeExistsCheck(schemaName, nativeType)),
|
|
42
|
-
],
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* `typeName` is the contract-facing type name (used for id/label).
|
|
48
|
-
* `nativeType` is the Postgres type name to mutate (may differ for external types).
|
|
49
|
-
*/
|
|
50
|
-
export function addEnumValues(
|
|
51
|
-
schemaName: string,
|
|
52
|
-
typeName: string,
|
|
53
|
-
nativeType: string,
|
|
54
|
-
values: readonly string[],
|
|
55
|
-
): Op {
|
|
56
|
-
const qualifiedType = qualifyName(schemaName, nativeType);
|
|
57
|
-
return {
|
|
58
|
-
id: `type.${typeName}.addValues`,
|
|
59
|
-
label: `Add values to enum type "${typeName}": ${values.join(', ')}`,
|
|
60
|
-
operationClass: 'additive',
|
|
61
|
-
target: targetDetails('type', typeName, schemaName),
|
|
62
|
-
precheck: [
|
|
63
|
-
step(`ensure type "${nativeType}" exists`, enumTypeExistsCheck(schemaName, nativeType)),
|
|
64
|
-
],
|
|
65
|
-
execute: values.map((value) =>
|
|
66
|
-
step(
|
|
67
|
-
`add value '${value}' to enum "${nativeType}"`,
|
|
68
|
-
`ALTER TYPE ${qualifiedType} ADD VALUE '${escapeLiteral(value)}'`,
|
|
69
|
-
),
|
|
70
|
-
),
|
|
71
|
-
postcheck: [
|
|
72
|
-
step(`verify type "${nativeType}" exists`, enumTypeExistsCheck(schemaName, nativeType)),
|
|
73
|
-
],
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function dropEnumType(schemaName: string, typeName: string): Op {
|
|
78
|
-
const qualified = qualifyName(schemaName, typeName);
|
|
79
|
-
return {
|
|
80
|
-
id: `type.${typeName}.drop`,
|
|
81
|
-
label: `Drop enum type "${typeName}"`,
|
|
82
|
-
operationClass: 'destructive',
|
|
83
|
-
target: targetDetails('type', typeName, schemaName),
|
|
84
|
-
precheck: [step(`ensure type "${typeName}" exists`, enumTypeExistsCheck(schemaName, typeName))],
|
|
85
|
-
execute: [step(`drop enum type "${typeName}"`, `DROP TYPE ${qualified}`)],
|
|
86
|
-
postcheck: [
|
|
87
|
-
step(`verify type "${typeName}" removed`, enumTypeExistsCheck(schemaName, typeName, false)),
|
|
88
|
-
],
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function renameType(schemaName: string, fromName: string, toName: string): Op {
|
|
93
|
-
const qualifiedFrom = qualifyName(schemaName, fromName);
|
|
94
|
-
return {
|
|
95
|
-
id: `type.${fromName}.rename`,
|
|
96
|
-
label: `Rename type "${fromName}" to "${toName}"`,
|
|
97
|
-
operationClass: 'destructive',
|
|
98
|
-
target: targetDetails('type', fromName, schemaName),
|
|
99
|
-
precheck: [
|
|
100
|
-
step(`ensure type "${fromName}" exists`, enumTypeExistsCheck(schemaName, fromName)),
|
|
101
|
-
step(
|
|
102
|
-
`ensure type "${toName}" does not already exist`,
|
|
103
|
-
enumTypeExistsCheck(schemaName, toName, false),
|
|
104
|
-
),
|
|
105
|
-
],
|
|
106
|
-
execute: [
|
|
107
|
-
step(
|
|
108
|
-
`rename type "${fromName}" to "${toName}"`,
|
|
109
|
-
`ALTER TYPE ${qualifiedFrom} RENAME TO ${quoteIdentifier(toName)}`,
|
|
110
|
-
),
|
|
111
|
-
],
|
|
112
|
-
postcheck: [step(`verify type "${toName}" exists`, enumTypeExistsCheck(schemaName, toName))],
|
|
113
|
-
};
|
|
114
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { ControlPolicy } from '@prisma-next/contract/types';
|
|
2
|
-
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
3
|
-
import { SqlNode } from '@prisma-next/sql-contract/types';
|
|
4
|
-
|
|
5
|
-
export interface PostgresEnumTypeInput<
|
|
6
|
-
TName extends string = string,
|
|
7
|
-
TValues extends readonly string[] = readonly string[],
|
|
8
|
-
> {
|
|
9
|
-
/**
|
|
10
|
-
* Contract-level enum name (e.g. `'Role'`). Used as the key in
|
|
11
|
-
* `SqlStorage.types` and as the contract-facing identifier in
|
|
12
|
-
* planner / verifier diagnostics.
|
|
13
|
-
*/
|
|
14
|
-
readonly name: TName;
|
|
15
|
-
/**
|
|
16
|
-
* Postgres-side native type name created by `CREATE TYPE … AS ENUM`.
|
|
17
|
-
* Defaults to `name` when not overridden via PSL `@map(...)` or the
|
|
18
|
-
* TS authoring surface.
|
|
19
|
-
*/
|
|
20
|
-
readonly nativeType?: string;
|
|
21
|
-
readonly values: TValues;
|
|
22
|
-
readonly control?: ControlPolicy;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Codec id used by Postgres enum-typed columns (text wire format). */
|
|
26
|
-
const PG_ENUM_CODEC_ID = 'pg/enum@1';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Postgres IR class for the `CREATE TYPE … AS ENUM` concept.
|
|
30
|
-
*
|
|
31
|
-
* Per Decision 18, enum is a target-only concept (Postgres alone today;
|
|
32
|
-
* SQLite emulates via CHECK constraints). There is no family-layer
|
|
33
|
-
* enum abstract — the abstract-earns-existence rule keeps the IR class
|
|
34
|
-
* hierarchy minimal: this class extends `SqlNode` directly and is the
|
|
35
|
-
* single concrete representation of the polymorphic `'postgres-enum'`
|
|
36
|
-
* slot variant.
|
|
37
|
-
*
|
|
38
|
-
* Carries Postgres-specific resolution (`nativeType` defaults to
|
|
39
|
-
* `name`; `values` is frozen at construction time). Constructor calls
|
|
40
|
-
* `freezeNode(this)` per Decision 8 — the instance is fully immutable,
|
|
41
|
-
* JSON-clean, and dispatchable on its enumerable `kind: 'postgres-enum'`
|
|
42
|
-
* literal.
|
|
43
|
-
*
|
|
44
|
-
* The family-layer slot dispatch (verifier, planner, lowering, etc.)
|
|
45
|
-
* narrows polymorphic `StorageType` entries via the `kind` literal
|
|
46
|
-
* (e.g. `isPostgresEnumStorageEntry`) — SQL-domain code must not import
|
|
47
|
-
* `target-postgres` directly (cross-domain layering rule). The
|
|
48
|
-
* structural interface lives at the family layer for that purpose;
|
|
49
|
-
* this class is the runtime concrete that satisfies it.
|
|
50
|
-
*/
|
|
51
|
-
export class PostgresEnumType<
|
|
52
|
-
TName extends string = string,
|
|
53
|
-
TValues extends readonly string[] = readonly string[],
|
|
54
|
-
> extends SqlNode {
|
|
55
|
-
override readonly kind = 'postgres-enum' as const;
|
|
56
|
-
readonly name: TName;
|
|
57
|
-
readonly nativeType: string;
|
|
58
|
-
readonly values: TValues;
|
|
59
|
-
/**
|
|
60
|
-
* Enumerable own property so the persisted JSON envelope carries
|
|
61
|
-
* `codecId: 'pg/enum@1'` alongside `kind: 'postgres-enum'`. The
|
|
62
|
-
* runtime path (`codecRefForStorageColumn`, `assertColumnCodecIntegrity`)
|
|
63
|
-
* receives JSON-shaped contracts (e.g. inside a user-written
|
|
64
|
-
* `migration.ts` that loads `endContract` from `end-contract.json`)
|
|
65
|
-
* and reads `codecId` directly from the envelope rather than
|
|
66
|
-
* dispatching through the prototype-only `codecBinding` accessor.
|
|
67
|
-
*/
|
|
68
|
-
readonly codecId: typeof PG_ENUM_CODEC_ID = PG_ENUM_CODEC_ID;
|
|
69
|
-
declare readonly control?: ControlPolicy;
|
|
70
|
-
|
|
71
|
-
constructor(input: PostgresEnumTypeInput<TName, TValues>) {
|
|
72
|
-
super();
|
|
73
|
-
this.name = input.name;
|
|
74
|
-
this.nativeType = input.nativeType ?? input.name;
|
|
75
|
-
// `Object.freeze` returns `Readonly<string[]>`, widening past the
|
|
76
|
-
// `TValues` literal tuple. Cast preserves the caller-supplied
|
|
77
|
-
// tuple shape so inferred contract types retain literal narrowing.
|
|
78
|
-
this.values = Object.freeze([...input.values] as unknown as TValues);
|
|
79
|
-
if (input.control !== undefined) this.control = input.control;
|
|
80
|
-
freezeNode(this);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get codecBinding(): {
|
|
84
|
-
readonly codecId: typeof PG_ENUM_CODEC_ID;
|
|
85
|
-
readonly typeParams: { readonly values: TValues };
|
|
86
|
-
} {
|
|
87
|
-
return { codecId: PG_ENUM_CODEC_ID, typeParams: { values: this.values } };
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
createResolveExistingEnumValues,
|
|
3
|
-
determineEnumDiff,
|
|
4
|
-
type EnumDiff,
|
|
5
|
-
enumStorageCompoundKey,
|
|
6
|
-
getDesiredEnumValues,
|
|
7
|
-
type PostgresSchemaIrAnnotations,
|
|
8
|
-
readExistingEnumValues,
|
|
9
|
-
readPostgresSchemaIrAnnotations,
|
|
10
|
-
resolveDdlSchemaForNamespaceStorage,
|
|
11
|
-
} from '../core/migrations/enum-planning';
|