@prisma-next/target-postgres 0.13.0-dev.28 → 0.13.0-dev.29
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-C_-Hj6bL.mjs → codec-ids-BvytN2P8.mjs} +2 -3
- package/dist/codec-ids-BvytN2P8.mjs.map +1 -0
- package/dist/{codec-ids-BzrFF-I4.d.mts → codec-ids-CnXu9Qy3.d.mts} +2 -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-B0WT0obB.d.mts → codec-types-DHCkwPKE.d.mts} +2 -3
- package/dist/codec-types-DHCkwPKE.d.mts.map +1 -0
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs-CX56Smsj.d.mts → codecs--0A5_4Bq.d.mts} +3 -23
- package/dist/codecs--0A5_4Bq.d.mts.map +1 -0
- package/dist/codecs.d.mts +2 -2
- package/dist/codecs.mjs +2 -38
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.mjs +1 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +7 -10
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-C7O6XHfh.mjs → descriptor-meta-BKma_hQ5.mjs} +2 -2
- package/dist/{descriptor-meta-C7O6XHfh.mjs.map → descriptor-meta-BKma_hQ5.mjs.map} +1 -1
- package/dist/{descriptor-meta-runtime-BToWdas9.mjs → descriptor-meta-runtime-e5f2tscJ.mjs} +2 -39
- package/dist/descriptor-meta-runtime-e5f2tscJ.mjs.map +1 -0
- package/dist/{issue-planner-CK-XWGB0.mjs → issue-planner-DsjB7xDj.mjs} +17 -227
- 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 +1 -11
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +3 -3
- package/dist/{op-factory-call-DxjpXw-A.d.mts → op-factory-call-CdtMyrlU.d.mts} +3 -48
- package/dist/{op-factory-call-DxjpXw-A.d.mts.map → op-factory-call-CdtMyrlU.d.mts.map} +1 -1
- package/dist/{op-factory-call-CHvtj70z.mjs → op-factory-call-CjR846f7.mjs} +4 -159
- 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 +2 -18
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-4FbY_95H.mjs → planner-_FOL4I21.mjs} +9 -41
- 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-qfkCkGVe.mjs → planner-produced-postgres-migration-BmCpyWLJ.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-qfkCkGVe.mjs.map → planner-produced-postgres-migration-BmCpyWLJ.mjs.map} +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-sql-checks-BLgdXLsA.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.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/{postgres-contract-serializer-CTxVcCVW.mjs → postgres-contract-serializer-CyAe8ZFv.mjs} +12 -29
- package/dist/postgres-contract-serializer-CyAe8ZFv.mjs.map +1 -0
- package/dist/{postgres-migration-DF5ApLqQ.mjs → postgres-migration-dG-J0aI8.mjs} +2 -2
- package/dist/{postgres-migration-DF5ApLqQ.mjs.map → postgres-migration-dG-J0aI8.mjs.map} +1 -1
- package/dist/{postgres-schema-C7c9rhGk.mjs → postgres-schema-CTKYiTHu.mjs} +7 -21
- package/dist/postgres-schema-CTKYiTHu.mjs.map +1 -0
- package/dist/runtime.d.mts +0 -2
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/types.d.mts +5 -25
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -4
- package/package.json +17 -18
- package/src/core/authoring.ts +1 -44
- package/src/core/codec-helpers.ts +0 -17
- package/src/core/codec-ids.ts +0 -1
- package/src/core/codec-type-map.ts +0 -2
- package/src/core/codecs.ts +0 -49
- package/src/core/migrations/control-policy.ts +3 -45
- package/src/core/migrations/issue-planner.ts +9 -52
- package/src/core/migrations/op-factory-call.ts +2 -124
- 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-recipes.ts +2 -6
- package/src/core/migrations/planner-sql-checks.ts +2 -6
- package/src/core/migrations/planner-strategies.ts +13 -353
- package/src/core/migrations/planner-type-resolution.ts +2 -20
- package/src/core/migrations/planner.ts +0 -2
- package/src/core/migrations/runner.ts +0 -4
- package/src/core/postgres-contract-serializer.ts +9 -67
- package/src/core/postgres-schema.ts +6 -37
- package/src/exports/codecs.ts +0 -2
- package/src/exports/control.ts +0 -15
- package/src/exports/migration.ts +0 -6
- package/src/exports/op-factory-call.ts +0 -4
- package/src/exports/types.ts +0 -2
- package/dist/codec-ids-BzrFF-I4.d.mts.map +0 -1
- package/dist/codec-ids-C_-Hj6bL.mjs.map +0 -1
- package/dist/codec-types-B0WT0obB.d.mts.map +0 -1
- package/dist/codecs-CX56Smsj.d.mts.map +0 -1
- package/dist/descriptor-meta-runtime-BToWdas9.mjs.map +0 -1
- package/dist/enum-planning-D8z4FH7y.mjs +0 -129
- package/dist/enum-planning-D8z4FH7y.mjs.map +0 -1
- package/dist/enum-planning.d.mts +0 -92
- package/dist/enum-planning.d.mts.map +0 -1
- package/dist/enum-planning.mjs +0 -2
- package/dist/issue-planner-CK-XWGB0.mjs.map +0 -1
- package/dist/op-factory-call-CHvtj70z.mjs.map +0 -1
- package/dist/planner-4FbY_95H.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-sql-checks-BLgdXLsA.mjs.map +0 -1
- package/dist/planner-type-resolution-836DExFN.mjs.map +0 -1
- package/dist/postgres-contract-serializer-CTxVcCVW.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-enum-type-schema-DZBTtvBF.mjs +0 -20
- package/dist/postgres-enum-type-schema-DZBTtvBF.mjs.map +0 -1
- package/dist/postgres-schema-C7c9rhGk.mjs.map +0 -1
- package/src/core/migrations/enum-planning.ts +0 -217
- 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 -10
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type } from "arktype";
|
|
2
|
-
//#region src/core/postgres-enum-type-schema.ts
|
|
3
|
-
const ControlPolicySchema = type("'managed' | 'tolerated' | 'external' | 'observed'");
|
|
4
|
-
/**
|
|
5
|
-
* Arktype validator for a `postgres-enum` entry under
|
|
6
|
-
* `storage.namespaces[id].entries.type[name]`. Registered by the Postgres
|
|
7
|
-
* target pack against the `'type'` entries key so the family-layer namespace
|
|
8
|
-
* validator accepts (and rejects) entries of this kind.
|
|
9
|
-
*/
|
|
10
|
-
const PostgresEnumTypeSchema = type({
|
|
11
|
-
kind: "'postgres-enum'",
|
|
12
|
-
"name?": "string",
|
|
13
|
-
"nativeType?": "string",
|
|
14
|
-
values: type.string.array().readonly(),
|
|
15
|
-
"control?": ControlPolicySchema
|
|
16
|
-
});
|
|
17
|
-
//#endregion
|
|
18
|
-
export { PostgresEnumTypeSchema as t };
|
|
19
|
-
|
|
20
|
-
//# sourceMappingURL=postgres-enum-type-schema-DZBTtvBF.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-enum-type-schema-DZBTtvBF.mjs","names":[],"sources":["../src/core/postgres-enum-type-schema.ts"],"sourcesContent":["import { type } from 'arktype';\n\nconst ControlPolicySchema = type(\"'managed' | 'tolerated' | 'external' | 'observed'\");\n\n/**\n * Arktype validator for a `postgres-enum` entry under\n * `storage.namespaces[id].entries.type[name]`. Registered by the Postgres\n * target pack against the `'type'` entries key so the family-layer namespace\n * validator accepts (and rejects) entries of this kind.\n */\nexport const PostgresEnumTypeSchema = type({\n kind: \"'postgres-enum'\",\n 'name?': 'string',\n 'nativeType?': 'string',\n values: type.string.array().readonly(),\n 'control?': ControlPolicySchema,\n});\n"],"mappings":";;AAEA,MAAM,sBAAsB,KAAK,mDAAmD;;;;;;;AAQpF,MAAa,yBAAyB,KAAK;CACzC,MAAM;CACN,SAAS;CACT,eAAe;CACf,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS;CACrC,YAAY;AACd,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-schema-C7c9rhGk.mjs","names":[],"sources":["../src/core/postgres-schema.ts"],"sourcesContent":["import {\n freezeNode,\n NamespaceBase,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport {\n type PostgresEnumStorageEntry,\n type SqlNamespaceEntries,\n type SqlNamespaceTablesInput,\n type SqlStorage,\n StorageTable,\n type StorageTableInput,\n StorageValueSet,\n type StorageValueSetInput,\n} from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { PostgresEnumType, type PostgresEnumTypeInput } from './postgres-enum-type';\nimport { escapeLiteral } from './sql-utils';\n\nexport type PostgresNamespaceEntries = SqlNamespaceEntries & {\n readonly type?: Readonly<Record<string, PostgresEnumType>>;\n};\n\nexport interface PostgresSchemaInput {\n readonly id: string;\n readonly entries: Readonly<Record<string, Readonly<Record<string, unknown>>>>;\n}\n\n/**\n * Postgres target `Namespace` concretion — a Postgres schema (`CREATE\n * SCHEMA …`). Each Postgres `SqlStorage` carries a\n * `namespaces: Record<NamespaceId, PostgresSchema>` map populated by\n * the Postgres PSL interpreter from `namespace { … }` AST buckets.\n *\n * `entries` holds entity-kind maps (`table`, `type`). Qualifier\n * emission is the rendering seam: DDL / SQL emission asks the namespace\n * for its qualifier (`\"<schema>\"`) or for a qualified table name\n * (`\"<schema>\".\"<table>\"`) and consumes the result polymorphically.\n * The unbound singleton below overrides these methods to elide the\n * prefix entirely — call sites stay polymorphic and never branch on\n * `id === UNBOUND_NAMESPACE_ID`.\n */\nexport class PostgresSchema extends NamespaceBase {\n /**\n * Stable singleton reference for the late-bound slot. Materialised\n * lazily below the singleton subclass declaration so the static\n * initialiser sees the subclass before assigning. Consumers always\n * reach for `PostgresSchema.unbound` (or `PostgresUnboundSchema.instance`\n * — same identity).\n */\n static unbound: PostgresUnboundSchema;\n\n declare readonly kind: 'schema';\n readonly id: string;\n readonly entries: PostgresNamespaceEntries;\n\n constructor(input: PostgresSchemaInput) {\n super();\n this.id = input.id;\n\n const carried: Record<string, Readonly<Record<string, unknown>>> = {};\n let table: Readonly<Record<string, StorageTable>> = Object.freeze({});\n let type: Readonly<Record<string, PostgresEnumType>> = Object.freeze({});\n let valueSet: Readonly<Record<string, StorageValueSet>> | undefined;\n for (const [kind, rawMap] of Object.entries(input.entries)) {\n if (kind === 'table') {\n const tableMap: Record<string, StorageTable> = {};\n for (const [name, v] of Object.entries(\n blindCast<\n Record<string, StorageTableInput>,\n 'entries[table] holds StorageTableInput by construction'\n >(rawMap),\n )) {\n tableMap[name] = new StorageTable(v);\n }\n table = Object.freeze(tableMap);\n } else if (kind === 'type') {\n const typeMap: Record<string, PostgresEnumType> = {};\n for (const [name, v] of Object.entries(\n blindCast<\n Record<string, PostgresEnumTypeInput>,\n 'entries[type] holds PostgresEnumTypeInput by construction'\n >(rawMap),\n )) {\n typeMap[name] = new PostgresEnumType(v);\n }\n type = Object.freeze(typeMap);\n } else if (kind === 'valueSet') {\n const vsMap: Record<string, StorageValueSet> = {};\n for (const [name, v] of Object.entries(\n blindCast<\n Record<string, StorageValueSetInput>,\n 'entries[valueSet] holds StorageValueSetInput by construction'\n >(rawMap),\n )) {\n vsMap[name] = new StorageValueSet(v);\n }\n if (Object.keys(vsMap).length > 0) {\n valueSet = Object.freeze(vsMap);\n }\n } else {\n carried[kind] = Object.freeze(rawMap);\n }\n }\n\n this.entries = Object.freeze({\n ...carried,\n table,\n type,\n ...ifDefined('valueSet', valueSet),\n });\n Object.defineProperty(this, 'kind', {\n value: 'schema',\n writable: false,\n enumerable: false,\n configurable: true,\n });\n freezeNode(this);\n }\n\n get table(): Readonly<Record<string, StorageTable>> {\n return this.entries.table ?? Object.freeze({});\n }\n\n get type(): Readonly<Record<string, PostgresEnumType>> {\n return this.entries.type ?? Object.freeze({});\n }\n\n get valueSet(): Readonly<Record<string, StorageValueSet>> | undefined {\n return this.entries.valueSet;\n }\n\n /**\n * The bare schema qualifier as it would appear in a rendered SQL\n * fragment (already quoted). The unbound-schema singleton overrides\n * this to return `''`.\n */\n qualifier(): string {\n return `\"${this.id}\"`;\n }\n\n /**\n * Qualify a table name with the schema prefix\n * (`\"<schema>\".\"<table>\"`). The unbound-schema singleton overrides\n * this to emit just `\"<table>\"` so the resolved DDL is unqualified\n * and `search_path` decides where the object lands at runtime.\n */\n qualifyTable(tableName: string): string {\n return `\"${this.id}\".\"${tableName}\"`;\n }\n\n /**\n * Render a SQL string-literal containing the qualified-name form\n * suitable for `to_regclass(...)` arguments (e.g. `'\"public\".\"user\"'`).\n * The unbound singleton overrides this to elide the schema prefix\n * (`'\"user\"'`) so `search_path` resolves the object at runtime.\n */\n regclassLiteral(name: string): string {\n return `'${escapeLiteral(this.qualifyTable(name))}'`;\n }\n\n /**\n * Render a SQL expression that evaluates to this namespace's schema\n * name at runtime, ready to drop into a `WHERE table_schema = …` /\n * `WHERE n.nspname = …` clause. Named schemas emit a quoted SQL\n * literal (`'public'`); the unbound singleton overrides this to emit\n * `current_schema()` so catalog queries match whichever schema the\n * connection's `search_path` resolved at runtime.\n */\n schemaSqlExpression(): string {\n return `'${escapeLiteral(this.id)}'`;\n }\n\n /**\n * The bare schema name a DDL planner should target when emitting\n * statements that need to identify this namespace in the live\n * database (e.g. `CREATE TABLE \"<ddlSchemaName>\".\"<table>\" …`,\n * catalog filters, planner conflict lookups). Named schemas resolve\n * to their own id. The `PostgresUnboundSchema` singleton inherits\n * this and returns `UNBOUND_NAMESPACE_ID` — callers that dispatch\n * through `qualifyTableName` / `toRegclassLiteral` route through the\n * polymorphic `PostgresUnboundSchema` overrides and produce\n * unqualified (search-path-resolved) output automatically.\n */\n ddlSchemaName(_storage: SqlStorage): string {\n return this.id;\n }\n}\n\n/**\n * Singleton subclass for the reserved sentinel namespace id\n * (`UNBOUND_NAMESPACE_ID`) — the late-bound Postgres slot whose binding\n * the connection's `search_path` resolves at runtime. Overrides\n * qualifier emission to elide the schema prefix; call sites that consume\n * `qualifier()` / `qualifyTable()` get unqualified output without\n * branching on the namespace id.\n *\n * This is the target-side materialization of \"the framework provides\n * affordances; targets implement specifics\": the framework names the\n * sentinel; Postgres decides what late-bound means here (the table\n * name, naked — the schema is supplied by the live connection's\n * `search_path`).\n *\n * `ddlSchemaName` is inherited from `PostgresSchema` and returns\n * `UNBOUND_NAMESPACE_ID`. Downstream helpers (`qualifyTableName`,\n * `toRegclassLiteral`) route through the polymorphic factory and\n * produce unqualified output automatically.\n */\nexport class PostgresUnboundSchema extends PostgresSchema {\n static readonly instance: PostgresUnboundSchema = new PostgresUnboundSchema();\n\n constructor(input?: PostgresSchemaInput) {\n super(input ?? { id: UNBOUND_NAMESPACE_ID, entries: { table: {}, type: {} } });\n }\n\n override qualifier(): string {\n return '';\n }\n\n override qualifyTable(tableName: string): string {\n return `\"${tableName}\"`;\n }\n\n override schemaSqlExpression(): string {\n return 'current_schema()';\n }\n}\n\nPostgresSchema.unbound = PostgresUnboundSchema.instance;\n\n/**\n * Narrow an arbitrary namespace (or `undefined`) to `PostgresSchema`\n * so callers can dispatch to the polymorphic emission methods without\n * branching at the call site. Uses the structural `kind` discriminator\n * (`'schema'`) rather than `instanceof` so the check survives realm /\n * bundle / hot-reload boundaries — matching the rest of the IR's\n * narrowing convention. `PostgresUnboundSchema` passes through because\n * it inherits the same `kind: 'schema'` from `PostgresSchema`.\n */\nexport function isPostgresSchema(ns: unknown): ns is PostgresSchema {\n return (ns as { kind?: unknown } | null | undefined)?.kind === 'schema';\n}\n\n/**\n * Target-supplied `Namespace` factory the Postgres target plumbs\n * through `defineContract({ createNamespace })` and the SQL PSL\n * interpreter. Returns the unbound singleton for the framework\n * sentinel and a fresh `PostgresSchema` for any other coordinate.\n *\n * The factory has no per-call state — every named id deterministically\n * maps to a distinct schema instance — so callers can pass it through\n * by reference and trust the resulting `SqlStorage.namespaces` map to\n * be value-stable for a given input set.\n */\nexport function postgresCreateNamespace(\n input: SqlNamespaceTablesInput,\n enumTypes?: Readonly<Record<string, PostgresEnumStorageEntry>>,\n): PostgresSchema {\n const schemaInput: PostgresSchemaInput = {\n id: input.id,\n entries: {\n ...input.entries,\n table: input.entries['table'] ?? {},\n type: blindCast<\n Record<string, PostgresEnumTypeInput>,\n 'enumTypes values are PostgresEnumTypeInput by construction'\n >(enumTypes ?? {}),\n },\n };\n if (input.id === UNBOUND_NAMESPACE_ID) {\n return new PostgresUnboundSchema(schemaInput);\n }\n return new PostgresSchema(schemaInput);\n}\n"],"mappings":"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"}
|
|
@@ -1,217 +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.enumTypes[schemaName][nativeType]`.
|
|
18
|
-
*/
|
|
19
|
-
interface PgStorageTypeEntry {
|
|
20
|
-
readonly codecId?: string;
|
|
21
|
-
readonly typeParams?: { readonly values?: unknown };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Live enum types keyed by `(schemaName, nativeType)` as a nested map, so two
|
|
26
|
-
* schemas sharing a native enum name stay distinct without packing the pair
|
|
27
|
-
* into a string. This is the same `(namespace, entityName)` coordinate the
|
|
28
|
-
* contract side addresses entities by.
|
|
29
|
-
*/
|
|
30
|
-
type PgEnumTypesMap = Readonly<Record<string, Readonly<Record<string, PgStorageTypeEntry>>>>;
|
|
31
|
-
|
|
32
|
-
/** Postgres-specific subtree on family `SqlSchemaIR.annotations`. */
|
|
33
|
-
export interface PostgresSchemaIrAnnotations {
|
|
34
|
-
readonly schema?: string;
|
|
35
|
-
readonly enumTypes?: PgEnumTypesMap;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function readOptionalString(value: unknown): string | undefined {
|
|
39
|
-
return typeof value === 'string' ? value : undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function readPgStorageTypeEntry(value: unknown): PgStorageTypeEntry | undefined {
|
|
43
|
-
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
|
-
const codecId = Reflect.get(value, 'codecId');
|
|
47
|
-
const typeParamsRaw = Reflect.get(value, 'typeParams');
|
|
48
|
-
const typeParams =
|
|
49
|
-
typeParamsRaw !== undefined &&
|
|
50
|
-
typeParamsRaw !== null &&
|
|
51
|
-
typeof typeParamsRaw === 'object' &&
|
|
52
|
-
!Array.isArray(typeParamsRaw)
|
|
53
|
-
? { values: Reflect.get(typeParamsRaw, 'values') }
|
|
54
|
-
: undefined;
|
|
55
|
-
return {
|
|
56
|
-
...(typeof codecId === 'string' ? { codecId } : {}),
|
|
57
|
-
...(typeParams !== undefined ? { typeParams } : {}),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function readPgEnumTypesMap(value: unknown): PgEnumTypesMap | undefined {
|
|
62
|
-
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
const bySchema: Record<string, Record<string, PgStorageTypeEntry>> = {};
|
|
66
|
-
for (const [schemaName, byTypeRaw] of Object.entries(value)) {
|
|
67
|
-
if (byTypeRaw === null || typeof byTypeRaw !== 'object' || Array.isArray(byTypeRaw)) {
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
const byType: Record<string, PgStorageTypeEntry> = {};
|
|
71
|
-
for (const [nativeType, entryValue] of Object.entries(byTypeRaw)) {
|
|
72
|
-
const entry = readPgStorageTypeEntry(entryValue);
|
|
73
|
-
if (entry !== undefined) {
|
|
74
|
-
byType[nativeType] = entry;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (Object.keys(byType).length > 0) {
|
|
78
|
-
bySchema[schemaName] = byType;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return Object.keys(bySchema).length > 0 ? bySchema : undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Reads the Postgres annotation envelope (`schema.annotations.pg`) from
|
|
86
|
-
* family Schema IR. `SqlAnnotations` is an open target-pack extensibility
|
|
87
|
-
* map (`Record<string, unknown>`); this accessor narrows the `pg` slot at
|
|
88
|
-
* runtime so Postgres code can read introspection fields without casts.
|
|
89
|
-
*/
|
|
90
|
-
export function readPostgresSchemaIrAnnotations(schema: SqlSchemaIR): PostgresSchemaIrAnnotations {
|
|
91
|
-
const raw = schema.annotations?.['pg'];
|
|
92
|
-
if (raw === undefined || raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
93
|
-
return {};
|
|
94
|
-
}
|
|
95
|
-
const schemaField = readOptionalString(Reflect.get(raw, 'schema'));
|
|
96
|
-
const enumTypes = readPgEnumTypesMap(Reflect.get(raw, 'enumTypes'));
|
|
97
|
-
return {
|
|
98
|
-
...(schemaField !== undefined ? { schema: schemaField } : {}),
|
|
99
|
-
...(enumTypes !== undefined ? { enumTypes } : {}),
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Resolves the live-schema name a namespace's enums are introspected under,
|
|
105
|
-
* for keying `readExistingEnumValues` lookups. The unbound namespace's
|
|
106
|
-
* `ddlSchemaName` is a planner-emit sentinel (`__unbound__`) that never names a
|
|
107
|
-
* real schema, so for the unbound coordinate we read the *introspected* schema
|
|
108
|
-
* recorded on `annotations.pg.schema` (the live `current_schema()` the adapter
|
|
109
|
-
* walked) — that is the schema the enum's `storageTypes` entry is keyed under.
|
|
110
|
-
* Named namespaces resolve to their own DDL schema, which matches the
|
|
111
|
-
* per-schema introspection key directly.
|
|
112
|
-
*/
|
|
113
|
-
export function resolveDdlSchemaForNamespaceStorage(
|
|
114
|
-
storage: SqlStorage,
|
|
115
|
-
namespaceId: string,
|
|
116
|
-
schemaIr?: SqlSchemaIR,
|
|
117
|
-
): string {
|
|
118
|
-
if (namespaceId === UNBOUND_NAMESPACE_ID) {
|
|
119
|
-
return (schemaIr ? readPostgresSchemaIrAnnotations(schemaIr).schema : undefined) ?? 'public';
|
|
120
|
-
}
|
|
121
|
-
const namespace = storage.namespaces[namespaceId];
|
|
122
|
-
if (namespace && isPostgresSchema(namespace)) {
|
|
123
|
-
return namespace.ddlSchemaName(storage);
|
|
124
|
-
}
|
|
125
|
-
return namespaceId;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** Contract-scoped bridge for the family verifier's enum value resolver. */
|
|
129
|
-
export function createResolveExistingEnumValues(
|
|
130
|
-
storage: SqlStorage,
|
|
131
|
-
): (
|
|
132
|
-
schema: SqlSchemaIR,
|
|
133
|
-
enumType: PostgresEnumStorageEntry,
|
|
134
|
-
namespaceId: string,
|
|
135
|
-
) => readonly string[] | null {
|
|
136
|
-
return (schema, enumType, namespaceId) =>
|
|
137
|
-
readExistingEnumValues(
|
|
138
|
-
schema,
|
|
139
|
-
resolveDdlSchemaForNamespaceStorage(storage, namespaceId, schema),
|
|
140
|
-
enumType.nativeType,
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Categorisation of how an existing enum type's values relate to the
|
|
146
|
-
* desired set in the contract.
|
|
147
|
-
*/
|
|
148
|
-
export type EnumDiff =
|
|
149
|
-
| { readonly kind: 'unchanged' }
|
|
150
|
-
| { readonly kind: 'add_values'; readonly values: readonly string[] }
|
|
151
|
-
| { readonly kind: 'rebuild'; readonly removedValues: readonly string[] };
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Reads existing enum values for `(schemaName, nativeType)` from the
|
|
155
|
-
* Postgres-introspected `schema.annotations.pg.enumTypes` map, addressed by
|
|
156
|
-
* the `(schema, nativeType)` coordinate.
|
|
157
|
-
*
|
|
158
|
-
* Schema IR's enum entries are always codec-typed
|
|
159
|
-
* (`{codecId: PG_ENUM_CODEC_ID, typeParams.values}`): the introspector
|
|
160
|
-
* writes that shape, and the Contract→Schema IR projector resolves
|
|
161
|
-
* `PostgresEnumType` instances down to the same codec-typed triple before
|
|
162
|
-
* they ever land in Schema IR. There is no second on-disk shape to
|
|
163
|
-
* accept here.
|
|
164
|
-
*
|
|
165
|
-
* Returns `null` when no enum entry exists for the given native type.
|
|
166
|
-
*/
|
|
167
|
-
export function readExistingEnumValues(
|
|
168
|
-
schema: SqlSchemaIR,
|
|
169
|
-
schemaName: string,
|
|
170
|
-
nativeType: string,
|
|
171
|
-
): readonly string[] | null {
|
|
172
|
-
const enumTypes = readPostgresSchemaIrAnnotations(schema).enumTypes;
|
|
173
|
-
const existing = enumTypes?.[schemaName]?.[nativeType];
|
|
174
|
-
if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
const enumValues = existing.typeParams?.values;
|
|
178
|
-
if (!Array.isArray(enumValues) || !enumValues.every((v) => typeof v === 'string')) {
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
return enumValues;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Determines what changes are needed to transform existing enum values to
|
|
186
|
-
* desired values.
|
|
187
|
-
*
|
|
188
|
-
* Postgres enums can only have values added (not removed or reordered)
|
|
189
|
-
* without a full type rebuild involving temp type creation and column
|
|
190
|
-
* migration; `'rebuild'` covers the value-removal and reorder cases.
|
|
191
|
-
*/
|
|
192
|
-
export function determineEnumDiff(
|
|
193
|
-
existing: readonly string[],
|
|
194
|
-
desired: readonly string[],
|
|
195
|
-
): EnumDiff {
|
|
196
|
-
if (arraysEqual(existing, desired)) {
|
|
197
|
-
return { kind: 'unchanged' };
|
|
198
|
-
}
|
|
199
|
-
const existingSet = new Set(existing);
|
|
200
|
-
const desiredSet = new Set(desired);
|
|
201
|
-
const missingValues = desired.filter((value) => !existingSet.has(value));
|
|
202
|
-
const removedValues = existing.filter((value) => !desiredSet.has(value));
|
|
203
|
-
const orderMismatch =
|
|
204
|
-
missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);
|
|
205
|
-
if (removedValues.length > 0 || orderMismatch) {
|
|
206
|
-
return { kind: 'rebuild', removedValues };
|
|
207
|
-
}
|
|
208
|
-
return { kind: 'add_values', values: missingValues };
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Convenience accessor — returns the enum's desired values from a
|
|
213
|
-
* `PostgresEnumType` IR instance.
|
|
214
|
-
*/
|
|
215
|
-
export function getDesiredEnumValues(typeInstance: PostgresEnumType): readonly string[] {
|
|
216
|
-
return typeInstance.values;
|
|
217
|
-
}
|
|
@@ -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,10 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
createResolveExistingEnumValues,
|
|
3
|
-
determineEnumDiff,
|
|
4
|
-
type EnumDiff,
|
|
5
|
-
getDesiredEnumValues,
|
|
6
|
-
type PostgresSchemaIrAnnotations,
|
|
7
|
-
readExistingEnumValues,
|
|
8
|
-
readPostgresSchemaIrAnnotations,
|
|
9
|
-
resolveDdlSchemaForNamespaceStorage,
|
|
10
|
-
} from '../core/migrations/enum-planning';
|