@prisma-next/contract 0.11.0 → 0.12.0

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 (62) hide show
  1. package/dist/canonicalization-DFE0HJkI.d.mts +69 -0
  2. package/dist/canonicalization-DFE0HJkI.d.mts.map +1 -0
  3. package/dist/canonicalization-path-match-b2jFuEso.mjs +25 -0
  4. package/dist/canonicalization-path-match-b2jFuEso.mjs.map +1 -0
  5. package/dist/{contract-types-Bt2uyqs3.d.mts → contract-types-xgwKtd7y.d.mts} +34 -74
  6. package/dist/contract-types-xgwKtd7y.d.mts.map +1 -0
  7. package/dist/contract-validation-error-ClZaKqMW.mjs +20 -0
  8. package/dist/contract-validation-error-ClZaKqMW.mjs.map +1 -0
  9. package/dist/contract-validation-error-T5LH4DW-.d.mts +13 -0
  10. package/dist/contract-validation-error-T5LH4DW-.d.mts.map +1 -0
  11. package/dist/contract-validation-error.d.mts +2 -10
  12. package/dist/contract-validation-error.mjs +2 -2
  13. package/dist/domain-envelope-4hyFtJ4_.d.mts +110 -0
  14. package/dist/domain-envelope-4hyFtJ4_.d.mts.map +1 -0
  15. package/dist/hashing-utils.d.mts +19 -0
  16. package/dist/hashing-utils.d.mts.map +1 -0
  17. package/dist/hashing-utils.mjs +50 -0
  18. package/dist/hashing-utils.mjs.map +1 -0
  19. package/dist/hashing.d.mts +8 -37
  20. package/dist/hashing.d.mts.map +1 -1
  21. package/dist/hashing.mjs +175 -1
  22. package/dist/hashing.mjs.map +1 -0
  23. package/dist/namespace-id-CVpkSFUK.mjs +9 -0
  24. package/dist/namespace-id-CVpkSFUK.mjs.map +1 -0
  25. package/dist/types.d.mts +4 -2
  26. package/dist/types.mjs +91 -2
  27. package/dist/types.mjs.map +1 -0
  28. package/dist/validate-domain.d.mts +6 -8
  29. package/dist/validate-domain.d.mts.map +1 -1
  30. package/dist/validate-domain.mjs +99 -56
  31. package/dist/validate-domain.mjs.map +1 -1
  32. package/package.json +16 -9
  33. package/src/canonicalization-path-match.ts +44 -0
  34. package/src/canonicalization-storage-sort.ts +88 -0
  35. package/src/canonicalization.ts +92 -161
  36. package/src/contract-types.ts +33 -7
  37. package/src/contract-validation-error.ts +7 -0
  38. package/src/cross-reference.ts +28 -0
  39. package/src/domain-envelope.ts +87 -0
  40. package/src/domain-types.ts +13 -15
  41. package/src/exports/contract-validation-error.ts +1 -0
  42. package/src/exports/hashing-utils.ts +12 -0
  43. package/src/exports/hashing.ts +2 -0
  44. package/src/exports/types.ts +24 -1
  45. package/src/hashing.ts +28 -11
  46. package/src/namespace-id.ts +10 -0
  47. package/src/types.ts +21 -0
  48. package/src/validate-domain.ts +162 -94
  49. package/dist/contract-types-Bt2uyqs3.d.mts.map +0 -1
  50. package/dist/contract-validation-error-Dp2vHZt5.mjs +0 -14
  51. package/dist/contract-validation-error-Dp2vHZt5.mjs.map +0 -1
  52. package/dist/contract-validation-error.d.mts.map +0 -1
  53. package/dist/hashing-rZiqFOlc.mjs +0 -204
  54. package/dist/hashing-rZiqFOlc.mjs.map +0 -1
  55. package/dist/testing.d.mts +0 -32
  56. package/dist/testing.d.mts.map +0 -1
  57. package/dist/testing.mjs +0 -63
  58. package/dist/testing.mjs.map +0 -1
  59. package/dist/types-CVGwkRLa.mjs +0 -46
  60. package/dist/types-CVGwkRLa.mjs.map +0 -1
  61. package/src/exports/testing.ts +0 -1
  62. package/src/testing-factories.ts +0 -115
@@ -1,31 +1,68 @@
1
1
  import { ContractValidationError } from './contract-validation-error';
2
+ import type { CrossReference } from './cross-reference';
3
+ import type { ContractWithDomain } from './domain-envelope';
4
+ import { asNamespaceId, type NamespaceId } from './namespace-id';
2
5
 
3
6
  export interface DomainModelShape {
4
7
  readonly fields: Record<string, unknown>;
5
- readonly relations?: Record<string, { readonly to: string }>;
8
+ readonly relations?: Record<string, { readonly to: CrossReference }>;
6
9
  readonly discriminator?: { readonly field: string };
7
10
  readonly variants?: Record<string, unknown>;
8
- readonly base?: string;
11
+ readonly base?: CrossReference;
9
12
  readonly owner?: string;
10
13
  }
11
14
 
12
- export interface DomainContractShape {
13
- readonly roots: Record<string, string>;
14
- readonly models: Record<string, DomainModelShape>;
15
- readonly valueObjects?: Record<string, { readonly fields: Record<string, unknown> }>;
15
+ export interface DomainContractShape extends ContractWithDomain {
16
+ readonly roots: Record<string, CrossReference>;
17
+ }
18
+
19
+ interface IndexedModel {
20
+ readonly namespaceId: NamespaceId;
21
+ readonly name: string;
22
+ readonly model: DomainModelShape;
23
+ }
24
+
25
+ type ModelIndex = Map<NamespaceId, Map<string, IndexedModel>>;
26
+
27
+ function indexDomainModels(contract: DomainContractShape): ModelIndex {
28
+ const index: ModelIndex = new Map();
29
+ for (const [namespaceKey, namespace] of Object.entries(contract.domain.namespaces)) {
30
+ const namespaceId = asNamespaceId(namespaceKey);
31
+ let modelsInNamespace = index.get(namespaceId);
32
+ if (modelsInNamespace === undefined) {
33
+ modelsInNamespace = new Map();
34
+ index.set(namespaceId, modelsInNamespace);
35
+ }
36
+ for (const [name, model] of Object.entries(namespace.models)) {
37
+ modelsInNamespace.set(name, { namespaceId, name, model });
38
+ }
39
+ }
40
+ return index;
41
+ }
42
+
43
+ function lookupModel(index: ModelIndex, ref: CrossReference): IndexedModel | undefined {
44
+ return index.get(ref.namespace)?.get(ref.model);
45
+ }
46
+
47
+ function* iterateIndexedModels(index: ModelIndex): IterableIterator<IndexedModel> {
48
+ for (const modelsInNamespace of index.values()) {
49
+ for (const entry of modelsInNamespace.values()) {
50
+ yield entry;
51
+ }
52
+ }
16
53
  }
17
54
 
18
55
  export function validateContractDomain(contract: DomainContractShape): void {
19
56
  const errors: string[] = [];
20
- const modelNames = new Set(Object.keys(contract.models));
57
+ const modelIndex = indexDomainModels(contract);
21
58
 
22
- validateRoots(contract, modelNames, errors);
23
- validateVariantsAndBases(contract, modelNames, errors);
24
- validateRelationTargets(contract, modelNames, errors);
25
- validateDiscriminators(contract, errors);
26
- validateOwnership(contract, modelNames, errors);
59
+ validateRoots(contract, modelIndex, errors);
60
+ validateVariantsAndBases(modelIndex, errors);
61
+ validateRelationTargets(modelIndex, errors);
62
+ validateDiscriminators(modelIndex, errors);
63
+ validateOwnership(contract, modelIndex, errors);
27
64
  validateValueObjectReferences(contract, errors);
28
- validateFieldModifiers(contract, errors);
65
+ validateFieldModifiers(modelIndex, contract, errors);
29
66
 
30
67
  if (errors.length > 0) {
31
68
  throw new ContractValidationError(
@@ -37,105 +74,104 @@ export function validateContractDomain(contract: DomainContractShape): void {
37
74
 
38
75
  function validateRoots(
39
76
  contract: DomainContractShape,
40
- modelNames: Set<string>,
77
+ modelIndex: ModelIndex,
41
78
  errors: string[],
42
79
  ): void {
43
- const seenValues = new Set<string>();
44
- for (const [rootKey, modelName] of Object.entries(contract.roots)) {
45
- if (seenValues.has(modelName)) {
46
- errors.push(`Duplicate root value: "${modelName}" is mapped by multiple root keys`);
80
+ const seenRootTargets = new Map<NamespaceId, Set<string>>();
81
+ for (const [rootKey, crossRef] of Object.entries(contract.roots)) {
82
+ let modelsInNamespace = seenRootTargets.get(crossRef.namespace);
83
+ if (modelsInNamespace === undefined) {
84
+ modelsInNamespace = new Set();
85
+ seenRootTargets.set(crossRef.namespace, modelsInNamespace);
47
86
  }
48
- seenValues.add(modelName);
87
+ if (modelsInNamespace.has(crossRef.model)) {
88
+ errors.push(
89
+ `Duplicate root value: "${crossRef.namespace}:${crossRef.model}" is mapped by multiple root keys`,
90
+ );
91
+ }
92
+ modelsInNamespace.add(crossRef.model);
49
93
 
50
- if (!modelNames.has(modelName)) {
94
+ if (!lookupModel(modelIndex, crossRef)) {
51
95
  errors.push(
52
- `Root "${rootKey}" references model "${modelName}" which does not exist in models`,
96
+ `Root "${rootKey}" references model "${crossRef.namespace}:${crossRef.model}" which does not exist in domain.namespaces`,
53
97
  );
54
98
  }
55
99
  }
56
100
  }
57
101
 
58
- function validateVariantsAndBases(
59
- contract: DomainContractShape,
60
- modelNames: Set<string>,
61
- errors: string[],
62
- ): void {
63
- const models = new Map(Object.entries(contract.models));
64
-
65
- for (const [modelName, model] of models) {
102
+ function validateVariantsAndBases(modelIndex: ModelIndex, errors: string[]): void {
103
+ for (const { namespaceId, name: modelName, model } of iterateIndexedModels(modelIndex)) {
66
104
  if (model.variants) {
67
105
  for (const variantName of Object.keys(model.variants)) {
68
- if (!modelNames.has(variantName)) {
106
+ const variantRef: CrossReference = { namespace: namespaceId, model: variantName };
107
+ const variantEntry = lookupModel(modelIndex, variantRef);
108
+ if (!variantEntry) {
69
109
  errors.push(
70
- `Model "${modelName}" lists variant "${variantName}" which does not exist in models`,
110
+ `Model "${namespaceId}:${modelName}" lists variant "${variantName}" which does not exist at that namespace coordinate`,
71
111
  );
72
112
  continue;
73
113
  }
74
- const variantModel = models.get(variantName);
75
- if (!variantModel) continue;
76
- if (variantModel.base !== modelName) {
114
+ const variantBase = variantEntry.model.base;
115
+ if (variantBase?.namespace !== namespaceId || variantBase?.model !== modelName) {
77
116
  errors.push(
78
- `Variant "${variantName}" has base "${variantModel.base ?? '(none)'}" but expected "${modelName}"`,
117
+ `Variant "${namespaceId}:${variantName}" has base "${variantBase?.namespace ?? '?'}:${variantBase?.model ?? '(none)'}" but expected "${namespaceId}:${modelName}"`,
79
118
  );
80
119
  }
81
120
  }
82
121
  }
83
122
 
84
123
  if (model.base) {
85
- if (!modelNames.has(model.base)) {
86
- errors.push(`Model "${modelName}" has base "${model.base}" which does not exist in models`);
124
+ const baseEntry = lookupModel(modelIndex, model.base);
125
+ if (!baseEntry) {
126
+ errors.push(
127
+ `Model "${namespaceId}:${modelName}" has base "${model.base.namespace}:${model.base.model}" which does not exist in domain.namespaces`,
128
+ );
87
129
  continue;
88
130
  }
89
- const baseModel = models.get(model.base);
90
- if (!baseModel) continue;
91
- if (!baseModel.variants || !Object.hasOwn(baseModel.variants, modelName)) {
131
+ if (!baseEntry.model.variants || !Object.hasOwn(baseEntry.model.variants, modelName)) {
92
132
  errors.push(
93
- `Model "${modelName}" has base "${model.base}" which does not list it as a variant`,
133
+ `Model "${namespaceId}:${modelName}" has base "${model.base.namespace}:${model.base.model}" which does not list it as a variant`,
94
134
  );
95
135
  }
96
136
  }
97
137
  }
98
138
  }
99
139
 
100
- function validateRelationTargets(
101
- contract: DomainContractShape,
102
- modelNames: Set<string>,
103
- errors: string[],
104
- ): void {
105
- for (const [modelName, model] of Object.entries(contract.models)) {
140
+ function validateRelationTargets(modelIndex: ModelIndex, errors: string[]): void {
141
+ for (const { namespaceId, name: modelName, model } of iterateIndexedModels(modelIndex)) {
106
142
  for (const [relName, relation] of Object.entries(model.relations ?? {})) {
107
- if (!modelNames.has(relation.to)) {
143
+ if (!lookupModel(modelIndex, relation.to)) {
108
144
  errors.push(
109
- `Relation "${relName}" on model "${modelName}" targets "${relation.to}" which does not exist in models`,
145
+ `Relation "${relName}" on model "${namespaceId}:${modelName}" targets "${relation.to.namespace}:${relation.to.model}" which does not exist in domain.namespaces`,
110
146
  );
111
147
  }
112
148
  }
113
149
  }
114
150
  }
115
151
 
116
- function validateDiscriminators(contract: DomainContractShape, errors: string[]): void {
117
- for (const [modelName, model] of Object.entries(contract.models)) {
152
+ function validateDiscriminators(modelIndex: ModelIndex, errors: string[]): void {
153
+ for (const { namespaceId, name: modelName, model } of iterateIndexedModels(modelIndex)) {
118
154
  if (model.discriminator) {
119
155
  if (!model.variants || Object.keys(model.variants).length === 0) {
120
- errors.push(`Model "${modelName}" has discriminator but no variants`);
156
+ errors.push(`Model "${namespaceId}:${modelName}" has discriminator but no variants`);
121
157
  }
122
158
  if (!Object.hasOwn(model.fields, model.discriminator.field)) {
123
159
  errors.push(
124
- `Discriminator field "${model.discriminator.field}" is not a field on model "${modelName}"`,
160
+ `Discriminator field "${model.discriminator.field}" is not a field on model "${namespaceId}:${modelName}"`,
125
161
  );
126
162
  }
127
163
  }
128
164
 
129
165
  if (model.variants && Object.keys(model.variants).length > 0 && !model.discriminator) {
130
- errors.push(`Model "${modelName}" has variants but no discriminator`);
166
+ errors.push(`Model "${namespaceId}:${modelName}" has variants but no discriminator`);
131
167
  }
132
168
 
133
169
  if (model.base) {
134
170
  if (model.discriminator) {
135
- errors.push(`Model "${modelName}" has base and must not have discriminator`);
171
+ errors.push(`Model "${namespaceId}:${modelName}" has base and must not have discriminator`);
136
172
  }
137
173
  if (model.variants && Object.keys(model.variants).length > 0) {
138
- errors.push(`Model "${modelName}" has base and must not have variants`);
174
+ errors.push(`Model "${namespaceId}:${modelName}" has base and must not have variants`);
139
175
  }
140
176
  }
141
177
  }
@@ -143,24 +179,27 @@ function validateDiscriminators(contract: DomainContractShape, errors: string[])
143
179
 
144
180
  function validateOwnership(
145
181
  contract: DomainContractShape,
146
- modelNames: Set<string>,
182
+ modelIndex: ModelIndex,
147
183
  errors: string[],
148
184
  ): void {
149
- for (const [modelName, model] of Object.entries(contract.models)) {
185
+ for (const { namespaceId, name: modelName, model } of iterateIndexedModels(modelIndex)) {
150
186
  if (!model.owner) continue;
151
187
 
152
188
  if (model.owner === modelName) {
153
- errors.push(`Model "${modelName}" cannot own itself`);
189
+ errors.push(`Model "${namespaceId}:${modelName}" cannot own itself`);
154
190
  }
155
191
 
156
- if (!modelNames.has(model.owner)) {
157
- errors.push(`Model "${modelName}" has owner "${model.owner}" which does not exist in models`);
192
+ const ownerRef: CrossReference = { namespace: namespaceId, model: model.owner };
193
+ if (!lookupModel(modelIndex, ownerRef)) {
194
+ errors.push(
195
+ `Model "${namespaceId}:${modelName}" has owner "${namespaceId}:${model.owner}" which does not exist in domain.namespaces`,
196
+ );
158
197
  }
159
198
 
160
- for (const [rootKey, rootModel] of Object.entries(contract.roots)) {
161
- if (rootModel === modelName) {
199
+ for (const [rootKey, rootRef] of Object.entries(contract.roots)) {
200
+ if (rootRef.namespace === namespaceId && rootRef.model === modelName) {
162
201
  errors.push(
163
- `Owned model "${modelName}" must not appear in roots (found as root "${rootKey}")`,
202
+ `Owned model "${namespaceId}:${modelName}" must not appear in roots (found as root "${rootKey}")`,
164
203
  );
165
204
  }
166
205
  }
@@ -179,49 +218,78 @@ interface FieldLike {
179
218
  readonly dict?: boolean;
180
219
  }
181
220
 
182
- function forEachContractField(
183
- contract: DomainContractShape,
184
- callback: (field: unknown, location: string) => void,
185
- ): void {
186
- for (const [modelName, model] of Object.entries(contract.models)) {
187
- for (const [fieldName, field] of Object.entries(model.fields)) {
188
- callback(field, `Model "${modelName}" field "${fieldName}"`);
189
- }
190
- }
191
- for (const [voName, vo] of Object.entries(contract.valueObjects ?? {})) {
192
- for (const [fieldName, field] of Object.entries(vo.fields)) {
193
- callback(field, `Value object "${voName}" field "${fieldName}"`);
194
- }
195
- }
196
- }
197
-
198
221
  function validateValueObjectReferences(contract: DomainContractShape, errors: string[]): void {
199
- const voNames = new Set(Object.keys(contract.valueObjects ?? {}));
222
+ const voNamesByNamespace = new Map<NamespaceId, Set<string>>();
223
+ for (const [namespaceKey, namespace] of Object.entries(contract.domain.namespaces)) {
224
+ const namespaceId = asNamespaceId(namespaceKey);
225
+ voNamesByNamespace.set(namespaceId, new Set(Object.keys(namespace.valueObjects ?? {})));
226
+ }
200
227
 
201
- function checkType(type: FieldTypeLike | undefined, location: string): void {
228
+ function checkType(
229
+ type: FieldTypeLike | undefined,
230
+ location: string,
231
+ namespaceId: NamespaceId,
232
+ ): void {
202
233
  if (!type) return;
234
+ const voNames = voNamesByNamespace.get(namespaceId) ?? new Set<string>();
203
235
  if (type.kind === 'valueObject' && type.name && !voNames.has(type.name)) {
204
236
  errors.push(
205
- `${location} references value object "${type.name}" which does not exist in valueObjects`,
237
+ `${location} references value object "${namespaceId}:${type.name}" which does not exist in that namespace's valueObjects`,
206
238
  );
207
239
  return;
208
240
  }
209
241
  if (type.kind === 'union') {
210
- for (const member of type.members ?? []) checkType(member, location);
242
+ for (const member of type.members ?? []) checkType(member, location, namespaceId);
211
243
  }
212
244
  }
213
245
 
214
- forEachContractField(contract, (field, location) => {
215
- const f = field as FieldLike | undefined;
216
- checkType(f?.type, location);
217
- });
246
+ for (const [namespaceKey, namespace] of Object.entries(contract.domain.namespaces)) {
247
+ const namespaceId = asNamespaceId(namespaceKey);
248
+ for (const [modelName, model] of Object.entries(namespace.models)) {
249
+ for (const [fieldName, field] of Object.entries(model.fields)) {
250
+ const f = field as FieldLike | undefined;
251
+ checkType(f?.type, `Model "${namespaceId}:${modelName}" field "${fieldName}"`, namespaceId);
252
+ }
253
+ }
254
+ for (const [voName, vo] of Object.entries(namespace.valueObjects ?? {})) {
255
+ for (const [fieldName, field] of Object.entries(vo.fields)) {
256
+ const f = field as FieldLike | undefined;
257
+ checkType(
258
+ f?.type,
259
+ `Value object "${namespaceId}:${voName}" field "${fieldName}"`,
260
+ namespaceId,
261
+ );
262
+ }
263
+ }
264
+ }
218
265
  }
219
266
 
220
- function validateFieldModifiers(contract: DomainContractShape, errors: string[]): void {
221
- forEachContractField(contract, (field, location) => {
222
- const f = field as FieldLike | undefined;
223
- if (f?.many && f?.dict) {
224
- errors.push(`${location} cannot have both "many" and "dict" modifiers`);
267
+ function validateFieldModifiers(
268
+ modelIndex: ModelIndex,
269
+ contract: DomainContractShape,
270
+ errors: string[],
271
+ ): void {
272
+ for (const { namespaceId, name: modelName, model } of iterateIndexedModels(modelIndex)) {
273
+ for (const [fieldName, field] of Object.entries(model.fields)) {
274
+ const f = field as FieldLike | undefined;
275
+ if (f?.many && f?.dict) {
276
+ errors.push(
277
+ `Model "${namespaceId}:${modelName}" field "${fieldName}" cannot have both "many" and "dict" modifiers`,
278
+ );
279
+ }
225
280
  }
226
- });
281
+ }
282
+ for (const [namespaceKey, namespace] of Object.entries(contract.domain.namespaces)) {
283
+ const namespaceId = asNamespaceId(namespaceKey);
284
+ for (const [voName, vo] of Object.entries(namespace.valueObjects ?? {})) {
285
+ for (const [fieldName, field] of Object.entries(vo.fields)) {
286
+ const f = field as FieldLike | undefined;
287
+ if (f?.many && f?.dict) {
288
+ errors.push(
289
+ `Value object "${namespaceId}:${voName}" field "${fieldName}" cannot have both "many" and "dict" modifiers`,
290
+ );
291
+ }
292
+ }
293
+ }
294
+ }
227
295
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-types-Bt2uyqs3.d.mts","names":[],"sources":["../src/domain-types.ts","../src/types.ts","../src/contract-types.ts"],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- //#region src/contract-validation-error.ts
2
- var ContractValidationError = class extends Error {
3
- code = "CONTRACT.VALIDATION_FAILED";
4
- phase;
5
- constructor(message, phase) {
6
- super(message);
7
- this.name = "ContractValidationError";
8
- this.phase = phase;
9
- }
10
- };
11
- //#endregion
12
- export { ContractValidationError as t };
13
-
14
- //# sourceMappingURL=contract-validation-error-Dp2vHZt5.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-validation-error-Dp2vHZt5.mjs","names":[],"sources":["../src/contract-validation-error.ts"],"sourcesContent":["export type ContractValidationPhase = 'structural' | 'domain' | 'storage';\n\nexport class ContractValidationError extends Error {\n readonly code = 'CONTRACT.VALIDATION_FAILED';\n readonly phase: ContractValidationPhase;\n\n constructor(message: string, phase: ContractValidationPhase) {\n super(message);\n this.name = 'ContractValidationError';\n this.phase = phase;\n }\n}\n"],"mappings":";AAEA,IAAa,0BAAb,cAA6C,MAAM;CACjD,OAAgB;CAChB;CAEA,YAAY,SAAiB,OAAgC;EAC3D,MAAM,QAAQ;EACd,KAAK,OAAO;EACZ,KAAK,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-validation-error.d.mts","names":[],"sources":["../src/contract-validation-error.ts"],"mappings":";KAAY,uBAAA;AAAA,cAEC,uBAAA,SAAgC,KAAA;EAAA,SAClC,IAAA;EAAA,SACA,KAAA,EAAO,uBAAA;cAEJ,OAAA,UAAiB,KAAA,EAAO,uBAAA;AAAA"}
@@ -1,204 +0,0 @@
1
- import { isArrayEqual } from "@prisma-next/utils/array-equal";
2
- import { ifDefined } from "@prisma-next/utils/defined";
3
- import { createHash } from "node:crypto";
4
- //#region src/canonicalization.ts
5
- const TOP_LEVEL_ORDER = [
6
- "schemaVersion",
7
- "canonicalVersion",
8
- "targetFamily",
9
- "target",
10
- "profileHash",
11
- "roots",
12
- "models",
13
- "valueObjects",
14
- "domain",
15
- "storage",
16
- "execution",
17
- "capabilities",
18
- "extensionPacks",
19
- "meta"
20
- ];
21
- function isDefaultValue(value) {
22
- if (value === false) return true;
23
- if (value === null) return false;
24
- if (Array.isArray(value) && value.length === 0) return true;
25
- if (typeof value === "object" && value !== null) return Object.keys(value).length === 0;
26
- return false;
27
- }
28
- function omitDefaults(obj, path) {
29
- if (obj === null || typeof obj !== "object") return obj;
30
- if (Array.isArray(obj)) return obj.map((item) => omitDefaults(item, path));
31
- const result = {};
32
- for (const [key, value] of Object.entries(obj)) {
33
- const currentPath = [...path, key];
34
- if (key === "_generated") continue;
35
- if (key === "generated" && value === false) continue;
36
- if ((key === "onDelete" || key === "onUpdate") && value === "noAction") continue;
37
- if (isDefaultValue(value)) {
38
- const isRequiredModels = isArrayEqual(currentPath, ["models"]);
39
- const isRequiredNamespaces = isArrayEqual(currentPath, ["storage", "namespaces"]);
40
- const isNamespaceSlot = currentPath.length === 3 && isArrayEqual([currentPath[0], currentPath[1]], ["storage", "namespaces"]);
41
- const isRequiredNamespaceTables = currentPath.length === 4 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables";
42
- const isNamespaceTableEntry = currentPath.length === 5 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables";
43
- const isRequiredRoots = isArrayEqual(currentPath, ["roots"]);
44
- const isRequiredExtensionPacks = isArrayEqual(currentPath, ["extensionPacks"]);
45
- const isRequiredCapabilities = isArrayEqual(currentPath, ["capabilities"]);
46
- const isRequiredMeta = isArrayEqual(currentPath, ["meta"]);
47
- const isRequiredExecutionDefaults = isArrayEqual(currentPath, [
48
- "execution",
49
- "mutations",
50
- "defaults"
51
- ]);
52
- const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === "extensionPacks";
53
- const isModelRelations = currentPath.length === 3 && isArrayEqual([currentPath[0], currentPath[2]], ["models", "relations"]);
54
- const isModelStorage = currentPath.length === 3 && isArrayEqual([currentPath[0], currentPath[2]], ["models", "storage"]);
55
- const isNamespaceTableUniques = currentPath.length === 6 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables" && currentPath[5] === "uniques";
56
- const isNamespaceTableIndexes = currentPath.length === 6 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables" && currentPath[5] === "indexes";
57
- const isNamespaceTableForeignKeys = currentPath.length === 6 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables" && currentPath[5] === "foreignKeys";
58
- const isStorageTypeTypeParams = currentPath.length === 4 && currentPath[0] === "storage" && currentPath[1] === "types" && key === "typeParams";
59
- const isFkBooleanField = currentPath.length === 7 && currentPath[0] === "storage" && currentPath[1] === "namespaces" && currentPath[3] === "tables" && currentPath[5] === "foreignKeys" && (key === "constraint" || key === "index");
60
- if (!isRequiredModels && !isRequiredNamespaces && !isNamespaceSlot && !isRequiredNamespaceTables && !isNamespaceTableEntry && !isRequiredRoots && !isRequiredExtensionPacks && !isRequiredCapabilities && !isRequiredMeta && !isRequiredExecutionDefaults && !isExtensionNamespace && !isModelRelations && !isModelStorage && !isNamespaceTableUniques && !isNamespaceTableIndexes && !isNamespaceTableForeignKeys && !isFkBooleanField && !(key === "nullable") && !isStorageTypeTypeParams) continue;
61
- }
62
- result[key] = omitDefaults(value, currentPath);
63
- }
64
- return result;
65
- }
66
- function sortObjectKeys(obj) {
67
- if (obj === null || typeof obj !== "object") return obj;
68
- if (Array.isArray(obj)) return obj.map((item) => sortObjectKeys(item));
69
- const sorted = {};
70
- const keys = Object.keys(obj).sort();
71
- for (const key of keys) sorted[key] = sortObjectKeys(obj[key]);
72
- return sorted;
73
- }
74
- function sortTableArrays(tableObj) {
75
- const sortedTable = { ...tableObj };
76
- if (Array.isArray(tableObj.indexes)) sortedTable.indexes = [...tableObj.indexes].sort((a, b) => {
77
- const nameA = a?.name || "";
78
- const nameB = b?.name || "";
79
- return nameA.localeCompare(nameB);
80
- });
81
- if (Array.isArray(tableObj.uniques)) sortedTable.uniques = [...tableObj.uniques].sort((a, b) => {
82
- const nameA = a?.name || "";
83
- const nameB = b?.name || "";
84
- return nameA.localeCompare(nameB);
85
- });
86
- return sortedTable;
87
- }
88
- function sortIndexesAndUniques(storage) {
89
- if (!storage || typeof storage !== "object") return storage;
90
- const storageObj = storage;
91
- if (!storageObj.namespaces || typeof storageObj.namespaces !== "object") return storage;
92
- const namespaces = storageObj.namespaces;
93
- const result = {
94
- ...storageObj,
95
- namespaces: {}
96
- };
97
- const resultNamespaces = result.namespaces;
98
- for (const nsId of Object.keys(namespaces)) {
99
- const ns = namespaces[nsId];
100
- if (!ns || typeof ns !== "object") {
101
- resultNamespaces[nsId] = ns;
102
- continue;
103
- }
104
- const nsObj = ns;
105
- if (!nsObj.tables || typeof nsObj.tables !== "object") {
106
- resultNamespaces[nsId] = ns;
107
- continue;
108
- }
109
- const sortedTables = {};
110
- const sortedTableNames = Object.keys(nsObj.tables).sort();
111
- for (const tableName of sortedTableNames) {
112
- const table = nsObj.tables[tableName];
113
- if (!table || typeof table !== "object") {
114
- sortedTables[tableName] = table;
115
- continue;
116
- }
117
- sortedTables[tableName] = sortTableArrays(table);
118
- }
119
- resultNamespaces[nsId] = {
120
- ...nsObj,
121
- tables: sortedTables
122
- };
123
- }
124
- return result;
125
- }
126
- function orderTopLevel(obj) {
127
- const ordered = {};
128
- const remaining = new Set(Object.keys(obj));
129
- for (const key of TOP_LEVEL_ORDER) if (remaining.has(key)) {
130
- ordered[key] = obj[key];
131
- remaining.delete(key);
132
- }
133
- for (const key of Array.from(remaining).sort()) ordered[key] = obj[key];
134
- return ordered;
135
- }
136
- /**
137
- * Object-form variant of {@link canonicalizeContract}. Exported because the
138
- * emitter writes the canonical contract through a separate JSON-stringify
139
- * pass and consumes the structured object directly.
140
- */
141
- function canonicalizeContractToObject(contract, options) {
142
- const serialized = options.serializeContract(contract);
143
- const withDefaultsOmitted = omitDefaults({
144
- ...ifDefined("schemaVersion", options.schemaVersion),
145
- targetFamily: serialized["targetFamily"],
146
- target: serialized["target"],
147
- profileHash: serialized["profileHash"],
148
- roots: serialized["roots"],
149
- models: serialized["models"],
150
- ...ifDefined("valueObjects", serialized["valueObjects"]),
151
- storage: serialized["storage"],
152
- ...ifDefined("execution", serialized["execution"]),
153
- extensionPacks: serialized["extensionPacks"],
154
- capabilities: serialized["capabilities"],
155
- meta: serialized["meta"]
156
- }, []);
157
- const withSortedIndexes = sortIndexesAndUniques(withDefaultsOmitted["storage"]);
158
- return orderTopLevel(sortObjectKeys({
159
- ...withDefaultsOmitted,
160
- storage: withSortedIndexes
161
- }));
162
- }
163
- function canonicalizeContract(contract, options) {
164
- return JSON.stringify(canonicalizeContractToObject(contract, options), null, 2);
165
- }
166
- //#endregion
167
- //#region src/hashing.ts
168
- const SCHEMA_VERSION = "1";
169
- function sha256(content) {
170
- const hash = createHash("sha256");
171
- hash.update(content);
172
- return `sha256:${hash.digest("hex")}`;
173
- }
174
- function hashContract(section) {
175
- return canonicalizeContract({
176
- targetFamily: section["targetFamily"],
177
- target: section["target"],
178
- roots: {},
179
- models: {},
180
- storage: section["storage"] ?? {},
181
- execution: section["execution"],
182
- extensionPacks: {},
183
- capabilities: section["capabilities"] ?? {},
184
- meta: {},
185
- profileHash: "",
186
- ...section
187
- }, {
188
- schemaVersion: SCHEMA_VERSION,
189
- serializeContract: (c) => JSON.parse(JSON.stringify(c))
190
- });
191
- }
192
- function computeStorageHash(args) {
193
- return sha256(hashContract(args));
194
- }
195
- function computeExecutionHash(args) {
196
- return sha256(hashContract(args));
197
- }
198
- function computeProfileHash(args) {
199
- return sha256(hashContract(args));
200
- }
201
- //#endregion
202
- export { canonicalizeContractToObject as a, canonicalizeContract as i, computeProfileHash as n, computeStorageHash as r, computeExecutionHash as t };
203
-
204
- //# sourceMappingURL=hashing-rZiqFOlc.mjs.map