@prisma-next/contract 0.12.0 → 0.13.0-dev.10

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.
Files changed (78) hide show
  1. package/dist/apply-specifier-default-control-policy.d.mts +7 -0
  2. package/dist/apply-specifier-default-control-policy.d.mts.map +1 -0
  3. package/dist/apply-specifier-default-control-policy.mjs +12 -0
  4. package/dist/apply-specifier-default-control-policy.mjs.map +1 -0
  5. package/dist/{canonicalization-DFE0HJkI.d.mts → canonicalization-BqYzAeWE.d.mts} +2 -2
  6. package/dist/canonicalization-BqYzAeWE.d.mts.map +1 -0
  7. package/dist/{canonicalization-path-match-b2jFuEso.mjs → canonicalization-path-match-CNgHuwM_.mjs} +1 -1
  8. package/dist/{canonicalization-path-match-b2jFuEso.mjs.map → canonicalization-path-match-CNgHuwM_.mjs.map} +1 -1
  9. package/dist/contract-types-CtIh62PH.d.mts +82 -0
  10. package/dist/contract-types-CtIh62PH.d.mts.map +1 -0
  11. package/dist/{contract-validation-error-ClZaKqMW.mjs → contract-validation-error-BFA66rwU.mjs} +1 -1
  12. package/dist/{contract-validation-error-ClZaKqMW.mjs.map → contract-validation-error-BFA66rwU.mjs.map} +1 -1
  13. package/dist/{contract-validation-error-T5LH4DW-.d.mts → contract-validation-error-D7g0kmcc.d.mts} +1 -1
  14. package/dist/{contract-validation-error-T5LH4DW-.d.mts.map → contract-validation-error-D7g0kmcc.d.mts.map} +1 -1
  15. package/dist/contract-validation-error.d.mts +1 -1
  16. package/dist/contract-validation-error.mjs +1 -1
  17. package/dist/default-namespace-D5X_k6hJ.d.mts +25 -0
  18. package/dist/default-namespace-D5X_k6hJ.d.mts.map +1 -0
  19. package/dist/default-namespace-rpdJeUMq.mjs +33 -0
  20. package/dist/default-namespace-rpdJeUMq.mjs.map +1 -0
  21. package/dist/default-namespace.d.mts +2 -0
  22. package/dist/default-namespace.mjs +2 -0
  23. package/dist/domain-envelope-DKOnhO5d.d.mts +352 -0
  24. package/dist/domain-envelope-DKOnhO5d.d.mts.map +1 -0
  25. package/dist/enum-accessor.d.mts +77 -0
  26. package/dist/enum-accessor.d.mts.map +1 -0
  27. package/dist/enum-accessor.mjs +45 -0
  28. package/dist/enum-accessor.mjs.map +1 -0
  29. package/dist/hashing-utils.d.mts +1 -1
  30. package/dist/hashing-utils.d.mts.map +1 -1
  31. package/dist/hashing-utils.mjs +5 -4
  32. package/dist/hashing-utils.mjs.map +1 -1
  33. package/dist/hashing.d.mts +2 -2
  34. package/dist/hashing.d.mts.map +1 -1
  35. package/dist/hashing.mjs +38 -11
  36. package/dist/hashing.mjs.map +1 -1
  37. package/dist/{namespace-id-CVpkSFUK.mjs → namespace-id-CUxYd4KL.mjs} +1 -1
  38. package/dist/{namespace-id-CVpkSFUK.mjs.map → namespace-id-CUxYd4KL.mjs.map} +1 -1
  39. package/dist/resolve-domain-model-BovPAsW2.mjs +20 -0
  40. package/dist/resolve-domain-model-BovPAsW2.mjs.map +1 -0
  41. package/dist/resolve-domain-model-CSEqpByI.d.mts +17 -0
  42. package/dist/resolve-domain-model-CSEqpByI.d.mts.map +1 -0
  43. package/dist/resolve-domain-model.d.mts +2 -0
  44. package/dist/resolve-domain-model.mjs +2 -0
  45. package/dist/types.d.mts +21 -4
  46. package/dist/types.d.mts.map +1 -0
  47. package/dist/types.mjs +40 -30
  48. package/dist/types.mjs.map +1 -1
  49. package/dist/validate-domain.d.mts +1 -1
  50. package/dist/validate-domain.mjs +6 -3
  51. package/dist/validate-domain.mjs.map +1 -1
  52. package/package.json +10 -6
  53. package/src/apply-specifier-default-control-policy.ts +12 -0
  54. package/src/canonicalization-storage-sort.ts +8 -1
  55. package/src/canonicalization.ts +13 -4
  56. package/src/contract-types.ts +9 -5
  57. package/src/control-policy.ts +25 -0
  58. package/src/cross-reference.ts +15 -3
  59. package/src/default-namespace.ts +36 -0
  60. package/src/domain-envelope.ts +3 -61
  61. package/src/domain-namespace-access.ts +32 -0
  62. package/src/domain-types.ts +32 -1
  63. package/src/enum-accessor.ts +173 -0
  64. package/src/exports/apply-specifier-default-control-policy.ts +1 -0
  65. package/src/exports/default-namespace.ts +1 -0
  66. package/src/exports/enum-accessor.ts +11 -0
  67. package/src/exports/resolve-domain-model.ts +1 -0
  68. package/src/exports/types.ts +16 -7
  69. package/src/hashing.ts +42 -13
  70. package/src/resolve-domain-model.ts +27 -0
  71. package/src/types.ts +18 -2
  72. package/src/validate-domain.ts +6 -0
  73. package/src/value-set-ref.ts +26 -0
  74. package/dist/canonicalization-DFE0HJkI.d.mts.map +0 -1
  75. package/dist/contract-types-xgwKtd7y.d.mts +0 -233
  76. package/dist/contract-types-xgwKtd7y.d.mts.map +0 -1
  77. package/dist/domain-envelope-4hyFtJ4_.d.mts +0 -110
  78. package/dist/domain-envelope-4hyFtJ4_.d.mts.map +0 -1
@@ -0,0 +1,77 @@
1
+ import { t as Contract } from "./contract-types-CtIh62PH.mjs";
2
+ import { U as JsonValue, o as ContractEnum } from "./domain-envelope-DKOnhO5d.mjs";
3
+
4
+ //#region src/enum-accessor.d.ts
5
+ /**
6
+ * Runtime view of a domain enum, built at the client from the emitted
7
+ * `ContractEnum` JSON (codec-encoded `JsonValue` members, literal types erased).
8
+ *
9
+ * This deliberately mirrors the accessor shape of the authoring-time
10
+ * `EnumTypeHandle` (in `contract-ts`) rather than reusing it: that handle carries
11
+ * the literal value generics and lives in the authoring layer, which the
12
+ * foundation layer cannot depend on. The two are the same surface seen from the
13
+ * two planes — authoring (typed) and runtime (validated JSON).
14
+ */
15
+ interface EnumAccessor {
16
+ readonly values: readonly JsonValue[];
17
+ readonly names: readonly string[];
18
+ readonly members: Readonly<Record<string, JsonValue>>;
19
+ has(v: JsonValue): boolean;
20
+ nameOf(v: JsonValue): string | undefined;
21
+ ordinalOf(v: JsonValue): number;
22
+ }
23
+ declare function createEnumAccessor(contractEnum: ContractEnum): EnumAccessor;
24
+ /**
25
+ * Build the enum-accessor map for a single namespace, keyed by enum name.
26
+ * Each namespace facet exposes only its own enums — the IR keys enums under
27
+ * `domain.namespaces[ns].enum`, so the same name in two namespaces resolves
28
+ * independently rather than colliding in one flat map.
29
+ */
30
+ declare function buildEnumsMapForNamespace(domain: {
31
+ readonly namespaces: Readonly<Record<string, {
32
+ readonly enum?: Readonly<Record<string, ContractEnum>>;
33
+ }>>;
34
+ }, namespaceId: string): Record<string, EnumAccessor>;
35
+ /**
36
+ * Build the enum-accessor map for every namespace of a domain, keyed by
37
+ * namespace id then enum name. This is the lane-agnostic enum surface the
38
+ * `db.enums` facade member exposes: enums are contract metadata, the same
39
+ * whether reached through the sql lane or the orm lane, so the facade builds
40
+ * this once and projects it per target.
41
+ */
42
+ declare function buildNamespacedEnums(domain: {
43
+ readonly namespaces: Readonly<Record<string, {
44
+ readonly enum?: Readonly<Record<string, ContractEnum>>;
45
+ }>>;
46
+ }): Record<string, Record<string, EnumAccessor>>;
47
+ type Present<T> = Exclude<T, undefined>;
48
+ type EnumMemberEntry = {
49
+ readonly name: string;
50
+ readonly value: unknown;
51
+ };
52
+ type EnumEntry = {
53
+ readonly members: readonly EnumMemberEntry[];
54
+ };
55
+ type EnumEntryValues<Entry extends EnumEntry> = { readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry ? Entry['members'][I]['value'] : never };
56
+ type EnumEntryNames<Entry extends EnumEntry> = { readonly [I in keyof Entry['members']]: Entry['members'][I] extends EnumMemberEntry ? Entry['members'][I]['name'] : never };
57
+ type EnumEntryMembers<Entry extends EnumEntry> = { readonly [M in Entry['members'][number] as M['name']]: M['value'] };
58
+ type ContractEnumAccessor<Entry extends EnumEntry> = {
59
+ readonly values: EnumEntryValues<Entry>;
60
+ readonly names: EnumEntryNames<Entry>;
61
+ readonly members: EnumEntryMembers<Entry>;
62
+ has(v: EnumEntryValues<Entry>[number]): boolean;
63
+ nameOf(v: EnumEntryValues<Entry>[number]): string | undefined;
64
+ ordinalOf(v: EnumEntryValues<Entry>[number]): number;
65
+ };
66
+ type EnumEntriesToAccessors<Enums> = { readonly [K in keyof Enums]: Enums[K] extends EnumEntry ? ContractEnumAccessor<Enums[K]> : never };
67
+ type BuiltEnumAccessorsOf<TContract> = TContract extends {
68
+ readonly enumAccessors: infer A;
69
+ } ? A : Record<never, never>;
70
+ type NamespaceEnumEntries<TNamespace> = TNamespace extends {
71
+ readonly enum?: infer E;
72
+ } ? unknown extends E ? Record<never, never> : Present<E> : Record<never, never>;
73
+ type NamespaceEnumAccessors<TContract extends Contract, NsId extends keyof TContract['domain']['namespaces']> = EnumEntriesToAccessors<NamespaceEnumEntries<TContract['domain']['namespaces'][NsId]>> & BuiltEnumAccessorsOf<TContract>;
74
+ type NamespacedEnums<TContract extends Contract> = { readonly [Ns in keyof TContract['domain']['namespaces']]: NamespaceEnumAccessors<TContract, Ns> };
75
+ //#endregion
76
+ export { type ContractEnumAccessor, type EnumAccessor, type NamespaceEnumAccessors, type NamespacedEnums, buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
77
+ //# sourceMappingURL=enum-accessor.d.mts.map
@@ -0,0 +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,MAAA,CAAO,CAAA,EAAG,SAAA;EACV,SAAA,CAAU,CAAA,EAAG,SAAA;AAAA;AAAA,iBAGC,kBAAA,CAAmB,YAAA,EAAc,YAAA,GAAe,YAAY;;;;;;;iBA2B5D,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;AArCM;AAGxB;;;;;;AAHwB,iBAuDR,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,KAAK;AAAA;AAAA,KACzD,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;EACnC,GAAA,CAAI,CAAA,EAAG,eAAA,CAAgB,KAAA;EACvB,MAAA,CAAO,CAAA,EAAG,eAAA,CAAgB,KAAA;EAC1B,SAAA,CAAU,CAAA,EAAG,eAAA,CAAgB,KAAA;AAAA;AAAA,KAG1B,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"}
@@ -0,0 +1,45 @@
1
+ //#region src/enum-accessor.ts
2
+ function createEnumAccessor(contractEnum) {
3
+ const values = Object.freeze(contractEnum.members.map((m) => m.value));
4
+ const names = Object.freeze(contractEnum.members.map((m) => m.name));
5
+ const members = Object.freeze(Object.fromEntries(contractEnum.members.map((m) => [m.name, m.value])));
6
+ const valueSet = new Set(values);
7
+ const valueToName = new Map(contractEnum.members.map((m) => [m.value, m.name]));
8
+ const valueToOrdinal = new Map(values.map((v, i) => [v, i]));
9
+ return {
10
+ values,
11
+ names,
12
+ members,
13
+ has: (v) => valueSet.has(v),
14
+ nameOf: (v) => valueToName.get(v),
15
+ ordinalOf: (v) => valueToOrdinal.get(v) ?? -1
16
+ };
17
+ }
18
+ /**
19
+ * Build the enum-accessor map for a single namespace, keyed by enum name.
20
+ * Each namespace facet exposes only its own enums — the IR keys enums under
21
+ * `domain.namespaces[ns].enum`, so the same name in two namespaces resolves
22
+ * independently rather than colliding in one flat map.
23
+ */
24
+ function buildEnumsMapForNamespace(domain, namespaceId) {
25
+ const result = {};
26
+ const namespace = domain.namespaces[namespaceId];
27
+ if (namespace?.enum) for (const [name, contractEnum] of Object.entries(namespace.enum)) result[name] = createEnumAccessor(contractEnum);
28
+ return result;
29
+ }
30
+ /**
31
+ * Build the enum-accessor map for every namespace of a domain, keyed by
32
+ * namespace id then enum name. This is the lane-agnostic enum surface the
33
+ * `db.enums` facade member exposes: enums are contract metadata, the same
34
+ * whether reached through the sql lane or the orm lane, so the facade builds
35
+ * this once and projects it per target.
36
+ */
37
+ function buildNamespacedEnums(domain) {
38
+ const result = {};
39
+ for (const namespaceId of Object.keys(domain.namespaces)) result[namespaceId] = buildEnumsMapForNamespace(domain, namespaceId);
40
+ return result;
41
+ }
42
+ //#endregion
43
+ export { buildEnumsMapForNamespace, buildNamespacedEnums, createEnumAccessor };
44
+
45
+ //# sourceMappingURL=enum-accessor.mjs.map
@@ -0,0 +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 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 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 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: unknown };\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 has(v: EnumEntryValues<Entry>[number]): boolean;\n nameOf(v: EnumEntryValues<Entry>[number]): string | undefined;\n ordinalOf(v: EnumEntryValues<Entry>[number]): number;\n};\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":";AAuBA,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,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,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,4 +1,4 @@
1
- import { i as StorageSort, n as PreserveEmptyPredicate } from "./canonicalization-DFE0HJkI.mjs";
1
+ import { i as StorageSort, n as PreserveEmptyPredicate } from "./canonicalization-BqYzAeWE.mjs";
2
2
 
3
3
  //#region src/canonicalization-path-match.d.ts
4
4
  type PathSegment = string | '*' | readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"hashing-utils.d.mts","names":[],"sources":["../src/canonicalization-path-match.ts","../src/canonicalization-storage-sort.ts"],"mappings":";;;KAEY,WAAA;AAAA,KAEA,WAAA,YAAuB,WAAW;AAAA,iBAE9B,kBAAA,CAAmB,IAAA,qBAAyB,OAAA,EAAS,WAAW;AAAA,iBAiChE,4BAAA,CACd,QAAA,WAAmB,WAAA,KAClB,sBAAsB;;;KCvCb,aAAA;AAAA,UAEK,oBAAA;EAAA,SACN,IAAA,WAAe,aAAW;EAAA,SAC1B,SAAA;AAAA;AAAA,iBAOK,qBAAA,CAAsB,CAAA,WAAY,CAAU;AAAA,iBA2D5C,iBAAA,CACd,OAAA,WAAkB,oBAAA,IAClB,OAAA,IAAU,CAAA,WAAY,CAAA,uBACrB,WAAW"}
1
+ {"version":3,"file":"hashing-utils.d.mts","names":[],"sources":["../src/canonicalization-path-match.ts","../src/canonicalization-storage-sort.ts"],"mappings":";;;KAEY,WAAA;AAAA,KAEA,WAAA,YAAuB,WAAW;AAAA,iBAE9B,kBAAA,CAAmB,IAAA,qBAAyB,OAAA,EAAS,WAAW;AAAA,iBAiChE,4BAAA,CACd,QAAA,WAAmB,WAAA,KAClB,sBAAsB;;;KCvCb,aAAA;AAAA,UAEK,oBAAA;EAAA,SACN,IAAA,WAAe,aAAW;EAAA,SAC1B,SAAA;AAAA;AAAA,iBAcK,qBAAA,CAAsB,CAAA,WAAY,CAAU;AAAA,iBA2D5C,iBAAA,CACd,OAAA,WAAkB,oBAAA,IAClB,OAAA,IAAU,CAAA,WAAY,CAAA,uBACrB,WAAW"}
@@ -1,12 +1,13 @@
1
- import { n as matchesPathPattern, t as createPreserveEmptyPredicate } from "./canonicalization-path-match-b2jFuEso.mjs";
1
+ import { n as matchesPathPattern, t as createPreserveEmptyPredicate } from "./canonicalization-path-match-CNgHuwM_.mjs";
2
2
  //#region src/canonicalization-storage-sort.ts
3
3
  function isPlainRecord(value) {
4
4
  return typeof value === "object" && value !== null && !Array.isArray(value);
5
5
  }
6
+ function compareCodeUnits(a, b) {
7
+ return a < b ? -1 : a > b ? 1 : 0;
8
+ }
6
9
  function compareByNameProperty(a, b) {
7
- const nameA = isPlainRecord(a) && typeof a["name"] === "string" ? a["name"] : "";
8
- const nameB = isPlainRecord(b) && typeof b["name"] === "string" ? b["name"] : "";
9
- return nameA.localeCompare(nameB);
10
+ return compareCodeUnits(isPlainRecord(a) && typeof a["name"] === "string" ? a["name"] : "", isPlainRecord(b) && typeof b["name"] === "string" ? b["name"] : "");
10
11
  }
11
12
  function sortArrayKeysOnRecord(record, arrayKeys, compare) {
12
13
  const sorted = { ...record };
@@ -1 +1 @@
1
- {"version":3,"file":"hashing-utils.mjs","names":[],"sources":["../src/canonicalization-storage-sort.ts"],"sourcesContent":["import type { StorageSort } from './canonicalization';\n\nexport type PathSegment = string | '*';\n\nexport interface NamedArraySortTarget {\n readonly path: readonly PathSegment[];\n readonly arrayKeys: readonly string[];\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function compareByNameProperty(a: unknown, b: unknown): number {\n const nameA = isPlainRecord(a) && typeof a['name'] === 'string' ? a['name'] : '';\n const nameB = isPlainRecord(b) && typeof b['name'] === 'string' ? b['name'] : '';\n return nameA.localeCompare(nameB);\n}\n\nfunction sortArrayKeysOnRecord(\n record: Record<string, unknown>,\n arrayKeys: readonly string[],\n compare: (a: unknown, b: unknown) => number,\n): Record<string, unknown> {\n const sorted: Record<string, unknown> = { ...record };\n for (const key of arrayKeys) {\n const value = record[key];\n if (Array.isArray(value)) {\n sorted[key] = [...value].sort(compare);\n }\n }\n return sorted;\n}\n\nfunction walkAndSort(\n node: unknown,\n pathSegments: readonly PathSegment[],\n arrayKeys: readonly string[],\n compare: (a: unknown, b: unknown) => number,\n): unknown {\n if (pathSegments.length === 0) {\n if (!isPlainRecord(node)) {\n return node;\n }\n return sortArrayKeysOnRecord(node, arrayKeys, compare);\n }\n\n if (!isPlainRecord(node)) {\n return node;\n }\n\n const [head, ...rest] = pathSegments;\n if (head === undefined) {\n return node;\n }\n\n if (head === '*') {\n const sorted: Record<string, unknown> = { ...node };\n for (const key of Object.keys(node)) {\n sorted[key] = walkAndSort(node[key], rest, arrayKeys, compare);\n }\n return sorted;\n }\n\n const child = node[head];\n if (child === undefined) {\n return node;\n }\n\n return { ...node, [head]: walkAndSort(child, rest, arrayKeys, compare) };\n}\n\nexport function createStorageSort(\n targets: readonly NamedArraySortTarget[],\n compare: (a: unknown, b: unknown) => number = compareByNameProperty,\n): StorageSort {\n return (storage) => {\n if (!isPlainRecord(storage)) {\n return storage;\n }\n\n let result: unknown = storage;\n for (const target of targets) {\n result = walkAndSort(result, target.path, target.arrayKeys, compare);\n }\n return result;\n };\n}\n"],"mappings":";;AASA,SAAS,cAAc,OAAkD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAgB,sBAAsB,GAAY,GAAoB;CACpE,MAAM,QAAQ,cAAc,CAAC,KAAK,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;CAC9E,MAAM,QAAQ,cAAc,CAAC,KAAK,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;CAC9E,OAAO,MAAM,cAAc,KAAK;AAClC;AAEA,SAAS,sBACP,QACA,WACA,SACyB;CACzB,MAAM,SAAkC,EAAE,GAAG,OAAO;CACpD,KAAK,MAAM,OAAO,WAAW;EAC3B,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,OAAO,CAAC,GAAG,KAAK,EAAE,KAAK,OAAO;CAEzC;CACA,OAAO;AACT;AAEA,SAAS,YACP,MACA,cACA,WACA,SACS;CACT,IAAI,aAAa,WAAW,GAAG;EAC7B,IAAI,CAAC,cAAc,IAAI,GACrB,OAAO;EAET,OAAO,sBAAsB,MAAM,WAAW,OAAO;CACvD;CAEA,IAAI,CAAC,cAAc,IAAI,GACrB,OAAO;CAGT,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,SAAS,KAAA,GACX,OAAO;CAGT,IAAI,SAAS,KAAK;EAChB,MAAM,SAAkC,EAAE,GAAG,KAAK;EAClD,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,GAChC,OAAO,OAAO,YAAY,KAAK,MAAM,MAAM,WAAW,OAAO;EAE/D,OAAO;CACT;CAEA,MAAM,QAAQ,KAAK;CACnB,IAAI,UAAU,KAAA,GACZ,OAAO;CAGT,OAAO;EAAE,GAAG;GAAO,OAAO,YAAY,OAAO,MAAM,WAAW,OAAO;CAAE;AACzE;AAEA,SAAgB,kBACd,SACA,UAA8C,uBACjC;CACb,QAAQ,YAAY;EAClB,IAAI,CAAC,cAAc,OAAO,GACxB,OAAO;EAGT,IAAI,SAAkB;EACtB,KAAK,MAAM,UAAU,SACnB,SAAS,YAAY,QAAQ,OAAO,MAAM,OAAO,WAAW,OAAO;EAErE,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"hashing-utils.mjs","names":[],"sources":["../src/canonicalization-storage-sort.ts"],"sourcesContent":["import type { StorageSort } from './canonicalization';\n\nexport type PathSegment = string | '*';\n\nexport interface NamedArraySortTarget {\n readonly path: readonly PathSegment[];\n readonly arrayKeys: readonly string[];\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// Order by UTF-16 code unit, not locale collation: canonicalization feeds\n// storageHash, which must be byte-identical across hosts, and locale\n// collation (localeCompare/Intl) varies by the engine's ICU build.\nfunction compareCodeUnits(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\nexport function compareByNameProperty(a: unknown, b: unknown): number {\n const nameA = isPlainRecord(a) && typeof a['name'] === 'string' ? a['name'] : '';\n const nameB = isPlainRecord(b) && typeof b['name'] === 'string' ? b['name'] : '';\n return compareCodeUnits(nameA, nameB);\n}\n\nfunction sortArrayKeysOnRecord(\n record: Record<string, unknown>,\n arrayKeys: readonly string[],\n compare: (a: unknown, b: unknown) => number,\n): Record<string, unknown> {\n const sorted: Record<string, unknown> = { ...record };\n for (const key of arrayKeys) {\n const value = record[key];\n if (Array.isArray(value)) {\n sorted[key] = [...value].sort(compare);\n }\n }\n return sorted;\n}\n\nfunction walkAndSort(\n node: unknown,\n pathSegments: readonly PathSegment[],\n arrayKeys: readonly string[],\n compare: (a: unknown, b: unknown) => number,\n): unknown {\n if (pathSegments.length === 0) {\n if (!isPlainRecord(node)) {\n return node;\n }\n return sortArrayKeysOnRecord(node, arrayKeys, compare);\n }\n\n if (!isPlainRecord(node)) {\n return node;\n }\n\n const [head, ...rest] = pathSegments;\n if (head === undefined) {\n return node;\n }\n\n if (head === '*') {\n const sorted: Record<string, unknown> = { ...node };\n for (const key of Object.keys(node)) {\n sorted[key] = walkAndSort(node[key], rest, arrayKeys, compare);\n }\n return sorted;\n }\n\n const child = node[head];\n if (child === undefined) {\n return node;\n }\n\n return { ...node, [head]: walkAndSort(child, rest, arrayKeys, compare) };\n}\n\nexport function createStorageSort(\n targets: readonly NamedArraySortTarget[],\n compare: (a: unknown, b: unknown) => number = compareByNameProperty,\n): StorageSort {\n return (storage) => {\n if (!isPlainRecord(storage)) {\n return storage;\n }\n\n let result: unknown = storage;\n for (const target of targets) {\n result = walkAndSort(result, target.path, target.arrayKeys, compare);\n }\n return result;\n };\n}\n"],"mappings":";;AASA,SAAS,cAAc,OAAkD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAKA,SAAS,iBAAiB,GAAW,GAAmB;CACtD,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAClC;AAEA,SAAgB,sBAAsB,GAAY,GAAoB;CAGpE,OAAO,iBAFO,cAAc,CAAC,KAAK,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,IAChE,cAAc,CAAC,KAAK,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,EAC1C;AACtC;AAEA,SAAS,sBACP,QACA,WACA,SACyB;CACzB,MAAM,SAAkC,EAAE,GAAG,OAAO;CACpD,KAAK,MAAM,OAAO,WAAW;EAC3B,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,OAAO;CAEzC;CACA,OAAO;AACT;AAEA,SAAS,YACP,MACA,cACA,WACA,SACS;CACT,IAAI,aAAa,WAAW,GAAG;EAC7B,IAAI,CAAC,cAAc,IAAI,GACrB,OAAO;EAET,OAAO,sBAAsB,MAAM,WAAW,OAAO;CACvD;CAEA,IAAI,CAAC,cAAc,IAAI,GACrB,OAAO;CAGT,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,SAAS,KAAA,GACX,OAAO;CAGT,IAAI,SAAS,KAAK;EAChB,MAAM,SAAkC,EAAE,GAAG,KAAK;EAClD,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,GAChC,OAAO,OAAO,YAAY,KAAK,MAAM,MAAM,WAAW,OAAO;EAE/D,OAAO;CACT;CAEA,MAAM,QAAQ,KAAK;CACnB,IAAI,UAAU,KAAA,GACZ,OAAO;CAGT,OAAO;EAAE,GAAG;GAAO,OAAO,YAAY,OAAO,MAAM,WAAW,OAAO;CAAE;AACzE;AAEA,SAAgB,kBACd,SACA,UAA8C,uBACjC;CACb,QAAQ,YAAY;EAClB,IAAI,CAAC,cAAc,OAAO,GACxB,OAAO;EAGT,IAAI,SAAkB;EACtB,KAAK,MAAM,UAAU,SACnB,SAAS,YAAY,QAAQ,OAAO,MAAM,OAAO,WAAW,OAAO;EAErE,OAAO;CACT;AACF"}
@@ -1,5 +1,5 @@
1
- import { O as StorageHashBase, p as ExecutionHashBase, w as ProfileHashBase } from "./contract-types-xgwKtd7y.mjs";
2
- import { a as canonicalizeContract, i as StorageSort, n as PreserveEmptyPredicate, o as canonicalizeContractToObject, r as SerializeContract, t as CanonicalizeContractOptions } from "./canonicalization-DFE0HJkI.mjs";
1
+ import { K as ProfileHashBase, P as ExecutionHashBase, X as StorageHashBase } from "./domain-envelope-DKOnhO5d.mjs";
2
+ import { a as canonicalizeContract, i as StorageSort, n as PreserveEmptyPredicate, o as canonicalizeContractToObject, r as SerializeContract, t as CanonicalizeContractOptions } from "./canonicalization-BqYzAeWE.mjs";
3
3
 
4
4
  //#region src/hashing.d.ts
5
5
  type ComputeStorageHashArgs = {
@@ -1 +1 @@
1
- {"version":3,"file":"hashing.d.mts","names":[],"sources":["../src/hashing.ts"],"mappings":";;;;KAqDY,sBAAA;EACV,MAAA;EACA,YAAA;EACA,OAAA,EAAS,MAAA;EAAA,SACA,mBAAA,GAAsB,sBAAA;EAAA,SACtB,WAAA,GAAc,WAAA;AAAA;AAAA,iBAGT,kBAAA,CAAmB,IAAA,EAAM,sBAAA,GAAyB,eAAe;AAAA,iBAIjE,oBAAA,CAAqB,IAAA;EACnC,MAAA;EACA,YAAA;EACA,SAAA,EAAW,MAAA;AAAA,IACT,iBAAiB;AAAA,iBAIL,kBAAA,CAAmB,IAAA;EACjC,MAAA;EACA,YAAA;EACA,YAAA,EAAc,MAAA,SAAe,MAAA;AAAA,IAC3B,eAAA"}
1
+ {"version":3,"file":"hashing.d.mts","names":[],"sources":["../src/hashing.ts"],"mappings":";;;;KA4EY,sBAAA;EACV,MAAA;EACA,YAAA;EACA,OAAA,EAAS,MAAA;EAAA,SACA,mBAAA,GAAsB,sBAAA;EAAA,SACtB,WAAA,GAAc,WAAA;AAAA;AAAA,iBAGT,kBAAA,CAAmB,IAAA,EAAM,sBAAA,GAAyB,eAAe;AAAA,iBAMjE,oBAAA,CAAqB,IAAA;EACnC,MAAA;EACA,YAAA;EACA,SAAA,EAAW,MAAA;AAAA,IACT,iBAAiB;AAAA,iBAML,kBAAA,CAAmB,IAAA;EACjC,MAAA;EACA,YAAA;EACA,YAAA,EAAc,MAAA,SAAe,MAAA;AAAA,IAC3B,eAAA"}
package/dist/hashing.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { n as matchesPathPattern } from "./canonicalization-path-match-b2jFuEso.mjs";
1
+ import { n as matchesPathPattern } from "./canonicalization-path-match-CNgHuwM_.mjs";
2
+ import { blindCast, castAs } from "@prisma-next/utils/casts";
2
3
  import { isArrayEqual } from "@prisma-next/utils/array-equal";
3
4
  import { ifDefined } from "@prisma-next/utils/defined";
4
5
  import { createHash } from "node:crypto";
@@ -30,6 +31,12 @@ const DOMAIN_MODEL_STORAGE_PATTERN = [
30
31
  "*",
31
32
  "storage"
32
33
  ];
34
+ const STORAGE_NAMESPACE_ENTRIES_PATTERN = [
35
+ "storage",
36
+ "namespaces",
37
+ "*",
38
+ "entries"
39
+ ];
33
40
  const TOP_LEVEL_ORDER = [
34
41
  "schemaVersion",
35
42
  "canonicalVersion",
@@ -42,6 +49,7 @@ const TOP_LEVEL_ORDER = [
42
49
  "execution",
43
50
  "capabilities",
44
51
  "extensionPacks",
52
+ "defaultControlPolicy",
45
53
  "meta"
46
54
  ];
47
55
  function isDefaultValue(value) {
@@ -65,7 +73,7 @@ function omitDefaults(obj, path, shouldPreserveEmpty) {
65
73
  const isDomainNamespaceSlot = matchesPathPattern(currentPath, DOMAIN_NAMESPACE_SLOT_PATTERN);
66
74
  const isRequiredDomainModels = matchesPathPattern(currentPath, DOMAIN_MODELS_CONTAINER_PATTERN);
67
75
  const isRequiredStorageNamespaces = isArrayEqual(currentPath, ["storage", "namespaces"]);
68
- const isStorageNamespaceSlot = currentPath.length === 3 && isArrayEqual([currentPath[0], currentPath[1]], ["storage", "namespaces"]);
76
+ const isStorageNamespaceEntries = matchesPathPattern(currentPath, STORAGE_NAMESPACE_ENTRIES_PATTERN);
69
77
  const isRequiredRoots = isArrayEqual(currentPath, ["roots"]);
70
78
  const isRequiredExtensionPacks = isArrayEqual(currentPath, ["extensionPacks"]);
71
79
  const isRequiredCapabilities = isArrayEqual(currentPath, ["capabilities"]);
@@ -80,7 +88,7 @@ function omitDefaults(obj, path, shouldPreserveEmpty) {
80
88
  const isModelStorage = matchesPathPattern(currentPath, DOMAIN_MODEL_STORAGE_PATTERN);
81
89
  const isNullableField = key === "nullable";
82
90
  const isFamilyPreserved = shouldPreserveEmpty?.(currentPath) ?? false;
83
- if (!isRequiredDomainNamespaces && !isDomainNamespaceSlot && !isRequiredDomainModels && !isRequiredStorageNamespaces && !isStorageNamespaceSlot && !isRequiredRoots && !isRequiredExtensionPacks && !isRequiredCapabilities && !isRequiredMeta && !isRequiredExecutionDefaults && !isExtensionNamespace && !isModelRelations && !isModelStorage && !isNullableField && !isFamilyPreserved) continue;
91
+ if (!isRequiredDomainNamespaces && !isDomainNamespaceSlot && !isRequiredDomainModels && !isRequiredStorageNamespaces && !isStorageNamespaceEntries && !isRequiredRoots && !isRequiredExtensionPacks && !isRequiredCapabilities && !isRequiredMeta && !isRequiredExecutionDefaults && !isExtensionNamespace && !isModelRelations && !isModelStorage && !isNullableField && !isFamilyPreserved) continue;
84
92
  }
85
93
  result[key] = omitDefaults(value, currentPath, shouldPreserveEmpty);
86
94
  }
@@ -122,6 +130,7 @@ function canonicalizeContractToObject(contract, options) {
122
130
  ...ifDefined("execution", serialized["execution"]),
123
131
  extensionPacks: serialized["extensionPacks"],
124
132
  capabilities: serialized["capabilities"],
133
+ ...ifDefined("defaultControlPolicy", serialized["defaultControlPolicy"]),
125
134
  meta: serialized["meta"]
126
135
  }, [], options.shouldPreserveEmpty);
127
136
  return orderTopLevel(sortObjectKeys(options.sortStorage ? {
@@ -135,6 +144,23 @@ function canonicalizeContract(contract, options) {
135
144
  //#endregion
136
145
  //#region src/hashing.ts
137
146
  const SCHEMA_VERSION = "1";
147
+ function isPlainRecord(value) {
148
+ return value !== null && typeof value === "object" && !Array.isArray(value);
149
+ }
150
+ function omitNamespaceKindsForHash(storage) {
151
+ if (!isPlainRecord(storage)) return storage;
152
+ const namespaces = storage["namespaces"];
153
+ if (!isPlainRecord(namespaces)) return storage;
154
+ const stripped = {};
155
+ for (const [nsId, ns] of Object.entries(namespaces)) if (isPlainRecord(ns)) {
156
+ const { kind: _kind, ...rest } = ns;
157
+ stripped[nsId] = rest;
158
+ } else stripped[nsId] = ns;
159
+ return {
160
+ ...storage,
161
+ namespaces: stripped
162
+ };
163
+ }
138
164
  function sha256(content) {
139
165
  const hash = createHash("sha256");
140
166
  hash.update(content);
@@ -142,33 +168,34 @@ function sha256(content) {
142
168
  }
143
169
  function hashContract(section) {
144
170
  const { shouldPreserveEmpty, sortStorage, ...sectionData } = section;
145
- return canonicalizeContract({
171
+ const storageForHash = omitNamespaceKindsForHash(sectionData["storage"] ?? {});
172
+ return canonicalizeContract(blindCast({
146
173
  targetFamily: sectionData["targetFamily"],
147
174
  target: sectionData["target"],
148
175
  roots: {},
149
176
  domain: { namespaces: {} },
150
- storage: sectionData["storage"] ?? {},
151
177
  execution: sectionData["execution"],
152
178
  extensionPacks: {},
153
179
  capabilities: sectionData["capabilities"] ?? {},
154
180
  meta: {},
155
181
  profileHash: "",
156
- ...sectionData
157
- }, {
182
+ ...sectionData,
183
+ storage: storageForHash
184
+ }), {
158
185
  schemaVersion: SCHEMA_VERSION,
159
- serializeContract: (c) => JSON.parse(JSON.stringify(c)),
186
+ serializeContract: (c) => castAs(JSON.parse(JSON.stringify(c))),
160
187
  ...ifDefined("shouldPreserveEmpty", shouldPreserveEmpty),
161
188
  ...ifDefined("sortStorage", sortStorage)
162
189
  });
163
190
  }
164
191
  function computeStorageHash(args) {
165
- return sha256(hashContract(args));
192
+ return blindCast(sha256(hashContract(args)));
166
193
  }
167
194
  function computeExecutionHash(args) {
168
- return sha256(hashContract(args));
195
+ return blindCast(sha256(hashContract(args)));
169
196
  }
170
197
  function computeProfileHash(args) {
171
- return sha256(hashContract(args));
198
+ return blindCast(sha256(hashContract(args)));
172
199
  }
173
200
  //#endregion
174
201
  export { canonicalizeContract, canonicalizeContractToObject, computeExecutionHash, computeProfileHash, computeStorageHash };
@@ -1 +1 @@
1
- {"version":3,"file":"hashing.mjs","names":[],"sources":["../src/canonicalization.ts","../src/hashing.ts"],"sourcesContent":["import { isArrayEqual } from '@prisma-next/utils/array-equal';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport { matchesPathPattern, type PathPattern } from './canonicalization-path-match';\nimport type { Contract } from './contract-types';\n\n/**\n * Per-target contract serializer hook. The framework canonicalizer uses\n * this to convert an in-memory contract (which may carry class-instance\n * IR nodes whose runtime-only fields must not appear in the on-disk\n * envelope) into a plain JsonObject before applying the family-agnostic\n * canonical-key ordering / default-omission / sort steps. Targets whose\n * contract is JSON-clean by construction return the contract unchanged.\n */\nexport type SerializeContract = (contract: Contract) => JsonObject;\n\n/**\n * Family-contributed predicate for the default-omission walk. Called when\n * a value at `path` is a default (empty object/array or `false`); if this\n * returns `true` the value is kept rather than stripped.\n *\n * The framework only calls the predicate inside the `isDefaultValue` branch,\n * so there is no need to guard against non-default values.\n */\nexport type PreserveEmptyPredicate = (path: readonly string[]) => boolean;\n\n/**\n * Family-contributed storage sort. Applied to the serialized `storage`\n * subtree after the default-omission walk; the result replaces the\n * `storage` field before the final key sort. Use to establish a\n * deterministic order for storage arrays (indexes, uniques) that the\n * family-agnostic `sortObjectKeys` pass cannot handle.\n */\nexport type StorageSort = (storage: unknown) => unknown;\n\nconst DOMAIN_NAMESPACE_SLOT_PATTERN = ['domain', 'namespaces', '*'] as const satisfies PathPattern;\nconst DOMAIN_MODELS_CONTAINER_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n] as const satisfies PathPattern;\nconst DOMAIN_MODEL_RELATIONS_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n '*',\n 'relations',\n] as const satisfies PathPattern;\nconst DOMAIN_MODEL_STORAGE_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n '*',\n 'storage',\n] as const satisfies PathPattern;\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'profileHash',\n 'roots',\n 'domain',\n 'storage',\n 'execution',\n 'capabilities',\n 'extensionPacks',\n 'meta',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(\n obj: unknown,\n path: readonly string[],\n shouldPreserveEmpty: PreserveEmptyPredicate | undefined,\n): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path, shouldPreserveEmpty));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n if ((key === 'onDelete' || key === 'onUpdate') && value === 'noAction') {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredDomainNamespaces = isArrayEqual(currentPath, ['domain', 'namespaces']);\n const isDomainNamespaceSlot = matchesPathPattern(currentPath, DOMAIN_NAMESPACE_SLOT_PATTERN);\n const isRequiredDomainModels = matchesPathPattern(\n currentPath,\n DOMAIN_MODELS_CONTAINER_PATTERN,\n );\n const isRequiredStorageNamespaces = isArrayEqual(currentPath, ['storage', 'namespaces']);\n const isStorageNamespaceSlot =\n currentPath.length === 3 &&\n isArrayEqual([currentPath[0], currentPath[1]], ['storage', 'namespaces']);\n const isRequiredRoots = isArrayEqual(currentPath, ['roots']);\n const isRequiredExtensionPacks = isArrayEqual(currentPath, ['extensionPacks']);\n const isRequiredCapabilities = isArrayEqual(currentPath, ['capabilities']);\n const isRequiredMeta = isArrayEqual(currentPath, ['meta']);\n const isRequiredExecutionDefaults = isArrayEqual(currentPath, [\n 'execution',\n 'mutations',\n 'defaults',\n ]);\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensionPacks';\n const isModelRelations = matchesPathPattern(currentPath, DOMAIN_MODEL_RELATIONS_PATTERN);\n const isModelStorage = matchesPathPattern(currentPath, DOMAIN_MODEL_STORAGE_PATTERN);\n\n const isNullableField = key === 'nullable';\n\n const isFamilyPreserved = shouldPreserveEmpty?.(currentPath) ?? false;\n\n if (\n !isRequiredDomainNamespaces &&\n !isDomainNamespaceSlot &&\n !isRequiredDomainModels &&\n !isRequiredStorageNamespaces &&\n !isStorageNamespaceSlot &&\n !isRequiredRoots &&\n !isRequiredExtensionPacks &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredExecutionDefaults &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isModelStorage &&\n !isNullableField &&\n !isFamilyPreserved\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath, shouldPreserveEmpty);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\nexport function orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport interface CanonicalizeContractOptions {\n readonly schemaVersion?: string;\n /**\n * Per-target hook that converts the in-memory contract (which may\n * carry class-instance IR nodes) into a plain JsonObject before the\n * family-agnostic canonicalization steps run.\n *\n * Routing through the hook is what lets each target decide which\n * fields appear in the on-disk envelope; runtime-only class API\n * fields stay invisible to the canonicalization walk by virtue of\n * the per-target serializer not putting them in the JSON shape.\n */\n readonly serializeContract: SerializeContract;\n /**\n * Family-contributed preserve-empty predicate. When the walk encounters a\n * default value (empty object/array or `false`) at `path`, calling this\n * with the full path allows the family to veto the omission. If absent,\n * only the framework's family-agnostic required-slot rules apply.\n */\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n /**\n * Family-contributed storage sort. Applied to the serialized `storage`\n * subtree after the default-omission walk, before the final key sort.\n * SQL family uses this to impose a deterministic order on `indexes` and\n * `uniques` arrays within each namespace table. Families that require no\n * special storage ordering omit this hook.\n */\n readonly sortStorage?: StorageSort;\n}\n\n/**\n * Object-form variant of {@link canonicalizeContract}. Exported because the\n * emitter writes the canonical contract through a separate JSON-stringify\n * pass and consumes the structured object directly.\n */\nexport function canonicalizeContractToObject(\n contract: Contract,\n options: CanonicalizeContractOptions,\n): Record<string, unknown> {\n const serialized = options.serializeContract(contract);\n const normalized: Record<string, unknown> = {\n ...ifDefined('schemaVersion', options.schemaVersion),\n targetFamily: serialized['targetFamily'],\n target: serialized['target'],\n profileHash: serialized['profileHash'],\n roots: serialized['roots'],\n domain: serialized['domain'],\n storage: serialized['storage'],\n ...ifDefined('execution', serialized['execution']),\n extensionPacks: serialized['extensionPacks'],\n capabilities: serialized['capabilities'],\n meta: serialized['meta'],\n };\n const withDefaultsOmitted = omitDefaults(normalized, [], options.shouldPreserveEmpty) as Record<\n string,\n unknown\n >;\n const withSortedStorage = options.sortStorage\n ? { ...withDefaultsOmitted, storage: options.sortStorage(withDefaultsOmitted['storage']) }\n : withDefaultsOmitted;\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n return orderTopLevel(withSortedKeys);\n}\n\nexport function canonicalizeContract(\n contract: Contract,\n options: CanonicalizeContractOptions,\n): string {\n return JSON.stringify(canonicalizeContractToObject(contract, options), null, 2);\n}\n","import { createHash } from 'node:crypto';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport {\n canonicalizeContract,\n type PreserveEmptyPredicate,\n type StorageSort,\n} from './canonicalization';\nimport type { Contract } from './contract-types';\nimport type { ExecutionHashBase, ProfileHashBase, StorageHashBase } from './types';\n\nconst SCHEMA_VERSION = '1';\n\nfunction sha256(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\ntype HashContractSection = Record<string, unknown> & {\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n readonly sortStorage?: StorageSort;\n};\n\nfunction hashContract(section: HashContractSection): string {\n const { shouldPreserveEmpty, sortStorage, ...sectionData } = section;\n // Blind cast: the synthesised object is a hash-only stand-in\n // — never returned to callers, never executed as a Contract.\n // `canonicalizeContract` only walks the storage / execution /\n // capabilities slices, all of which are populated above, so the\n // missing precise Contract typing on the other slots is\n // immaterial for the hash result.\n const contract = {\n targetFamily: sectionData['targetFamily'],\n target: sectionData['target'],\n roots: {},\n domain: { namespaces: {} },\n storage: sectionData['storage'] ?? {},\n execution: sectionData['execution'],\n extensionPacks: {},\n capabilities: sectionData['capabilities'] ?? {},\n meta: {},\n profileHash: '',\n ...sectionData,\n } as unknown as Contract;\n return canonicalizeContract(contract, {\n schemaVersion: SCHEMA_VERSION,\n serializeContract: (c) => JSON.parse(JSON.stringify(c)) as JsonObject,\n ...ifDefined('shouldPreserveEmpty', shouldPreserveEmpty),\n ...ifDefined('sortStorage', sortStorage),\n });\n}\n\nexport type ComputeStorageHashArgs = {\n target: string;\n targetFamily: string;\n storage: Record<string, unknown>;\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n readonly sortStorage?: StorageSort;\n};\n\nexport function computeStorageHash(args: ComputeStorageHashArgs): StorageHashBase<string> {\n return sha256(hashContract(args)) as StorageHashBase<string>;\n}\n\nexport function computeExecutionHash(args: {\n target: string;\n targetFamily: string;\n execution: Record<string, unknown>;\n}): ExecutionHashBase<string> {\n return sha256(hashContract(args)) as ExecutionHashBase<string>;\n}\n\nexport function computeProfileHash(args: {\n target: string;\n targetFamily: string;\n capabilities: Record<string, Record<string, boolean>>;\n}): ProfileHashBase<string> {\n return sha256(hashContract(args)) as ProfileHashBase<string>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"hashing.mjs","names":[],"sources":["../src/canonicalization.ts","../src/hashing.ts"],"sourcesContent":["import { isArrayEqual } from '@prisma-next/utils/array-equal';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport { matchesPathPattern, type PathPattern } from './canonicalization-path-match';\nimport type { Contract } from './contract-types';\n\n/**\n * Per-target contract serializer hook. The framework canonicalizer uses\n * this to convert an in-memory contract (which may carry class-instance\n * IR nodes whose runtime-only fields must not appear in the on-disk\n * envelope) into a plain JsonObject before applying the family-agnostic\n * canonical-key ordering / default-omission / sort steps. Targets whose\n * contract is JSON-clean by construction return the contract unchanged.\n */\nexport type SerializeContract = (contract: Contract) => JsonObject;\n\n/**\n * Family-contributed predicate for the default-omission walk. Called when\n * a value at `path` is a default (empty object/array or `false`); if this\n * returns `true` the value is kept rather than stripped.\n *\n * The framework only calls the predicate inside the `isDefaultValue` branch,\n * so there is no need to guard against non-default values.\n */\nexport type PreserveEmptyPredicate = (path: readonly string[]) => boolean;\n\n/**\n * Family-contributed storage sort. Applied to the serialized `storage`\n * subtree after the default-omission walk; the result replaces the\n * `storage` field before the final key sort. Use to establish a\n * deterministic order for storage arrays (indexes, uniques) that the\n * family-agnostic `sortObjectKeys` pass cannot handle.\n */\nexport type StorageSort = (storage: unknown) => unknown;\n\nconst DOMAIN_NAMESPACE_SLOT_PATTERN = ['domain', 'namespaces', '*'] as const satisfies PathPattern;\nconst DOMAIN_MODELS_CONTAINER_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n] as const satisfies PathPattern;\nconst DOMAIN_MODEL_RELATIONS_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n '*',\n 'relations',\n] as const satisfies PathPattern;\nconst DOMAIN_MODEL_STORAGE_PATTERN = [\n 'domain',\n 'namespaces',\n '*',\n 'models',\n '*',\n 'storage',\n] as const satisfies PathPattern;\nconst STORAGE_NAMESPACE_ENTRIES_PATTERN = [\n 'storage',\n 'namespaces',\n '*',\n 'entries',\n] as const satisfies PathPattern;\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'profileHash',\n 'roots',\n 'domain',\n 'storage',\n 'execution',\n 'capabilities',\n 'extensionPacks',\n 'defaultControlPolicy',\n 'meta',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(\n obj: unknown,\n path: readonly string[],\n shouldPreserveEmpty: PreserveEmptyPredicate | undefined,\n): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path, shouldPreserveEmpty));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n if ((key === 'onDelete' || key === 'onUpdate') && value === 'noAction') {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredDomainNamespaces = isArrayEqual(currentPath, ['domain', 'namespaces']);\n const isDomainNamespaceSlot = matchesPathPattern(currentPath, DOMAIN_NAMESPACE_SLOT_PATTERN);\n const isRequiredDomainModels = matchesPathPattern(\n currentPath,\n DOMAIN_MODELS_CONTAINER_PATTERN,\n );\n const isRequiredStorageNamespaces = isArrayEqual(currentPath, ['storage', 'namespaces']);\n const isStorageNamespaceEntries = matchesPathPattern(\n currentPath,\n STORAGE_NAMESPACE_ENTRIES_PATTERN,\n );\n const isRequiredRoots = isArrayEqual(currentPath, ['roots']);\n const isRequiredExtensionPacks = isArrayEqual(currentPath, ['extensionPacks']);\n const isRequiredCapabilities = isArrayEqual(currentPath, ['capabilities']);\n const isRequiredMeta = isArrayEqual(currentPath, ['meta']);\n const isRequiredExecutionDefaults = isArrayEqual(currentPath, [\n 'execution',\n 'mutations',\n 'defaults',\n ]);\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensionPacks';\n const isModelRelations = matchesPathPattern(currentPath, DOMAIN_MODEL_RELATIONS_PATTERN);\n const isModelStorage = matchesPathPattern(currentPath, DOMAIN_MODEL_STORAGE_PATTERN);\n\n const isNullableField = key === 'nullable';\n\n const isFamilyPreserved = shouldPreserveEmpty?.(currentPath) ?? false;\n\n if (\n !isRequiredDomainNamespaces &&\n !isDomainNamespaceSlot &&\n !isRequiredDomainModels &&\n !isRequiredStorageNamespaces &&\n !isStorageNamespaceEntries &&\n !isRequiredRoots &&\n !isRequiredExtensionPacks &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredExecutionDefaults &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isModelStorage &&\n !isNullableField &&\n !isFamilyPreserved\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath, shouldPreserveEmpty);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\nexport function orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport interface CanonicalizeContractOptions {\n readonly schemaVersion?: string;\n /**\n * Per-target hook that converts the in-memory contract (which may\n * carry class-instance IR nodes) into a plain JsonObject before the\n * family-agnostic canonicalization steps run.\n *\n * Routing through the hook is what lets each target decide which\n * fields appear in the on-disk envelope; runtime-only class API\n * fields stay invisible to the canonicalization walk by virtue of\n * the per-target serializer not putting them in the JSON shape.\n */\n readonly serializeContract: SerializeContract;\n /**\n * Family-contributed preserve-empty predicate. When the walk encounters a\n * default value (empty object/array or `false`) at `path`, calling this\n * with the full path allows the family to veto the omission. If absent,\n * only the framework's family-agnostic required-slot rules apply.\n */\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n /**\n * Family-contributed storage sort. Applied to the serialized `storage`\n * subtree after the default-omission walk, before the final key sort.\n * SQL family uses this to impose a deterministic order on `indexes` and\n * `uniques` arrays within each namespace table. Families that require no\n * special storage ordering omit this hook.\n */\n readonly sortStorage?: StorageSort;\n}\n\n/**\n * Object-form variant of {@link canonicalizeContract}. Exported because the\n * emitter writes the canonical contract through a separate JSON-stringify\n * pass and consumes the structured object directly.\n */\nexport function canonicalizeContractToObject(\n contract: Contract,\n options: CanonicalizeContractOptions,\n): Record<string, unknown> {\n const serialized = options.serializeContract(contract);\n const normalized: Record<string, unknown> = {\n ...ifDefined('schemaVersion', options.schemaVersion),\n targetFamily: serialized['targetFamily'],\n target: serialized['target'],\n profileHash: serialized['profileHash'],\n roots: serialized['roots'],\n domain: serialized['domain'],\n storage: serialized['storage'],\n ...ifDefined('execution', serialized['execution']),\n extensionPacks: serialized['extensionPacks'],\n capabilities: serialized['capabilities'],\n ...ifDefined('defaultControlPolicy', serialized['defaultControlPolicy']),\n meta: serialized['meta'],\n };\n const withDefaultsOmitted = omitDefaults(normalized, [], options.shouldPreserveEmpty) as Record<\n string,\n unknown\n >;\n const withSortedStorage = options.sortStorage\n ? { ...withDefaultsOmitted, storage: options.sortStorage(withDefaultsOmitted['storage']) }\n : withDefaultsOmitted;\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n return orderTopLevel(withSortedKeys);\n}\n\nexport function canonicalizeContract(\n contract: Contract,\n options: CanonicalizeContractOptions,\n): string {\n return JSON.stringify(canonicalizeContractToObject(contract, options), null, 2);\n}\n","import { createHash } from 'node:crypto';\nimport { blindCast, castAs } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport {\n canonicalizeContract,\n type PreserveEmptyPredicate,\n type StorageSort,\n} from './canonicalization';\nimport type { Contract } from './contract-types';\nimport type { ExecutionHashBase, ProfileHashBase, StorageHashBase } from './types';\n\nconst SCHEMA_VERSION = '1';\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n// Storage hashes fingerprint table/column layout, not which target pack emitted a\n// namespace. Persisted contract.json carries namespace `kind` discriminators;\n// authoring-time hashes never included them (IR `kind` is non-enumerable).\nfunction omitNamespaceKindsForHash(storage: unknown): unknown {\n if (!isPlainRecord(storage)) {\n return storage;\n }\n const namespaces = storage['namespaces'];\n if (!isPlainRecord(namespaces)) {\n return storage;\n }\n const stripped: Record<string, unknown> = {};\n for (const [nsId, ns] of Object.entries(namespaces)) {\n if (isPlainRecord(ns)) {\n const { kind: _kind, ...rest } = ns;\n stripped[nsId] = rest;\n } else {\n stripped[nsId] = ns;\n }\n }\n return { ...storage, namespaces: stripped };\n}\n\nfunction sha256(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\ntype HashContractSection = Record<string, unknown> & {\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n readonly sortStorage?: StorageSort;\n};\n\nfunction hashContract(section: HashContractSection): string {\n const { shouldPreserveEmpty, sortStorage, ...sectionData } = section;\n const storageForHash = omitNamespaceKindsForHash(sectionData['storage'] ?? {});\n const contract = blindCast<Contract, 'hash-only partial contract for canonicalizeContract'>({\n targetFamily: sectionData['targetFamily'],\n target: sectionData['target'],\n roots: {},\n domain: { namespaces: {} },\n execution: sectionData['execution'],\n extensionPacks: {},\n capabilities: sectionData['capabilities'] ?? {},\n meta: {},\n profileHash: '',\n ...sectionData,\n storage: storageForHash,\n });\n return canonicalizeContract(contract, {\n schemaVersion: SCHEMA_VERSION,\n serializeContract: (c) => castAs<JsonObject>(JSON.parse(JSON.stringify(c))),\n ...ifDefined('shouldPreserveEmpty', shouldPreserveEmpty),\n ...ifDefined('sortStorage', sortStorage),\n });\n}\n\nexport type ComputeStorageHashArgs = {\n target: string;\n targetFamily: string;\n storage: Record<string, unknown>;\n readonly shouldPreserveEmpty?: PreserveEmptyPredicate;\n readonly sortStorage?: StorageSort;\n};\n\nexport function computeStorageHash(args: ComputeStorageHashArgs): StorageHashBase<string> {\n return blindCast<StorageHashBase<string>, 'sha256 digest of canonicalized storage'>(\n sha256(hashContract(args)),\n );\n}\n\nexport function computeExecutionHash(args: {\n target: string;\n targetFamily: string;\n execution: Record<string, unknown>;\n}): ExecutionHashBase<string> {\n return blindCast<ExecutionHashBase<string>, 'sha256 digest of canonicalized execution'>(\n sha256(hashContract(args)),\n );\n}\n\nexport function computeProfileHash(args: {\n target: string;\n targetFamily: string;\n capabilities: Record<string, Record<string, boolean>>;\n}): ProfileHashBase<string> {\n return blindCast<ProfileHashBase<string>, 'sha256 digest of canonicalized profile'>(\n sha256(hashContract(args)),\n );\n}\n"],"mappings":"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"}
@@ -6,4 +6,4 @@ function asNamespaceId(value) {
6
6
  //#endregion
7
7
  export { asNamespaceId as t };
8
8
 
9
- //# sourceMappingURL=namespace-id-CVpkSFUK.mjs.map
9
+ //# sourceMappingURL=namespace-id-CUxYd4KL.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-id-CVpkSFUK.mjs","names":[],"sources":["../src/namespace-id.ts"],"sourcesContent":["import { blindCast } from '@prisma-next/utils/casts';\n\nexport type NamespaceId = string & { readonly __brand: 'NamespaceId' };\n\nexport function asNamespaceId(value: string): NamespaceId {\n return blindCast<\n NamespaceId,\n 'NamespaceId is a compile-time-only brand on string; this factory is the sole assertion site'\n >(value);\n}\n"],"mappings":";;AAIA,SAAgB,cAAc,OAA4B;CACxD,OAAO,UAGL,KAAK;AACT"}
1
+ {"version":3,"file":"namespace-id-CUxYd4KL.mjs","names":[],"sources":["../src/namespace-id.ts"],"sourcesContent":["import { blindCast } from '@prisma-next/utils/casts';\n\nexport type NamespaceId = string & { readonly __brand: 'NamespaceId' };\n\nexport function asNamespaceId(value: string): NamespaceId {\n return blindCast<\n NamespaceId,\n 'NamespaceId is a compile-time-only brand on string; this factory is the sole assertion site'\n >(value);\n}\n"],"mappings":";;AAIA,SAAgB,cAAc,OAA4B;CACxD,OAAO,UAGL,KAAK;AACT"}
@@ -0,0 +1,20 @@
1
+ //#region src/resolve-domain-model.ts
2
+ /**
3
+ * Resolve a bare domain model name to its namespace coordinate and model IR by
4
+ * scanning the contract's namespaces. For the single-namespace contracts in
5
+ * scope the scan is exact; cross-namespace bare-name collisions are selected
6
+ * explicitly (TML-2550).
7
+ */
8
+ function resolveDomainModel(domain, modelName) {
9
+ for (const namespaceId of Object.keys(domain.namespaces)) {
10
+ const model = domain.namespaces[namespaceId]?.models[modelName];
11
+ if (model !== void 0) return {
12
+ namespaceId,
13
+ model
14
+ };
15
+ }
16
+ }
17
+ //#endregion
18
+ export { resolveDomainModel as t };
19
+
20
+ //# sourceMappingURL=resolve-domain-model-BovPAsW2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-domain-model-BovPAsW2.mjs","names":[],"sources":["../src/resolve-domain-model.ts"],"sourcesContent":["import type { ApplicationDomain } from './domain-envelope';\nimport type { ContractModelBase } from './domain-types';\n\nexport interface ResolvedDomainModel {\n readonly namespaceId: string;\n readonly model: ContractModelBase;\n}\n\n/**\n * Resolve a bare domain model name to its namespace coordinate and model IR by\n * scanning the contract's namespaces. For the single-namespace contracts in\n * scope the scan is exact; cross-namespace bare-name collisions are selected\n * explicitly (TML-2550).\n */\nexport function resolveDomainModel(\n domain: ApplicationDomain,\n modelName: string,\n): ResolvedDomainModel | undefined {\n for (const namespaceId of Object.keys(domain.namespaces)) {\n const model = domain.namespaces[namespaceId]?.models[modelName];\n if (model !== undefined) {\n return { namespaceId, model };\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;AAcA,SAAgB,mBACd,QACA,WACiC;CACjC,KAAK,MAAM,eAAe,OAAO,KAAK,OAAO,UAAU,GAAG;EACxD,MAAM,QAAQ,OAAO,WAAW,YAAY,EAAE,OAAO;EACrD,IAAI,UAAU,KAAA,GACZ,OAAO;GAAE;GAAa;EAAM;CAEhC;AAGF"}
@@ -0,0 +1,17 @@
1
+ import { d as ContractModelBase, t as ApplicationDomain } from "./domain-envelope-DKOnhO5d.mjs";
2
+
3
+ //#region src/resolve-domain-model.d.ts
4
+ interface ResolvedDomainModel {
5
+ readonly namespaceId: string;
6
+ readonly model: ContractModelBase;
7
+ }
8
+ /**
9
+ * Resolve a bare domain model name to its namespace coordinate and model IR by
10
+ * scanning the contract's namespaces. For the single-namespace contracts in
11
+ * scope the scan is exact; cross-namespace bare-name collisions are selected
12
+ * explicitly (TML-2550).
13
+ */
14
+ declare function resolveDomainModel(domain: ApplicationDomain, modelName: string): ResolvedDomainModel | undefined;
15
+ //#endregion
16
+ export { resolveDomainModel as n, ResolvedDomainModel as t };
17
+ //# sourceMappingURL=resolve-domain-model-CSEqpByI.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-domain-model-CSEqpByI.d.mts","names":[],"sources":["../src/resolve-domain-model.ts"],"mappings":";;;UAGiB,mBAAA;EAAA,SACN,WAAA;EAAA,SACA,KAAA,EAAO,iBAAiB;AAAA;;;;;;AAAA;iBASnB,kBAAA,CACd,MAAA,EAAQ,iBAAA,EACR,SAAA,WACC,mBAAmB"}
@@ -0,0 +1,2 @@
1
+ import { n as resolveDomainModel, t as ResolvedDomainModel } from "./resolve-domain-model-CSEqpByI.mjs";
2
+ export { type ResolvedDomainModel, resolveDomainModel };
@@ -0,0 +1,2 @@
1
+ import { t as resolveDomainModel } from "./resolve-domain-model-BovPAsW2.mjs";
2
+ export { resolveDomainModel };
package/dist/types.d.mts CHANGED
@@ -1,4 +1,21 @@
1
- import { r as DomainNamespaceResolutionError } from "./contract-validation-error-T5LH4DW-.mjs";
2
- import { C as UnionFieldType, D as crossRef, E as CrossReferenceSchema, O as NamespaceId, S as ScalarFieldType, T as CrossReference, _ as ContractValueObject, a as contractModels, b as ModelStorageBase, c as ContractDiscriminator, d as ContractFieldType, f as ContractModel, g as ContractRelationOn, h as ContractRelation, i as UNBOUND_DOMAIN_NAMESPACE_ID, k as asNamespaceId, l as ContractEmbedRelation, m as ContractReferenceRelation, n as ApplicationDomainNamespace, o as contractValueObjects, p as ContractModelBase, r as ContractWithDomain, s as resolveSingleDomainNamespaceId, t as ApplicationDomain, u as ContractField, v as ContractVariantEntry, w as ValueObjectFieldType, x as ReferenceRelationKeys, y as EmbedRelationKeys } from "./domain-envelope-4hyFtJ4_.mjs";
3
- import { A as coreHash, C as PlanMeta, D as StorageEntitySlot, E as StorageBase, F as profileHash, M as isColumnDefault, N as isColumnDefaultLiteralInputValue, O as StorageHashBase, P as isExecutionMutationDefaultValue, S as JsonValue, T as Source, _ as ExecutionSection, a as $, b as GeneratedValueSpec, c as ColumnDefaultLiteralInputValue, d as DocCollection, f as DocIndex, g as ExecutionMutationDefaultValue, h as ExecutionMutationDefaultPhases, i as ContractValueObjectsMap, j as executionHash, k as StorageNamespace, l as ColumnDefaultLiteralValue, m as ExecutionMutationDefault, n as ContractExecutionSection, o as Brand, p as ExecutionHashBase, r as ContractModelsMap, s as ColumnDefault, t as Contract, u as ContractMarkerRecord, v as Expr, w as ProfileHashBase, x as JsonPrimitive, y as FieldType } from "./contract-types-xgwKtd7y.mjs";
4
- export { type $, type ApplicationDomain, type ApplicationDomainNamespace, type Brand, type ColumnDefault, type ColumnDefaultLiteralInputValue, type ColumnDefaultLiteralValue, type Contract, type ContractDiscriminator, type ContractEmbedRelation, type ContractExecutionSection, type ContractField, type ContractFieldType, type ContractMarkerRecord, type ContractModel, type ContractModelBase, type ContractModelsMap, type ContractReferenceRelation, type ContractRelation, type ContractRelationOn, type ContractValueObject, type ContractValueObjectsMap, type ContractVariantEntry, type ContractWithDomain, type CrossReference, CrossReferenceSchema, type DocCollection, type DocIndex, DomainNamespaceResolutionError, type EmbedRelationKeys, type ExecutionHashBase, type ExecutionMutationDefault, type ExecutionMutationDefaultPhases, type ExecutionMutationDefaultValue, type ExecutionSection, type Expr, type FieldType, type GeneratedValueSpec, type JsonPrimitive, type JsonValue, type ModelStorageBase, type NamespaceId, type PlanMeta, type ProfileHashBase, type ReferenceRelationKeys, type ScalarFieldType, type Source, type StorageBase, type StorageEntitySlot, type StorageHashBase, type StorageNamespace, UNBOUND_DOMAIN_NAMESPACE_ID, type UnionFieldType, type ValueObjectFieldType, asNamespaceId, contractModels, contractValueObjects, coreHash, crossRef, executionHash, isColumnDefault, isColumnDefaultLiteralInputValue, isExecutionMutationDefaultValue, profileHash, resolveSingleDomainNamespaceId };
1
+ import { a as ControlPolicy, i as ContractValueObjectDefinitions, n as ContractExecutionSection, o as effectiveControlPolicy, r as ContractModelDefinitions, t as Contract } from "./contract-types-CtIh62PH.mjs";
2
+ import { $ as executionHash, A as ColumnDefaultLiteralValue, B as FieldType, C as UnionFieldType, D as Brand, E as $, F as ExecutionMutationDefault, G as PlanMeta, H as JsonPrimitive, I as ExecutionMutationDefaultPhases, J as StorageBase, K as ProfileHashBase, L as ExecutionMutationDefaultValue, M as DocCollection, N as DocIndex, O as ColumnDefault, P as ExecutionHashBase, Q as coreHash, R as ExecutionSection, S as ScalarFieldType, T as ValueSetRef, U as JsonValue, V as GeneratedValueSpec, W as LedgerEntryRecord, X as StorageHashBase, Y as StorageEntitySlot, Z as StorageNamespace, _ as ContractValueObject, a as ContractEmbedRelation, at as CrossReferenceSchema, b as ModelStorageBase, c as ContractFieldType, ct as asNamespaceId, d as ContractModelBase, et as isColumnDefault, f as ContractNonJunctionRelation, g as ContractRelationThrough, h as ContractRelationOn, i as ContractDiscriminator, it as CrossReference, j as ContractMarkerRecord, k as ColumnDefaultLiteralInputValue, l as ContractManyToManyRelation, m as ContractRelation, n as ApplicationDomainNamespace, nt as isExecutionMutationDefaultValue, o as ContractEnum, ot as crossRef, p as ContractReferenceRelation, q as Source, r as ContractWithDomain, rt as profileHash, s as ContractField, st as NamespaceId, t as ApplicationDomain, tt as isColumnDefaultLiteralInputValue, u as ContractModel, v as ContractVariantEntry, w as ValueObjectFieldType, x as ReferenceRelationKeys, y as EmbedRelationKeys, z as Expr } from "./domain-envelope-DKOnhO5d.mjs";
3
+ import { n as soleDomainNamespaceId, t as UNBOUND_DOMAIN_NAMESPACE_ID } from "./default-namespace-D5X_k6hJ.mjs";
4
+ import { r as DomainNamespaceResolutionError } from "./contract-validation-error-D7g0kmcc.mjs";
5
+ import { n as resolveDomainModel, t as ResolvedDomainModel } from "./resolve-domain-model-CSEqpByI.mjs";
6
+
7
+ //#region src/domain-namespace-access.d.ts
8
+ /**
9
+ * Models map for the contract's single domain namespace. Throws when the
10
+ * contract does not declare exactly one namespace — bare-name access is
11
+ * ambiguous across namespaces and must be qualified explicitly (TML-2550).
12
+ */
13
+ declare function domainModelsAtDefaultNamespace<TModels extends Record<string, ContractModelBase>>(domain: ApplicationDomain<TModels>): TModels;
14
+ /**
15
+ * Value objects for the contract's single domain namespace, when present.
16
+ * Throws when the contract does not declare exactly one namespace.
17
+ */
18
+ declare function domainValueObjectsAtDefaultNamespace<TModels extends Record<string, ContractModelBase>>(domain: ApplicationDomain<TModels>): Record<string, ContractValueObject> | undefined;
19
+ //#endregion
20
+ export { type $, type ApplicationDomain, type ApplicationDomainNamespace, type Brand, type ColumnDefault, type ColumnDefaultLiteralInputValue, type ColumnDefaultLiteralValue, type Contract, type ContractDiscriminator, type ContractEmbedRelation, type ContractEnum, type ContractExecutionSection, type ContractField, type ContractFieldType, type ContractManyToManyRelation, type ContractMarkerRecord, type ContractModel, type ContractModelBase, type ContractModelDefinitions, type ContractNonJunctionRelation, type ContractReferenceRelation, type ContractRelation, type ContractRelationOn, type ContractRelationThrough, type ContractValueObject, type ContractValueObjectDefinitions, type ContractVariantEntry, type ContractWithDomain, type ControlPolicy, type CrossReference, CrossReferenceSchema, type DocCollection, type DocIndex, DomainNamespaceResolutionError, type EmbedRelationKeys, type ExecutionHashBase, type ExecutionMutationDefault, type ExecutionMutationDefaultPhases, type ExecutionMutationDefaultValue, type ExecutionSection, type Expr, type FieldType, type GeneratedValueSpec, type JsonPrimitive, type JsonValue, type LedgerEntryRecord, type ModelStorageBase, type NamespaceId, type PlanMeta, type ProfileHashBase, type ReferenceRelationKeys, type ResolvedDomainModel, type ScalarFieldType, type Source, type StorageBase, type StorageEntitySlot, type StorageHashBase, type StorageNamespace, UNBOUND_DOMAIN_NAMESPACE_ID, type UnionFieldType, type ValueObjectFieldType, type ValueSetRef, asNamespaceId, coreHash, crossRef, domainModelsAtDefaultNamespace, domainValueObjectsAtDefaultNamespace, effectiveControlPolicy, executionHash, isColumnDefault, isColumnDefaultLiteralInputValue, isExecutionMutationDefaultValue, profileHash, resolveDomainModel, soleDomainNamespaceId };
21
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../src/domain-namespace-access.ts"],"mappings":";;;;;;;;;;;;iBAUgB,8BAAA,iBAA+C,MAAA,SAAe,iBAAA,GAC5E,MAAA,EAAQ,iBAAA,CAAkB,OAAA,IACzB,OAAA;;;;;iBAea,oCAAA,iBACE,MAAA,SAAe,iBAAA,GAC/B,MAAA,EAAQ,iBAAA,CAAkB,OAAA,IAAW,MAAA,SAAe,mBAAA"}