@prisma-next/contract 0.14.0-dev.3 → 0.14.0-dev.30

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.
@@ -22,24 +22,11 @@ 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
30
  declare function buildNamespacedEnums(domain: {
44
31
  readonly namespaces: Readonly<Record<string, {
45
32
  readonly enum?: Readonly<Record<string, ContractEnum>>;
@@ -81,12 +68,12 @@ type EnumMemberNames<A> = A extends {
81
68
  } ? N : never;
82
69
  type EnumEntriesToAccessors<Enums> = { readonly [K in keyof Enums]: Enums[K] extends EnumEntry ? ContractEnumAccessor<Enums[K]> : never };
83
70
  type BuiltEnumAccessorsOf<TContract> = TContract extends {
84
- readonly enumAccessors: infer A;
85
- } ? A : Record<never, never>;
71
+ readonly enumAccessors?: infer A;
72
+ } ? Exclude<A, undefined> : Record<never, never>;
86
73
  type NamespaceEnumEntries<TNamespace> = TNamespace extends {
87
74
  readonly enum?: infer E;
88
75
  } ? 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]>> & BuiltEnumAccessorsOf<TContract>;
76
+ 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
77
  type NamespacedEnums<TContract extends Contract> = { readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns> };
91
78
  //#endregion
92
79
  export { type ContractEnumAccessor, type EnumAccessor, type EnumMemberNames, type EnumValues, type NamespaceEnumAccessors, type NamespacedEnums, buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
@@ -1 +1 @@
1
- {"version":3,"file":"enum-accessor.d.mts","names":[],"sources":["../src/enum-accessor.ts"],"mappings":";;;;;AAcA;;;;;;;;;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;;;;;;;iBA6B5D,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;;AAvCM;AAGxB;;;;;iBAsDgB,oBAAA,CAAqB,MAAA;EAAA,SAC1B,UAAA,EAAY,QAAA,CACnB,MAAA;IAAA,SAA0B,IAAA,GAAO,QAAA,CAAS,MAAA,SAAe,YAAA;EAAA;AAAA,IAEzD,MAAA,SAAe,MAAA,SAAe,YAAA;AAAA,KA0B7B,OAAA,MAAa,OAAO,CAAC,CAAA;AAAA,KAKrB,eAAA;EAAA,SAA6B,IAAA;EAAA,SAAuB,KAAA,EAAO,SAAS;AAAA;AAAA,KACpE,SAAA;EAAA,SAAuB,OAAA,WAAkB,eAAe;AAAA;AAAA,KAExD,eAAA,eAA8B,SAAA,2BACZ,KAAA,cAAmB,KAAA,YAAiB,CAAA,UAAW,eAAA,GAChE,KAAA,YAAiB,CAAA;AAAA,KAIlB,cAAA,eAA6B,SAAA,2BACX,KAAA,cAAmB,KAAA,YAAiB,CAAA,UAAW,eAAA,GAChE,KAAA,YAAiB,CAAA;AAAA,KAIlB,gBAAA,eAA+B,SAAA,qBACnB,KAAA,uBAA4B,CAAA,WAAY,CAAA;AAAA,KAM7C,oBAAA,eAAmC,SAAA;EAAA,SACpC,MAAA,EAAQ,eAAA,CAAgB,KAAA;EAAA,SACxB,KAAA,EAAO,cAAA,CAAe,KAAA;EAAA,SACtB,OAAA,EAAS,gBAAA,CAAiB,KAAA,GA9EnB;EAgFhB,GAAA,CAAI,CAAA,EAAG,SAAA,GAAY,CAAA,IAAK,eAAA,CAAgB,KAAA,WAhFZ;EAkF5B,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;AAAA;;;;;;KAQnB,UAAA,MAAgB,CAAA;EAAA,SAAqB,MAAA,EAAQ,aAAa;AAAA,IAAc,CAAA;;;;KAKxE,eAAA,MAAqB,CAAA;EAAA,SAAqB,KAAA,EAAO,aAAa;AAAA,IAAc,CAAA;AAAA,KAEnF,sBAAA,iCACkB,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,SAAA,GAAY,oBAAA,CAAqB,KAAA,CAAM,CAAA;AAAA,KAGlF,oBAAA,cAAkC,SAAA;EAAA,SAC5B,aAAA;AAAA,IAEP,CAAA,GACA,MAAM;AAAA,KAEL,oBAAA,eAAmC,UAAA;EAAA,SAC7B,IAAA;AAAA,oBAES,CAAA,GACd,MAAA,iBACA,OAAA,CAAQ,CAAA,IACV,MAAA;AAAA,KAKQ,sBAAA,mBACQ,QAAA,qBACC,SAAA,4BACjB,sBAAA,CAAuB,oBAAA,CAAqB,SAAA,yBAAkC,IAAA,MAChF,oBAAA,CAAqB,SAAA;AAAA,KAIX,eAAA,mBAAkC,QAAA,4BACtB,SAAA,2BAAoC,sBAAA,CAAuB,SAAA,EAAW,EAAA"}
1
+ {"version":3,"file":"enum-accessor.d.mts","names":[],"sources":["../src/enum-accessor.ts"],"mappings":";;;;;AAcA;;;;;;;;;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,CAAqB,MAAA;EAAA,SAC1B,UAAA,EAAY,QAAA,CACnB,MAAA;IAAA,SAA0B,IAAA,GAAO,QAAA,CAAS,MAAA,SAAe,YAAA;EAAA;AAAA,IAEzD,MAAA,SAAe,MAAA,SAAe,YAAA;AAAA,KAQ7B,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,KAExD,eAAA,eAA8B,SAAA,2BACZ,KAAA,cAAmB,KAAA,YAAiB,CAAA,UAAW,eAAA,GAChE,KAAA,YAAiB,CAAA;AAAA,KAIlB,cAAA,eAA6B,SAAA,2BACX,KAAA,cAAmB,KAAA,YAAiB,CAAA,UAAW,eAAA,GAChE,KAAA,YAAiB,CAAA;AAAA,KAIlB,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,GA/ClC;EAiDD,GAAA,CAAI,CAAA,EAAG,SAAA,GAAY,CAAA,IAAK,eAAA,CAAgB,KAAA,WAjDjC;EAmDP,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;AAAA;;;;;;KAQnB,UAAA,MAAgB,CAAA;EAAA,SAAqB,MAAA,EAAQ,aAAa;AAAA,IAAc,CAAA;AA7DtD;AAW9B;;AAX8B,KAkElB,eAAA,MAAqB,CAAA;EAAA,SAAqB,KAAA,EAAO,aAAa;AAAA,IAAc,CAAA;AAAA,KAEnF,sBAAA,iCACkB,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"}
@@ -17,25 +17,12 @@ function createEnumAccessor(contractEnum) {
17
17
  ordinalOf: (v) => valueToOrdinal.get(v) ?? -1
18
18
  };
19
19
  }
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
20
  function buildEnumsMapForNamespace(domain, namespaceId) {
27
21
  const result = {};
28
22
  const namespace = domain.namespaces[namespaceId];
29
23
  if (namespace?.enum) for (const [name, contractEnum] of Object.entries(namespace.enum)) result[name] = createEnumAccessor(contractEnum);
30
24
  return result;
31
25
  }
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
26
  function buildNamespacedEnums(domain) {
40
27
  const result = {};
41
28
  for (const namespaceId of Object.keys(domain.namespaces)) result[namespaceId] = buildEnumsMapForNamespace(domain, namespaceId);
@@ -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\n/**\n * Build the enum-accessor map for a single namespace, keyed by enum name.\n * Each namespace facet exposes only its own enums — the IR keys enums under\n * `domain.namespaces[ns].enum`, so the same name in two namespaces resolves\n * independently rather than colliding in one flat map.\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\n/**\n * Build the enum-accessor map for every namespace of a domain, keyed by\n * namespace id then enum name. This is the lane-agnostic enum surface the\n * `db.enums` facade member exposes: enums are contract metadata, the same\n * whether reached through the sql lane or the orm lane, so the facade builds\n * this once and projects it per target.\n */\nexport function buildNamespacedEnums(domain: {\n readonly namespaces: Readonly<\n Record<string, { readonly enum?: Readonly<Record<string, ContractEnum>> }>\n >;\n}): Record<string, Record<string, EnumAccessor>> {\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 result;\n}\n\n// ---------------------------------------------------------------------------\n// Type-level projection of the namespaced enum surface.\n//\n// These types derive the literal-preserving accessor shape from the contract,\n// hung off the `db.enums` facade map (`db.enums.<ns>.<Name>`). They are the\n// same accessors the runtime builds above, but typed from the two emission\n// paths:\n// - Emitted contracts carry the literal enum entries under\n// `domain.namespaces[ns].enum`; each maps to a `ContractEnumAccessor`.\n// - The no-emit (built) contract carries them flat on `enumAccessors`\n// (already accessor-shaped, literal-preserving), since its built domain\n// type does not narrow `namespaces[ns].enum`. All authored enums land in\n// the single built namespace, so exposing the flat map per namespace is\n// correct there.\n// Only `SqlContractResult` carries `enumAccessors`; emitted contracts never\n// do, so the two carriers never overlap.\n// ---------------------------------------------------------------------------\n\ntype Present<T> = Exclude<T, undefined>;\n\n// A domain enum entry as carried in `domain.namespaces[ns].enum[name]`: an\n// ordered member tuple. The no-emit (built) path preserves the literal member\n// values so the derived accessor keeps its literal `values`/`names`/`members`.\ntype EnumMemberEntry = { readonly name: string; readonly value: JsonValue };\ntype EnumEntry = { readonly members: readonly EnumMemberEntry[] };\n\ntype EnumEntryValues<Entry extends EnumEntry> = {\n readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry\n ? Entry['members'][I]['value']\n : never;\n};\n\ntype EnumEntryNames<Entry extends EnumEntry> = {\n readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry\n ? Entry['members'][I]['name']\n : never;\n};\n\ntype EnumEntryMembers<Entry extends EnumEntry> = {\n readonly [M in Entry['members'][number] as M['name']]: M['value'];\n};\n\n// The runtime accessor shape for one enum, with literal `values`/`names`/\n// `members` derived from the entry's member tuple. Mirrors `EnumAccessor`'s\n// runtime surface and the authoring `EnumTypeHandle` accessor.\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\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\ntype 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 ? A\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// The per-namespace enum accessors. Each namespace exposes only its own enums\n// (the IR's `domain.namespaces[ns].enum`), so the same enum name in two\n// namespaces resolves to each namespace's own accessor.\nexport type NamespaceEnumAccessors<\n TContract extends Contract,\n NsId extends keyof TContract['domain']['namespaces'],\n> = EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>> &\n BuiltEnumAccessorsOf<TContract>;\n\n// The lane-agnostic enum surface exposed on the `db.enums` facade member: a\n// namespace-keyed map projected per target exactly like `db.sql` / `db.orm`.\nexport type NamespacedEnums<TContract extends Contract> = {\n readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns>;\n};\n"],"mappings":";AAwBA,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;;;;;;;AAQA,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;;;;;;;;AASA,SAAgB,qBAAqB,QAIY;CAC/C,MAAM,SAAuD,CAAC;CAC9D,KAAK,MAAM,eAAe,OAAO,KAAK,OAAO,UAAU,GACrD,OAAO,eAAe,0BAA0B,QAAQ,WAAW;CAErE,OAAO;AACT"}
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\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(domain: {\n readonly namespaces: Readonly<\n Record<string, { readonly enum?: Readonly<Record<string, ContractEnum>> }>\n >;\n}): Record<string, Record<string, EnumAccessor>> {\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 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\ntype EnumEntryValues<Entry extends EnumEntry> = {\n readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry\n ? Entry['members'][I]['value']\n : never;\n};\n\ntype EnumEntryNames<Entry extends EnumEntry> = {\n readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry\n ? Entry['members'][I]['name']\n : never;\n};\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\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\ntype 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":";AAwBA,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,qBAAqB,QAIY;CAC/C,MAAM,SAAuD,CAAC;CAC9D,KAAK,MAAM,eAAe,OAAO,KAAK,OAAO,UAAU,GACrD,OAAO,eAAe,0BAA0B,QAAQ,WAAW;CAErE,OAAO;AACT"}
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@prisma-next/contract",
3
- "version": "0.14.0-dev.3",
3
+ "version": "0.14.0-dev.30",
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.3",
9
+ "@prisma-next/utils": "0.14.0-dev.30",
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.3",
15
- "@prisma-next/tsdown": "0.14.0-dev.3",
14
+ "@prisma-next/tsconfig": "0.14.0-dev.30",
15
+ "@prisma-next/tsdown": "0.14.0-dev.30",
16
16
  "tsdown": "0.22.1",
17
17
  "typescript": "5.9.3",
18
18
  "vitest": "4.1.8"
@@ -45,12 +45,6 @@ export function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor {
45
45
  };
46
46
  }
47
47
 
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
48
  export function buildEnumsMapForNamespace(
55
49
  domain: {
56
50
  readonly namespaces: Readonly<
@@ -69,13 +63,6 @@ export function buildEnumsMapForNamespace(
69
63
  return result;
70
64
  }
71
65
 
72
- /**
73
- * Build the enum-accessor map for every namespace of a domain, keyed by
74
- * namespace id then enum name. This is the lane-agnostic enum surface the
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
66
  export function buildNamespacedEnums(domain: {
80
67
  readonly namespaces: Readonly<
81
68
  Record<string, { readonly enum?: Readonly<Record<string, ContractEnum>> }>
@@ -88,29 +75,8 @@ export function buildNamespacedEnums(domain: {
88
75
  return result;
89
76
  }
90
77
 
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
78
  type Present<T> = Exclude<T, undefined>;
110
79
 
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
80
  type EnumMemberEntry = { readonly name: string; readonly value: JsonValue };
115
81
  type EnumEntry = { readonly members: readonly EnumMemberEntry[] };
116
82
 
@@ -130,9 +96,6 @@ type EnumEntryMembers<Entry extends EnumEntry> = {
130
96
  readonly [M in Entry['members'][number] as M['name']]: M['value'];
131
97
  };
132
98
 
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
99
  export type ContractEnumAccessor<Entry extends EnumEntry> = {
137
100
  readonly values: EnumEntryValues<Entry>;
138
101
  readonly names: EnumEntryNames<Entry>;
@@ -162,9 +125,9 @@ type EnumEntriesToAccessors<Enums> = {
162
125
  };
163
126
 
164
127
  type BuiltEnumAccessorsOf<TContract> = TContract extends {
165
- readonly enumAccessors: infer A;
128
+ readonly enumAccessors?: infer A;
166
129
  }
167
- ? A
130
+ ? Exclude<A, undefined>
168
131
  : Record<never, never>;
169
132
 
170
133
  type NamespaceEnumEntries<TNamespace> = TNamespace extends {
@@ -175,17 +138,15 @@ type NamespaceEnumEntries<TNamespace> = TNamespace extends {
175
138
  : Present<E>
176
139
  : Record<never, never>;
177
140
 
178
- // The per-namespace enum accessors. Each namespace exposes only its own enums
179
- // (the IR's `domain.namespaces[ns].enum`), so the same enum name in two
180
- // namespaces resolves to each namespace's own accessor.
141
+ // When `enumAccessors` is present (TS-DSL contract), it is the sole source because merging
142
+ // both carriers would create conflicting `values` types for the same enum key.
181
143
  export type NamespaceEnumAccessors<
182
144
  TContract extends Contract,
183
145
  NsId extends keyof TContract['domain']['namespaces'],
184
- > = EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>> &
185
- BuiltEnumAccessorsOf<TContract>;
146
+ > = keyof BuiltEnumAccessorsOf<TContract> extends never
147
+ ? EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>>
148
+ : BuiltEnumAccessorsOf<TContract>;
186
149
 
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
150
  export type NamespacedEnums<TContract extends Contract> = {
190
151
  readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns>;
191
152
  };