@prisma-next/contract 0.14.0-dev.5 → 0.14.0-dev.51
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/enum-accessor.d.mts
CHANGED
|
@@ -22,29 +22,12 @@ interface EnumAccessor {
|
|
|
22
22
|
ordinalOf(v: JsonValue): number;
|
|
23
23
|
}
|
|
24
24
|
declare function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor;
|
|
25
|
-
/**
|
|
26
|
-
* Build the enum-accessor map for a single namespace, keyed by enum name.
|
|
27
|
-
* Each namespace facet exposes only its own enums — the IR keys enums under
|
|
28
|
-
* `domain.namespaces[ns].enum`, so the same name in two namespaces resolves
|
|
29
|
-
* independently rather than colliding in one flat map.
|
|
30
|
-
*/
|
|
31
25
|
declare function buildEnumsMapForNamespace(domain: {
|
|
32
26
|
readonly namespaces: Readonly<Record<string, {
|
|
33
27
|
readonly enum?: Readonly<Record<string, ContractEnum>>;
|
|
34
28
|
}>>;
|
|
35
29
|
}, namespaceId: string): Record<string, EnumAccessor>;
|
|
36
|
-
|
|
37
|
-
* Build the enum-accessor map for every namespace of a domain, keyed by
|
|
38
|
-
* namespace id then enum name. This is the lane-agnostic enum surface the
|
|
39
|
-
* `db.enums` facade member exposes: enums are contract metadata, the same
|
|
40
|
-
* whether reached through the sql lane or the orm lane, so the facade builds
|
|
41
|
-
* this once and projects it per target.
|
|
42
|
-
*/
|
|
43
|
-
declare function buildNamespacedEnums(domain: {
|
|
44
|
-
readonly namespaces: Readonly<Record<string, {
|
|
45
|
-
readonly enum?: Readonly<Record<string, ContractEnum>>;
|
|
46
|
-
}>>;
|
|
47
|
-
}): Record<string, Record<string, EnumAccessor>>;
|
|
30
|
+
declare function buildNamespacedEnums<TContract extends Contract>(domain: TContract['domain']): NamespacedEnums<TContract>;
|
|
48
31
|
type Present<T> = Exclude<T, undefined>;
|
|
49
32
|
type EnumMemberEntry = {
|
|
50
33
|
readonly name: string;
|
|
@@ -53,8 +36,10 @@ type EnumMemberEntry = {
|
|
|
53
36
|
type EnumEntry = {
|
|
54
37
|
readonly members: readonly EnumMemberEntry[];
|
|
55
38
|
};
|
|
56
|
-
type
|
|
57
|
-
type
|
|
39
|
+
type MemberValues<Members> = { readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['value'] : never };
|
|
40
|
+
type MemberNames<Members> = { readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['name'] : never };
|
|
41
|
+
type EnumEntryValues<Entry extends EnumEntry> = MemberValues<Entry['members']>;
|
|
42
|
+
type EnumEntryNames<Entry extends EnumEntry> = MemberNames<Entry['members']>;
|
|
58
43
|
type EnumEntryMembers<Entry extends EnumEntry> = { readonly [M in Entry['members'][number] as M['name']]: M['value'] };
|
|
59
44
|
type ContractEnumAccessor<Entry extends EnumEntry> = {
|
|
60
45
|
readonly values: EnumEntryValues<Entry>;
|
|
@@ -64,6 +49,11 @@ type ContractEnumAccessor<Entry extends EnumEntry> = {
|
|
|
64
49
|
hasName(name: string): name is Extract<EnumEntryNames<Entry>[number], string>;
|
|
65
50
|
nameOf(v: EnumEntryValues<Entry>[number]): string | undefined;
|
|
66
51
|
ordinalOf(v: EnumEntryValues<Entry>[number]): number;
|
|
52
|
+
/**
|
|
53
|
+
* Type-only: the enum's value union. Absent at runtime — use `typeof X.Value`
|
|
54
|
+
* to derive the type; never read `X.Value` as a value.
|
|
55
|
+
*/
|
|
56
|
+
readonly Value: EnumEntryValues<Entry>[number];
|
|
67
57
|
};
|
|
68
58
|
/**
|
|
69
59
|
* The value union for a `ContractEnumAccessor`.
|
|
@@ -81,13 +71,13 @@ type EnumMemberNames<A> = A extends {
|
|
|
81
71
|
} ? N : never;
|
|
82
72
|
type EnumEntriesToAccessors<Enums> = { readonly [K in keyof Enums]: Enums[K] extends EnumEntry ? ContractEnumAccessor<Enums[K]> : never };
|
|
83
73
|
type BuiltEnumAccessorsOf<TContract> = TContract extends {
|
|
84
|
-
readonly enumAccessors
|
|
85
|
-
} ? A : Record<never, never>;
|
|
74
|
+
readonly enumAccessors?: infer A;
|
|
75
|
+
} ? Exclude<A, undefined> : Record<never, never>;
|
|
86
76
|
type NamespaceEnumEntries<TNamespace> = TNamespace extends {
|
|
87
77
|
readonly enum?: infer E;
|
|
88
78
|
} ? unknown extends E ? Record<never, never> : Present<E> : Record<never, never>;
|
|
89
|
-
type NamespaceEnumAccessors<TContract extends Contract, NsId extends keyof TContract['domain']['namespaces']> = EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>>
|
|
79
|
+
type NamespaceEnumAccessors<TContract extends Contract, NsId extends keyof TContract['domain']['namespaces']> = keyof BuiltEnumAccessorsOf<TContract> extends never ? EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>> : BuiltEnumAccessorsOf<TContract>;
|
|
90
80
|
type NamespacedEnums<TContract extends Contract> = { readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns> };
|
|
91
81
|
//#endregion
|
|
92
|
-
export { type ContractEnumAccessor, type EnumAccessor, type EnumMemberNames, type EnumValues, type NamespaceEnumAccessors, type NamespacedEnums, buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
|
|
82
|
+
export { type ContractEnumAccessor, type EnumAccessor, type EnumEntriesToAccessors, type EnumMemberNames, type EnumValues, type NamespaceEnumAccessors, type NamespacedEnums, buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
|
|
93
83
|
//# sourceMappingURL=enum-accessor.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enum-accessor.d.mts","names":[],"sources":["../src/enum-accessor.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"enum-accessor.d.mts","names":[],"sources":["../src/enum-accessor.ts"],"mappings":";;;;;AAeA;;;;;;;;;UAAiB,YAAA;EAAA,SACN,MAAA,WAAiB,SAAA;EAAA,SACjB,KAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA,SAAe,SAAA;EAC1C,GAAA,CAAI,CAAA,EAAG,SAAA;EACP,OAAA,CAAQ,IAAA;EACR,MAAA,CAAO,CAAA,EAAG,SAAA;EACV,SAAA,CAAU,CAAA,EAAG,SAAA;AAAA;AAAA,iBAGC,kBAAA,CAAmB,YAAA,EAAc,YAAA,GAAe,YAAY;AAAA,iBAuB5D,yBAAA,CACd,MAAA;EAAA,SACW,UAAA,EAAY,QAAA,CACnB,MAAA;IAAA,SAA0B,IAAA,GAAO,QAAA,CAAS,MAAA,SAAe,YAAA;EAAA;AAAA,GAG7D,WAAA,WACC,MAAA,SAAe,YAAA;AAAA,iBAWF,oBAAA,mBAAuC,QAAA,EACrD,MAAA,EAAQ,SAAA,aACP,eAAA,CAAgB,SAAA;AAAA,KAWd,OAAA,MAAa,OAAO,CAAC,CAAA;AAAA,KAErB,eAAA;EAAA,SAA6B,IAAA;EAAA,SAAuB,KAAA,EAAO,SAAS;AAAA;AAAA,KACpE,SAAA;EAAA,SAAuB,OAAA,WAAkB,eAAe;AAAA;AAAA,KAKxD,YAAA,mCACkB,OAAA,GAAU,OAAA,CAAQ,CAAA,UAAW,eAAA,GAAkB,OAAA,CAAQ,CAAA;AAAA,KAGzE,WAAA,mCACkB,OAAA,GAAU,OAAA,CAAQ,CAAA,UAAW,eAAA,GAAkB,OAAA,CAAQ,CAAA;AAAA,KAGzE,eAAA,eAA8B,SAAA,IAAa,YAAA,CAAa,KAAA;AAAA,KAExD,cAAA,eAA6B,SAAA,IAAa,WAAA,CAAY,KAAA;AAAA,KAEtD,gBAAA,eAA+B,SAAA,qBACnB,KAAA,uBAA4B,CAAA,WAAY,CAAA;AAAA,KAG7C,oBAAA,eAAmC,SAAA;EAAA,SACpC,MAAA,EAAQ,eAAA,CAAgB,KAAA;EAAA,SACxB,KAAA,EAAO,cAAA,CAAe,KAAA;EAAA,SACtB,OAAA,EAAS,gBAAA,CAAiB,KAAA,GAxDZ;EA0DvB,GAAA,CAAI,CAAA,EAAG,SAAA,GAAY,CAAA,IAAK,eAAA,CAAgB,KAAA,WArDvC;EAuDD,OAAA,CAAQ,IAAA,WAAe,IAAA,IAAQ,OAAA,CAAQ,cAAA,CAAe,KAAA;EACtD,MAAA,CAAO,CAAA,EAAG,eAAA,CAAgB,KAAA;EAC1B,SAAA,CAAU,CAAA,EAAG,eAAA,CAAgB,KAAA;EA9DN;;;;EAAA,SAmEd,KAAA,EAAO,eAAA,CAAgB,KAAA;AAAA;;;;;;KAQtB,UAAA,MAAgB,CAAA;EAAA,SAAqB,MAAA,EAAQ,aAAa;AAAA,IAAc,CAAA;;;;KAKxE,eAAA,MAAqB,CAAA;EAAA,SAAqB,KAAA,EAAO,aAAa;AAAA,IAAc,CAAA;AAAA,KAE5E,sBAAA,iCACW,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,SAAA,GAAY,oBAAA,CAAqB,KAAA,CAAM,CAAA;AAAA,KAGlF,oBAAA,cAAkC,SAAA;EAAA,SAC5B,aAAA;AAAA,IAEP,OAAA,CAAQ,CAAA,eACR,MAAA;AAAA,KAEC,oBAAA,eAAmC,UAAA;EAAA,SAC7B,IAAA;AAAA,oBAES,CAAA,GACd,MAAA,iBACA,OAAA,CAAQ,CAAA,IACV,MAAA;AAAA,KAIQ,sBAAA,mBACQ,QAAA,qBACC,SAAA,kCACX,oBAAA,CAAqB,SAAA,kBAC3B,sBAAA,CAAuB,oBAAA,CAAqB,SAAA,yBAAkC,IAAA,MAC9E,oBAAA,CAAqB,SAAA;AAAA,KAEb,eAAA,mBAAkC,QAAA,4BACtB,SAAA,2BAAoC,sBAAA,CAAuB,SAAA,EAAW,EAAA"}
|
package/dist/enum-accessor.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
1
2
|
//#region src/enum-accessor.ts
|
|
2
3
|
function createEnumAccessor(contractEnum) {
|
|
3
4
|
const values = Object.freeze(contractEnum.members.map((m) => m.value));
|
|
@@ -17,29 +18,16 @@ function createEnumAccessor(contractEnum) {
|
|
|
17
18
|
ordinalOf: (v) => valueToOrdinal.get(v) ?? -1
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Build the enum-accessor map for a single namespace, keyed by enum name.
|
|
22
|
-
* Each namespace facet exposes only its own enums — the IR keys enums under
|
|
23
|
-
* `domain.namespaces[ns].enum`, so the same name in two namespaces resolves
|
|
24
|
-
* independently rather than colliding in one flat map.
|
|
25
|
-
*/
|
|
26
21
|
function buildEnumsMapForNamespace(domain, namespaceId) {
|
|
27
22
|
const result = {};
|
|
28
23
|
const namespace = domain.namespaces[namespaceId];
|
|
29
24
|
if (namespace?.enum) for (const [name, contractEnum] of Object.entries(namespace.enum)) result[name] = createEnumAccessor(contractEnum);
|
|
30
25
|
return result;
|
|
31
26
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Build the enum-accessor map for every namespace of a domain, keyed by
|
|
34
|
-
* namespace id then enum name. This is the lane-agnostic enum surface the
|
|
35
|
-
* `db.enums` facade member exposes: enums are contract metadata, the same
|
|
36
|
-
* whether reached through the sql lane or the orm lane, so the facade builds
|
|
37
|
-
* this once and projects it per target.
|
|
38
|
-
*/
|
|
39
27
|
function buildNamespacedEnums(domain) {
|
|
40
28
|
const result = {};
|
|
41
29
|
for (const namespaceId of Object.keys(domain.namespaces)) result[namespaceId] = buildEnumsMapForNamespace(domain, namespaceId);
|
|
42
|
-
return result;
|
|
30
|
+
return blindCast(result);
|
|
43
31
|
}
|
|
44
32
|
//#endregion
|
|
45
33
|
export { buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enum-accessor.mjs","names":[],"sources":["../src/enum-accessor.ts"],"sourcesContent":["import type { Contract } from './contract-types';\nimport type { ContractEnum } from './domain-types';\nimport type { JsonValue } from './types';\n\n/**\n * Runtime view of a domain enum, built at the client from the emitted\n * `ContractEnum` JSON (codec-encoded `JsonValue` members, literal types erased).\n *\n * This deliberately mirrors the accessor shape of the authoring-time\n * `EnumTypeHandle` (in `contract-ts`) rather than reusing it: that handle carries\n * the literal value generics and lives in the authoring layer, which the\n * foundation layer cannot depend on. The two are the same surface seen from the\n * two planes — authoring (typed) and runtime (validated JSON).\n */\nexport interface EnumAccessor {\n readonly values: readonly JsonValue[];\n readonly names: readonly string[];\n readonly members: Readonly<Record<string, JsonValue>>;\n has(v: JsonValue): boolean;\n hasName(name: string): boolean;\n nameOf(v: JsonValue): string | undefined;\n ordinalOf(v: JsonValue): number;\n}\n\nexport function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor {\n const values = Object.freeze(contractEnum.members.map((m) => m.value));\n const names = Object.freeze(contractEnum.members.map((m) => m.name));\n const members: Readonly<Record<string, JsonValue>> = Object.freeze(\n Object.fromEntries(contractEnum.members.map((m) => [m.name, m.value])),\n );\n\n const valueSet = new Set(values);\n const nameSet = Object.freeze(new Set(names));\n const valueToName = new Map(contractEnum.members.map((m) => [m.value, m.name]));\n const valueToOrdinal = new Map(values.map((v, i) => [v, i]));\n\n return {\n values,\n names,\n members,\n has: (v: JsonValue) => valueSet.has(v),\n hasName: (name: string) => nameSet.has(name),\n nameOf: (v: JsonValue) => valueToName.get(v),\n ordinalOf: (v: JsonValue) => valueToOrdinal.get(v) ?? -1,\n };\n}\n\
|
|
1
|
+
{"version":3,"file":"enum-accessor.mjs","names":[],"sources":["../src/enum-accessor.ts"],"sourcesContent":["import { blindCast } from '@prisma-next/utils/casts';\nimport type { Contract } from './contract-types';\nimport type { ContractEnum } from './domain-types';\nimport type { JsonValue } from './types';\n\n/**\n * Runtime view of a domain enum, built at the client from the emitted\n * `ContractEnum` JSON (codec-encoded `JsonValue` members, literal types erased).\n *\n * This deliberately mirrors the accessor shape of the authoring-time\n * `EnumTypeHandle` (in `contract-ts`) rather than reusing it: that handle carries\n * the literal value generics and lives in the authoring layer, which the\n * foundation layer cannot depend on. The two are the same surface seen from the\n * two planes — authoring (typed) and runtime (validated JSON).\n */\nexport interface EnumAccessor {\n readonly values: readonly JsonValue[];\n readonly names: readonly string[];\n readonly members: Readonly<Record<string, JsonValue>>;\n has(v: JsonValue): boolean;\n hasName(name: string): boolean;\n nameOf(v: JsonValue): string | undefined;\n ordinalOf(v: JsonValue): number;\n}\n\nexport function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor {\n const values = Object.freeze(contractEnum.members.map((m) => m.value));\n const names = Object.freeze(contractEnum.members.map((m) => m.name));\n const members: Readonly<Record<string, JsonValue>> = Object.freeze(\n Object.fromEntries(contractEnum.members.map((m) => [m.name, m.value])),\n );\n\n const valueSet = new Set(values);\n const nameSet = Object.freeze(new Set(names));\n const valueToName = new Map(contractEnum.members.map((m) => [m.value, m.name]));\n const valueToOrdinal = new Map(values.map((v, i) => [v, i]));\n\n return {\n values,\n names,\n members,\n has: (v: JsonValue) => valueSet.has(v),\n hasName: (name: string) => nameSet.has(name),\n nameOf: (v: JsonValue) => valueToName.get(v),\n ordinalOf: (v: JsonValue) => valueToOrdinal.get(v) ?? -1,\n };\n}\n\nexport function buildEnumsMapForNamespace(\n domain: {\n readonly namespaces: Readonly<\n Record<string, { readonly enum?: Readonly<Record<string, ContractEnum>> }>\n >;\n },\n namespaceId: string,\n): Record<string, EnumAccessor> {\n const result: Record<string, EnumAccessor> = {};\n const namespace = domain.namespaces[namespaceId];\n if (namespace?.enum) {\n for (const [name, contractEnum] of Object.entries(namespace.enum)) {\n result[name] = createEnumAccessor(contractEnum);\n }\n }\n return result;\n}\n\nexport function buildNamespacedEnums<TContract extends Contract>(\n domain: TContract['domain'],\n): NamespacedEnums<TContract> {\n const result: Record<string, Record<string, EnumAccessor>> = {};\n for (const namespaceId of Object.keys(domain.namespaces)) {\n result[namespaceId] = buildEnumsMapForNamespace(domain, namespaceId);\n }\n return blindCast<\n NamespacedEnums<TContract>,\n 'built dynamically from domain.namespaces; the mapped-type shape cannot be proven statically'\n >(result);\n}\n\ntype Present<T> = Exclude<T, undefined>;\n\ntype EnumMemberEntry = { readonly name: string; readonly value: JsonValue };\ntype EnumEntry = { readonly members: readonly EnumMemberEntry[] };\n\n// Mapped over a bare type parameter so the mapped type is homomorphic — a\n// readonly tuple of members yields a readonly tuple of values/names (array\n// methods preserved), not a plain `{ 0: …; 1: … }` mapped object.\ntype MemberValues<Members> = {\n readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['value'] : never;\n};\n\ntype MemberNames<Members> = {\n readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['name'] : never;\n};\n\ntype EnumEntryValues<Entry extends EnumEntry> = MemberValues<Entry['members']>;\n\ntype EnumEntryNames<Entry extends EnumEntry> = MemberNames<Entry['members']>;\n\ntype EnumEntryMembers<Entry extends EnumEntry> = {\n readonly [M in Entry['members'][number] as M['name']]: M['value'];\n};\n\nexport type ContractEnumAccessor<Entry extends EnumEntry> = {\n readonly values: EnumEntryValues<Entry>;\n readonly names: EnumEntryNames<Entry>;\n readonly members: EnumEntryMembers<Entry>;\n /** Returns true and narrows `v` to the enum's value union when `v` is a declared member value. */\n has(v: JsonValue): v is EnumEntryValues<Entry>[number];\n /** Returns true and narrows `name` to the enum's member-name union when `name` is a declared member name. */\n hasName(name: string): name is Extract<EnumEntryNames<Entry>[number], string>;\n nameOf(v: EnumEntryValues<Entry>[number]): string | undefined;\n ordinalOf(v: EnumEntryValues<Entry>[number]): number;\n /**\n * Type-only: the enum's value union. Absent at runtime — use `typeof X.Value`\n * to derive the type; never read `X.Value` as a value.\n */\n readonly Value: EnumEntryValues<Entry>[number];\n};\n\n/**\n * The value union for a `ContractEnumAccessor`.\n * Use in function signatures to accept any declared enum value without re-exporting\n * the member type alias from the accessor's generic entry.\n */\nexport type EnumValues<A> = A extends { readonly values: ReadonlyArray<infer V> } ? V : never;\n\n/**\n * The member-name union for a `ContractEnumAccessor`.\n */\nexport type EnumMemberNames<A> = A extends { readonly names: ReadonlyArray<infer N> } ? N : never;\n\nexport type EnumEntriesToAccessors<Enums> = {\n readonly [K in keyof Enums]: Enums[K] extends EnumEntry ? ContractEnumAccessor<Enums[K]> : never;\n};\n\ntype BuiltEnumAccessorsOf<TContract> = TContract extends {\n readonly enumAccessors?: infer A;\n}\n ? Exclude<A, undefined>\n : Record<never, never>;\n\ntype NamespaceEnumEntries<TNamespace> = TNamespace extends {\n readonly enum?: infer E;\n}\n ? unknown extends E\n ? Record<never, never>\n : Present<E>\n : Record<never, never>;\n\n// When `enumAccessors` is present (TS-DSL contract), it is the sole source because merging\n// both carriers would create conflicting `values` types for the same enum key.\nexport type NamespaceEnumAccessors<\n TContract extends Contract,\n NsId extends keyof TContract['domain']['namespaces'],\n> = keyof BuiltEnumAccessorsOf<TContract> extends never\n ? EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>>\n : BuiltEnumAccessorsOf<TContract>;\n\nexport type NamespacedEnums<TContract extends Contract> = {\n readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns>;\n};\n"],"mappings":";;AAyBA,SAAgB,mBAAmB,cAA0C;CAC3E,MAAM,SAAS,OAAO,OAAO,aAAa,QAAQ,KAAK,MAAM,EAAE,KAAK,CAAC;CACrE,MAAM,QAAQ,OAAO,OAAO,aAAa,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC;CACnE,MAAM,UAA+C,OAAO,OAC1D,OAAO,YAAY,aAAa,QAAQ,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CACvE;CAEA,MAAM,WAAW,IAAI,IAAI,MAAM;CAC/B,MAAM,UAAU,OAAO,OAAO,IAAI,IAAI,KAAK,CAAC;CAC5C,MAAM,cAAc,IAAI,IAAI,aAAa,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;CAC9E,MAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;CAE3D,OAAO;EACL;EACA;EACA;EACA,MAAM,MAAiB,SAAS,IAAI,CAAC;EACrC,UAAU,SAAiB,QAAQ,IAAI,IAAI;EAC3C,SAAS,MAAiB,YAAY,IAAI,CAAC;EAC3C,YAAY,MAAiB,eAAe,IAAI,CAAC,KAAK;CACxD;AACF;AAEA,SAAgB,0BACd,QAKA,aAC8B;CAC9B,MAAM,SAAuC,CAAC;CAC9C,MAAM,YAAY,OAAO,WAAW;CACpC,IAAI,WAAW,MACb,KAAK,MAAM,CAAC,MAAM,iBAAiB,OAAO,QAAQ,UAAU,IAAI,GAC9D,OAAO,QAAQ,mBAAmB,YAAY;CAGlD,OAAO;AACT;AAEA,SAAgB,qBACd,QAC4B;CAC5B,MAAM,SAAuD,CAAC;CAC9D,KAAK,MAAM,eAAe,OAAO,KAAK,OAAO,UAAU,GACrD,OAAO,eAAe,0BAA0B,QAAQ,WAAW;CAErE,OAAO,UAGL,MAAM;AACV"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/contract",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.51",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Data contract type definitions and JSON schema for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/utils": "0.14.0-dev.
|
|
9
|
+
"@prisma-next/utils": "0.14.0-dev.51",
|
|
10
10
|
"@standard-schema/spec": "^1.1.0",
|
|
11
11
|
"arktype": "^2.2.0"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@prisma-next/tsconfig": "0.14.0-dev.
|
|
15
|
-
"@prisma-next/tsdown": "0.14.0-dev.
|
|
14
|
+
"@prisma-next/tsconfig": "0.14.0-dev.51",
|
|
15
|
+
"@prisma-next/tsdown": "0.14.0-dev.51",
|
|
16
16
|
"tsdown": "0.22.1",
|
|
17
17
|
"typescript": "5.9.3",
|
|
18
18
|
"vitest": "4.1.8"
|
package/src/enum-accessor.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
1
2
|
import type { Contract } from './contract-types';
|
|
2
3
|
import type { ContractEnum } from './domain-types';
|
|
3
4
|
import type { JsonValue } from './types';
|
|
@@ -45,12 +46,6 @@ export function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor {
|
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
/**
|
|
49
|
-
* Build the enum-accessor map for a single namespace, keyed by enum name.
|
|
50
|
-
* Each namespace facet exposes only its own enums — the IR keys enums under
|
|
51
|
-
* `domain.namespaces[ns].enum`, so the same name in two namespaces resolves
|
|
52
|
-
* independently rather than colliding in one flat map.
|
|
53
|
-
*/
|
|
54
49
|
export function buildEnumsMapForNamespace(
|
|
55
50
|
domain: {
|
|
56
51
|
readonly namespaces: Readonly<
|
|
@@ -69,70 +64,43 @@ export function buildEnumsMapForNamespace(
|
|
|
69
64
|
return result;
|
|
70
65
|
}
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
* `db.enums` facade member exposes: enums are contract metadata, the same
|
|
76
|
-
* whether reached through the sql lane or the orm lane, so the facade builds
|
|
77
|
-
* this once and projects it per target.
|
|
78
|
-
*/
|
|
79
|
-
export function buildNamespacedEnums(domain: {
|
|
80
|
-
readonly namespaces: Readonly<
|
|
81
|
-
Record<string, { readonly enum?: Readonly<Record<string, ContractEnum>> }>
|
|
82
|
-
>;
|
|
83
|
-
}): Record<string, Record<string, EnumAccessor>> {
|
|
67
|
+
export function buildNamespacedEnums<TContract extends Contract>(
|
|
68
|
+
domain: TContract['domain'],
|
|
69
|
+
): NamespacedEnums<TContract> {
|
|
84
70
|
const result: Record<string, Record<string, EnumAccessor>> = {};
|
|
85
71
|
for (const namespaceId of Object.keys(domain.namespaces)) {
|
|
86
72
|
result[namespaceId] = buildEnumsMapForNamespace(domain, namespaceId);
|
|
87
73
|
}
|
|
88
|
-
return
|
|
74
|
+
return blindCast<
|
|
75
|
+
NamespacedEnums<TContract>,
|
|
76
|
+
'built dynamically from domain.namespaces; the mapped-type shape cannot be proven statically'
|
|
77
|
+
>(result);
|
|
89
78
|
}
|
|
90
79
|
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
|
-
// Type-level projection of the namespaced enum surface.
|
|
93
|
-
//
|
|
94
|
-
// These types derive the literal-preserving accessor shape from the contract,
|
|
95
|
-
// hung off the `db.enums` facade map (`db.enums.<ns>.<Name>`). They are the
|
|
96
|
-
// same accessors the runtime builds above, but typed from the two emission
|
|
97
|
-
// paths:
|
|
98
|
-
// - Emitted contracts carry the literal enum entries under
|
|
99
|
-
// `domain.namespaces[ns].enum`; each maps to a `ContractEnumAccessor`.
|
|
100
|
-
// - The no-emit (built) contract carries them flat on `enumAccessors`
|
|
101
|
-
// (already accessor-shaped, literal-preserving), since its built domain
|
|
102
|
-
// type does not narrow `namespaces[ns].enum`. All authored enums land in
|
|
103
|
-
// the single built namespace, so exposing the flat map per namespace is
|
|
104
|
-
// correct there.
|
|
105
|
-
// Only `SqlContractResult` carries `enumAccessors`; emitted contracts never
|
|
106
|
-
// do, so the two carriers never overlap.
|
|
107
|
-
// ---------------------------------------------------------------------------
|
|
108
|
-
|
|
109
80
|
type Present<T> = Exclude<T, undefined>;
|
|
110
81
|
|
|
111
|
-
// A domain enum entry as carried in `domain.namespaces[ns].enum[name]`: an
|
|
112
|
-
// ordered member tuple. The no-emit (built) path preserves the literal member
|
|
113
|
-
// values so the derived accessor keeps its literal `values`/`names`/`members`.
|
|
114
82
|
type EnumMemberEntry = { readonly name: string; readonly value: JsonValue };
|
|
115
83
|
type EnumEntry = { readonly members: readonly EnumMemberEntry[] };
|
|
116
84
|
|
|
117
|
-
type
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
85
|
+
// Mapped over a bare type parameter so the mapped type is homomorphic — a
|
|
86
|
+
// readonly tuple of members yields a readonly tuple of values/names (array
|
|
87
|
+
// methods preserved), not a plain `{ 0: …; 1: … }` mapped object.
|
|
88
|
+
type MemberValues<Members> = {
|
|
89
|
+
readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['value'] : never;
|
|
121
90
|
};
|
|
122
91
|
|
|
123
|
-
type
|
|
124
|
-
readonly [I in keyof
|
|
125
|
-
? Entry['members'][I]['name']
|
|
126
|
-
: never;
|
|
92
|
+
type MemberNames<Members> = {
|
|
93
|
+
readonly [I in keyof Members]: Members[I] extends EnumMemberEntry ? Members[I]['name'] : never;
|
|
127
94
|
};
|
|
128
95
|
|
|
96
|
+
type EnumEntryValues<Entry extends EnumEntry> = MemberValues<Entry['members']>;
|
|
97
|
+
|
|
98
|
+
type EnumEntryNames<Entry extends EnumEntry> = MemberNames<Entry['members']>;
|
|
99
|
+
|
|
129
100
|
type EnumEntryMembers<Entry extends EnumEntry> = {
|
|
130
101
|
readonly [M in Entry['members'][number] as M['name']]: M['value'];
|
|
131
102
|
};
|
|
132
103
|
|
|
133
|
-
// The runtime accessor shape for one enum, with literal `values`/`names`/
|
|
134
|
-
// `members` derived from the entry's member tuple. Mirrors `EnumAccessor`'s
|
|
135
|
-
// runtime surface and the authoring `EnumTypeHandle` accessor.
|
|
136
104
|
export type ContractEnumAccessor<Entry extends EnumEntry> = {
|
|
137
105
|
readonly values: EnumEntryValues<Entry>;
|
|
138
106
|
readonly names: EnumEntryNames<Entry>;
|
|
@@ -143,6 +111,11 @@ export type ContractEnumAccessor<Entry extends EnumEntry> = {
|
|
|
143
111
|
hasName(name: string): name is Extract<EnumEntryNames<Entry>[number], string>;
|
|
144
112
|
nameOf(v: EnumEntryValues<Entry>[number]): string | undefined;
|
|
145
113
|
ordinalOf(v: EnumEntryValues<Entry>[number]): number;
|
|
114
|
+
/**
|
|
115
|
+
* Type-only: the enum's value union. Absent at runtime — use `typeof X.Value`
|
|
116
|
+
* to derive the type; never read `X.Value` as a value.
|
|
117
|
+
*/
|
|
118
|
+
readonly Value: EnumEntryValues<Entry>[number];
|
|
146
119
|
};
|
|
147
120
|
|
|
148
121
|
/**
|
|
@@ -157,14 +130,14 @@ export type EnumValues<A> = A extends { readonly values: ReadonlyArray<infer V>
|
|
|
157
130
|
*/
|
|
158
131
|
export type EnumMemberNames<A> = A extends { readonly names: ReadonlyArray<infer N> } ? N : never;
|
|
159
132
|
|
|
160
|
-
type EnumEntriesToAccessors<Enums> = {
|
|
133
|
+
export type EnumEntriesToAccessors<Enums> = {
|
|
161
134
|
readonly [K in keyof Enums]: Enums[K] extends EnumEntry ? ContractEnumAccessor<Enums[K]> : never;
|
|
162
135
|
};
|
|
163
136
|
|
|
164
137
|
type BuiltEnumAccessorsOf<TContract> = TContract extends {
|
|
165
|
-
readonly enumAccessors
|
|
138
|
+
readonly enumAccessors?: infer A;
|
|
166
139
|
}
|
|
167
|
-
? A
|
|
140
|
+
? Exclude<A, undefined>
|
|
168
141
|
: Record<never, never>;
|
|
169
142
|
|
|
170
143
|
type NamespaceEnumEntries<TNamespace> = TNamespace extends {
|
|
@@ -175,17 +148,15 @@ type NamespaceEnumEntries<TNamespace> = TNamespace extends {
|
|
|
175
148
|
: Present<E>
|
|
176
149
|
: Record<never, never>;
|
|
177
150
|
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
// namespaces resolves to each namespace's own accessor.
|
|
151
|
+
// When `enumAccessors` is present (TS-DSL contract), it is the sole source because merging
|
|
152
|
+
// both carriers would create conflicting `values` types for the same enum key.
|
|
181
153
|
export type NamespaceEnumAccessors<
|
|
182
154
|
TContract extends Contract,
|
|
183
155
|
NsId extends keyof TContract['domain']['namespaces'],
|
|
184
|
-
> =
|
|
185
|
-
|
|
156
|
+
> = keyof BuiltEnumAccessorsOf<TContract> extends never
|
|
157
|
+
? EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>>
|
|
158
|
+
: BuiltEnumAccessorsOf<TContract>;
|
|
186
159
|
|
|
187
|
-
// The lane-agnostic enum surface exposed on the `db.enums` facade member: a
|
|
188
|
-
// namespace-keyed map projected per target exactly like `db.sql` / `db.orm`.
|
|
189
160
|
export type NamespacedEnums<TContract extends Contract> = {
|
|
190
161
|
readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns>;
|
|
191
162
|
};
|