@fjell/core 4.4.73 → 4.4.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/AItemService.d.ts +1 -1
- package/dist/Coordinate.d.ts +1 -6
- package/dist/event/emitter.d.ts +1 -2
- package/dist/event/events.d.ts +1 -2
- package/dist/event/matching.d.ts +1 -1
- package/dist/event/subscription.d.ts +1 -2
- package/dist/index.d.ts +7 -20
- package/dist/index.js +1113 -1276
- package/dist/item/IFactory.d.ts +1 -2
- package/dist/item/IQFactory.d.ts +1 -1
- package/dist/item/IQUtils.d.ts +1 -2
- package/dist/item/IUtils.d.ts +1 -7
- package/dist/key/KUtils.d.ts +3 -3
- package/dist/operations/OperationContext.d.ts +1 -1
- package/dist/operations/index.d.ts +1 -0
- package/dist/operations/wrappers/createActionWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createAllActionWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createAllFacetWrapper.d.ts +1 -2
- package/dist/operations/wrappers/createAllWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createCreateWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createFacetWrapper.d.ts +1 -2
- package/dist/operations/wrappers/createFindOneWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createFindWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createGetWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createOneWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createRemoveWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createUpdateWrapper.d.ts +1 -3
- package/dist/operations/wrappers/createUpsertWrapper.d.ts +1 -3
- package/dist/operations/wrappers/types.d.ts +1 -1
- package/package.json +4 -7
- package/dist/item/ItemQuery.d.ts +0 -62
- package/dist/items.d.ts +0 -74
- package/dist/keys.d.ts +0 -66
- package/dist/operations/Operations.d.ts +0 -530
- package/dist/operations/contained.d.ts +0 -65
- package/dist/operations/methods.d.ts +0 -204
- package/dist/operations/primary.d.ts +0 -57
- package/dist/operations/specialized.d.ts +0 -41
- package/dist/validation/ItemValidator.d.ts +0 -43
- package/dist/validation/KeyValidator.d.ts +0 -56
- package/dist/validation/LocationValidator.d.ts +0 -39
- package/dist/validation/QueryValidator.d.ts +0 -57
- package/dist/validation/index.d.ts +0 -17
- package/dist/validation/index.js +0 -656
- package/dist/validation/schema.d.ts +0 -23
- package/dist/validation/types.d.ts +0 -69
package/dist/validation/index.js
DELETED
|
@@ -1,656 +0,0 @@
|
|
|
1
|
-
// src/logger.ts
|
|
2
|
-
import Logging from "@fjell/logging";
|
|
3
|
-
var LibLogger = Logging.getLogger("@fjell/core");
|
|
4
|
-
var logger_default = LibLogger;
|
|
5
|
-
|
|
6
|
-
// src/validation/LocationValidator.ts
|
|
7
|
-
var logger = logger_default.get("validation", "LocationValidator");
|
|
8
|
-
var validateLocations = (locations, coordinate, operation) => {
|
|
9
|
-
if (!locations || locations.length === 0) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
const keyTypeArray = coordinate.kta;
|
|
13
|
-
const expectedLocationTypes = keyTypeArray.slice(1);
|
|
14
|
-
const actualLocationTypes = locations.map((loc) => loc.kt);
|
|
15
|
-
logger.debug(`Validating locations for ${operation}`, {
|
|
16
|
-
expected: expectedLocationTypes,
|
|
17
|
-
actual: actualLocationTypes,
|
|
18
|
-
coordinate: keyTypeArray
|
|
19
|
-
});
|
|
20
|
-
if (actualLocationTypes.length > expectedLocationTypes.length) {
|
|
21
|
-
logger.error("Location key array has too many elements", {
|
|
22
|
-
expected: expectedLocationTypes.length,
|
|
23
|
-
actual: actualLocationTypes.length,
|
|
24
|
-
expectedTypes: expectedLocationTypes,
|
|
25
|
-
actualTypes: actualLocationTypes,
|
|
26
|
-
coordinate,
|
|
27
|
-
operation
|
|
28
|
-
});
|
|
29
|
-
throw new Error(
|
|
30
|
-
`Invalid location key array for ${operation}: Expected at most ${expectedLocationTypes.length} location keys (hierarchy: [${expectedLocationTypes.join(", ")}]), but received ${actualLocationTypes.length} (types: [${actualLocationTypes.join(", ")}])`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
for (let i = 0; i < actualLocationTypes.length; i++) {
|
|
34
|
-
if (expectedLocationTypes[i] !== actualLocationTypes[i]) {
|
|
35
|
-
logger.error("Location key array order mismatch", {
|
|
36
|
-
position: i,
|
|
37
|
-
expected: expectedLocationTypes[i],
|
|
38
|
-
actual: actualLocationTypes[i],
|
|
39
|
-
expectedHierarchy: expectedLocationTypes,
|
|
40
|
-
actualOrder: actualLocationTypes,
|
|
41
|
-
coordinate,
|
|
42
|
-
operation
|
|
43
|
-
});
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Invalid location key array order for ${operation}: At position ${i}, expected key type "${expectedLocationTypes[i]}" but received "${actualLocationTypes[i]}". Location keys must be ordered according to the hierarchy: [${expectedLocationTypes.join(", ")}]. Received order: [${actualLocationTypes.join(", ")}]`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
logger.debug(`Location key array validation passed for ${operation}`, { locations });
|
|
50
|
-
};
|
|
51
|
-
var isValidLocations = (locations, coordinate, operation) => {
|
|
52
|
-
try {
|
|
53
|
-
validateLocations(locations, coordinate, operation);
|
|
54
|
-
return { valid: true };
|
|
55
|
-
} catch (error) {
|
|
56
|
-
return {
|
|
57
|
-
valid: false,
|
|
58
|
-
error: error instanceof Error ? error.message : String(error)
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// src/key/KUtils.ts
|
|
64
|
-
var logger2 = logger_default.get("KUtils");
|
|
65
|
-
var isComKey = (key) => {
|
|
66
|
-
logger2.trace("isComKey", { key });
|
|
67
|
-
return key !== void 0 && (key.pk !== void 0 && key.kt !== void 0) && (key.loc !== void 0 && Array.isArray(key.loc));
|
|
68
|
-
};
|
|
69
|
-
var isPriKey = (key) => {
|
|
70
|
-
logger2.trace("isPriKey", { key });
|
|
71
|
-
return key !== void 0 && (key.pk !== void 0 && key.kt !== void 0) && key.loc === void 0;
|
|
72
|
-
};
|
|
73
|
-
var toKeyTypeArray = (ik) => {
|
|
74
|
-
logger2.trace("toKeyTypeArray", { ik });
|
|
75
|
-
if (isComKey(ik)) {
|
|
76
|
-
const ck = ik;
|
|
77
|
-
return [ck.kt, ...ck.loc.map((l) => l.kt)];
|
|
78
|
-
} else {
|
|
79
|
-
return [ik.kt];
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// src/validation/KeyValidator.ts
|
|
84
|
-
var logger3 = logger_default.get("validation", "KeyValidator");
|
|
85
|
-
var validateLocationKeyOrder = (key, coordinate, operation) => {
|
|
86
|
-
const keyTypeArray = coordinate.kta;
|
|
87
|
-
const expectedLocationTypes = keyTypeArray.slice(1);
|
|
88
|
-
const actualLocationTypes = key.loc.map((loc) => loc.kt);
|
|
89
|
-
if (expectedLocationTypes.length !== actualLocationTypes.length) {
|
|
90
|
-
logger3.error("Location key array length mismatch", {
|
|
91
|
-
expected: expectedLocationTypes.length,
|
|
92
|
-
actual: actualLocationTypes.length,
|
|
93
|
-
key,
|
|
94
|
-
coordinate,
|
|
95
|
-
operation
|
|
96
|
-
});
|
|
97
|
-
const expectedOrder = expectedLocationTypes.map(
|
|
98
|
-
(kt, i) => ` [${i}] { kt: '${kt}', lk: <value> }`
|
|
99
|
-
).join("\n");
|
|
100
|
-
const actualOrder = key.loc.map(
|
|
101
|
-
(loc, i) => ` [${i}] { kt: '${loc.kt}', lk: ${JSON.stringify(loc.lk)} }`
|
|
102
|
-
).join("\n");
|
|
103
|
-
throw new Error(
|
|
104
|
-
`Location key array length mismatch for ${operation} operation.
|
|
105
|
-
|
|
106
|
-
Expected ${expectedLocationTypes.length} location keys but received ${actualLocationTypes.length}.
|
|
107
|
-
|
|
108
|
-
Expected location key order for '${keyTypeArray[0]}':
|
|
109
|
-
${expectedOrder}
|
|
110
|
-
|
|
111
|
-
Received location key order:
|
|
112
|
-
${actualOrder}`
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
for (let i = 0; i < expectedLocationTypes.length; i++) {
|
|
116
|
-
if (expectedLocationTypes[i] !== actualLocationTypes[i]) {
|
|
117
|
-
logger3.error("Location key array order mismatch", {
|
|
118
|
-
position: i,
|
|
119
|
-
expected: expectedLocationTypes[i],
|
|
120
|
-
actual: actualLocationTypes[i],
|
|
121
|
-
key,
|
|
122
|
-
coordinate,
|
|
123
|
-
operation
|
|
124
|
-
});
|
|
125
|
-
const expectedOrder = expectedLocationTypes.map(
|
|
126
|
-
(kt, i2) => ` [${i2}] { kt: '${kt}', lk: <value> }`
|
|
127
|
-
).join("\n");
|
|
128
|
-
const actualOrder = key.loc.map(
|
|
129
|
-
(loc, i2) => ` [${i2}] { kt: '${loc.kt}', lk: ${JSON.stringify(loc.lk)} }`
|
|
130
|
-
).join("\n");
|
|
131
|
-
throw new Error(
|
|
132
|
-
`Location key array order mismatch for ${operation} operation.
|
|
133
|
-
|
|
134
|
-
At position ${i}, expected key type "${expectedLocationTypes[i]}" but received "${actualLocationTypes[i]}".
|
|
135
|
-
|
|
136
|
-
Expected location key order for '${keyTypeArray[0]}':
|
|
137
|
-
${expectedOrder}
|
|
138
|
-
|
|
139
|
-
Received location key order:
|
|
140
|
-
${actualOrder}
|
|
141
|
-
|
|
142
|
-
Tip: Location keys must be ordered according to the hierarchy: [${expectedLocationTypes.join(", ")}]`
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
var validateKey = (key, coordinate, operation) => {
|
|
148
|
-
logger3.debug(`Validating key for ${operation}`, { key, coordinate: coordinate.kta });
|
|
149
|
-
if (!key || key === null) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
`Invalid key structure for ${operation} operation.
|
|
152
|
-
|
|
153
|
-
The provided key is null or undefined.
|
|
154
|
-
|
|
155
|
-
Valid key formats:
|
|
156
|
-
PriKey: { kt: string, pk: string|number }
|
|
157
|
-
ComKey: { kt: string, pk: string|number, loc: Array<{ kt: string, lk: string|number }> }`
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
const isCompositeLibrary = coordinate.kta.length > 1;
|
|
161
|
-
const keyIsComposite = isComKey(key);
|
|
162
|
-
const keyIsPrimary = isPriKey(key);
|
|
163
|
-
if (isCompositeLibrary && !keyIsComposite) {
|
|
164
|
-
logger3.error(`Composite library received primary key in ${operation}`, { key, coordinate });
|
|
165
|
-
const keyTypeArray = coordinate.kta;
|
|
166
|
-
throw new Error(
|
|
167
|
-
`Invalid key type for ${operation} operation.
|
|
168
|
-
|
|
169
|
-
This is a composite item library. You must provide a ComKey with location keys.
|
|
170
|
-
|
|
171
|
-
Expected: ComKey with format:
|
|
172
|
-
{
|
|
173
|
-
kt: '${keyTypeArray[0]}',
|
|
174
|
-
pk: string|number,
|
|
175
|
-
loc: [
|
|
176
|
-
` + keyTypeArray.slice(1).map((kt) => ` { kt: '${kt}', lk: string|number }`).join(",\n") + `
|
|
177
|
-
]
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
Received: PriKey with format:
|
|
181
|
-
${JSON.stringify(key, null, 2)}
|
|
182
|
-
|
|
183
|
-
Example correct usage:
|
|
184
|
-
library.operations.${operation}({
|
|
185
|
-
kt: '${keyTypeArray[0]}',
|
|
186
|
-
pk: 'item-id',
|
|
187
|
-
loc: [${keyTypeArray.slice(1).map((kt) => `{ kt: '${kt}', lk: 'parent-id' }`).join(", ")}]
|
|
188
|
-
})`
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
if (!isCompositeLibrary && keyIsComposite) {
|
|
192
|
-
logger3.error(`Primary library received composite key in ${operation}`, { key, coordinate });
|
|
193
|
-
const keyTypeArray = coordinate.kta;
|
|
194
|
-
throw new Error(
|
|
195
|
-
`Invalid key type for ${operation} operation.
|
|
196
|
-
|
|
197
|
-
This is a primary item library. You should provide a PriKey without location keys.
|
|
198
|
-
|
|
199
|
-
Expected: PriKey with format:
|
|
200
|
-
{ kt: '${keyTypeArray[0]}', pk: string|number }
|
|
201
|
-
|
|
202
|
-
Received: ComKey with format:
|
|
203
|
-
${JSON.stringify(key, null, 2)}
|
|
204
|
-
|
|
205
|
-
Example correct usage:
|
|
206
|
-
library.operations.${operation}({ kt: '${keyTypeArray[0]}', pk: 'item-id' })`
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
if (!keyIsPrimary && !keyIsComposite) {
|
|
210
|
-
logger3.error(`Invalid key structure in ${operation}`, { key, coordinate });
|
|
211
|
-
throw new Error(
|
|
212
|
-
`Invalid key structure for ${operation} operation.
|
|
213
|
-
|
|
214
|
-
The provided key does not match PriKey or ComKey format.
|
|
215
|
-
|
|
216
|
-
Received:
|
|
217
|
-
${JSON.stringify(key, null, 2)}
|
|
218
|
-
|
|
219
|
-
Valid key formats:
|
|
220
|
-
PriKey: { kt: string, pk: string|number }
|
|
221
|
-
ComKey: { kt: string, pk: string|number, loc: Array<{ kt: string, lk: string|number }> }`
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
const expectedKeyType = coordinate.kta[0];
|
|
225
|
-
if (key.kt !== expectedKeyType) {
|
|
226
|
-
logger3.error(`Key type mismatch in ${operation}`, {
|
|
227
|
-
expected: expectedKeyType,
|
|
228
|
-
received: key.kt,
|
|
229
|
-
key,
|
|
230
|
-
coordinate
|
|
231
|
-
});
|
|
232
|
-
throw new Error(
|
|
233
|
-
`Invalid key type for ${operation} operation.
|
|
234
|
-
|
|
235
|
-
Expected key type: '${expectedKeyType}'
|
|
236
|
-
Received key type: '${key.kt}'
|
|
237
|
-
|
|
238
|
-
Example correct usage:
|
|
239
|
-
library.operations.${operation}({ kt: '${expectedKeyType}', pk: 'item-id', ... })`
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
if (keyIsComposite) {
|
|
243
|
-
const comKey = key;
|
|
244
|
-
if (comKey.loc.length === 0) {
|
|
245
|
-
logger3.debug(`Empty loc array detected in ${operation} - will search across all locations`, { key });
|
|
246
|
-
} else {
|
|
247
|
-
validateLocationKeyOrder(comKey, coordinate, operation);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
logger3.debug(`Key validation passed for ${operation}`, { key });
|
|
251
|
-
};
|
|
252
|
-
var validatePriKey = (key, expectedType, operation) => {
|
|
253
|
-
if (!key || key === null) {
|
|
254
|
-
throw new Error(`[${operation}] PriKey is undefined or null`);
|
|
255
|
-
}
|
|
256
|
-
if (!key.kt) {
|
|
257
|
-
throw new Error(`[${operation}] PriKey is missing 'kt' field`);
|
|
258
|
-
}
|
|
259
|
-
if (key.kt !== expectedType) {
|
|
260
|
-
throw new Error(
|
|
261
|
-
`[${operation}] PriKey has incorrect type.
|
|
262
|
-
Expected: '${expectedType}'
|
|
263
|
-
Received: '${key.kt}'`
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
if (typeof key.pk === "undefined" || key.pk === null) {
|
|
267
|
-
throw new Error(`[${operation}] PriKey is missing 'pk' field`);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
var validateComKey = (key, coordinate, operation) => {
|
|
271
|
-
if (!key || key === null) {
|
|
272
|
-
throw new Error(`[${operation}] ComKey is undefined or null`);
|
|
273
|
-
}
|
|
274
|
-
if (!key.kt) {
|
|
275
|
-
throw new Error(`[${operation}] ComKey is missing 'kt' field`);
|
|
276
|
-
}
|
|
277
|
-
if (key.kt !== coordinate.kta[0]) {
|
|
278
|
-
throw new Error(
|
|
279
|
-
`[${operation}] ComKey has incorrect type.
|
|
280
|
-
Expected: '${coordinate.kta[0]}'
|
|
281
|
-
Received: '${key.kt}'`
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
if (typeof key.pk === "undefined" || key.pk === null) {
|
|
285
|
-
throw new Error(`[${operation}] ComKey is missing 'pk' field`);
|
|
286
|
-
}
|
|
287
|
-
if (!Array.isArray(key.loc)) {
|
|
288
|
-
throw new Error(`[${operation}] ComKey is missing or invalid 'loc' field (must be an array)`);
|
|
289
|
-
}
|
|
290
|
-
if (key.loc.length > 0) {
|
|
291
|
-
validateLocationKeyOrder(key, coordinate, operation);
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// src/validation/ItemValidator.ts
|
|
296
|
-
var logger4 = logger_default.get("validation", "ItemValidator");
|
|
297
|
-
var validatePKForItem = (item, pkType) => {
|
|
298
|
-
if (!item) {
|
|
299
|
-
logger4.error("Item validation failed - item is undefined", {
|
|
300
|
-
component: "core",
|
|
301
|
-
operation: "validatePK",
|
|
302
|
-
expectedType: pkType,
|
|
303
|
-
item,
|
|
304
|
-
suggestion: "Ensure the operation returns a valid item object, not undefined/null"
|
|
305
|
-
});
|
|
306
|
-
throw new Error(
|
|
307
|
-
`Item validation failed: item is undefined. Expected item of type '${pkType}'. This usually indicates a database operation returned null/undefined unexpectedly.`
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
if (!item.key) {
|
|
311
|
-
logger4.error("Item validation failed - item missing key", {
|
|
312
|
-
component: "core",
|
|
313
|
-
operation: "validatePK",
|
|
314
|
-
expectedType: pkType,
|
|
315
|
-
item,
|
|
316
|
-
suggestion: "Ensure the item has a valid key property with kt and pk fields"
|
|
317
|
-
});
|
|
318
|
-
throw new Error(
|
|
319
|
-
`Item validation failed: item does not have a key property. Expected key with type '${pkType}'. Item: ${JSON.stringify(item)}. This indicates a database processing error.`
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
const keyTypeArray = toKeyTypeArray(item.key);
|
|
323
|
-
if (keyTypeArray[0] !== pkType) {
|
|
324
|
-
logger4.error("Key type mismatch during validation", {
|
|
325
|
-
component: "core",
|
|
326
|
-
operation: "validatePK",
|
|
327
|
-
expectedType: pkType,
|
|
328
|
-
actualType: keyTypeArray[0],
|
|
329
|
-
keyTypeArray,
|
|
330
|
-
itemKey: item.key,
|
|
331
|
-
suggestion: `Ensure the item key has kt: '${pkType}', not '${keyTypeArray[0]}'`
|
|
332
|
-
});
|
|
333
|
-
throw new Error(
|
|
334
|
-
`Item has incorrect primary key type. Expected '${pkType}', got '${keyTypeArray[0]}'. Key: ${JSON.stringify(item.key)}. This indicates a data model mismatch.`
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
return item;
|
|
338
|
-
};
|
|
339
|
-
var validatePK = (input, pkType) => {
|
|
340
|
-
logger4.trace("Checking Return Type", { input });
|
|
341
|
-
if (Array.isArray(input)) {
|
|
342
|
-
return input.map((item) => validatePKForItem(item, pkType));
|
|
343
|
-
}
|
|
344
|
-
return validatePKForItem(input, pkType);
|
|
345
|
-
};
|
|
346
|
-
var validateKeys = (item, keyTypes) => {
|
|
347
|
-
logger4.trace("Checking Return Type", { item });
|
|
348
|
-
if (!item) {
|
|
349
|
-
logger4.error("Key validation failed - item is undefined", {
|
|
350
|
-
component: "core",
|
|
351
|
-
operation: "validateKeys",
|
|
352
|
-
expectedKeyTypes: keyTypes,
|
|
353
|
-
suggestion: "Ensure the operation returns a valid item object, not undefined/null"
|
|
354
|
-
});
|
|
355
|
-
throw new Error(
|
|
356
|
-
`Key validation failed: item is undefined. Expected item with key types [${keyTypes.join(", ")}]. This usually indicates a database operation returned null/undefined unexpectedly.`
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
if (!item.key) {
|
|
360
|
-
logger4.error("Key validation failed - item missing key", {
|
|
361
|
-
component: "core",
|
|
362
|
-
operation: "validateKeys",
|
|
363
|
-
expectedKeyTypes: keyTypes,
|
|
364
|
-
item: JSON.stringify(item),
|
|
365
|
-
suggestion: "Ensure the item has a valid key property"
|
|
366
|
-
});
|
|
367
|
-
throw new Error(
|
|
368
|
-
`Key validation failed: item does not have a key property. Expected key with types [${keyTypes.join(", ")}]. Item: ${JSON.stringify(item)}. This indicates a database processing error.`
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
const keyTypeArray = toKeyTypeArray(item.key);
|
|
372
|
-
if (keyTypeArray.length !== keyTypes.length) {
|
|
373
|
-
logger4.error("Key hierarchy depth mismatch", {
|
|
374
|
-
component: "core",
|
|
375
|
-
operation: "validateKeys",
|
|
376
|
-
expectedKeyTypes: keyTypes,
|
|
377
|
-
expectedDepth: keyTypes.length,
|
|
378
|
-
actualKeyTypes: keyTypeArray,
|
|
379
|
-
actualDepth: keyTypeArray.length,
|
|
380
|
-
itemKey: item.key,
|
|
381
|
-
suggestion: `Check coordinate definition. Expected hierarchy depth of ${keyTypes.length}, got ${keyTypeArray.length}`
|
|
382
|
-
});
|
|
383
|
-
throw new Error(
|
|
384
|
-
`Item has incorrect key hierarchy depth. Expected ${keyTypes.length} levels [${keyTypes.join(" > ")}], but got ${keyTypeArray.length} levels [${keyTypeArray.join(" > ")}]. Key: ${JSON.stringify(item.key)}. This indicates a coordinate/hierarchy mismatch.`
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
const match = JSON.stringify(keyTypeArray) === JSON.stringify(keyTypes);
|
|
388
|
-
if (!match) {
|
|
389
|
-
logger4.error("Key Type Array Mismatch", {
|
|
390
|
-
component: "core",
|
|
391
|
-
operation: "validateKeys",
|
|
392
|
-
expectedKeyTypes: keyTypes,
|
|
393
|
-
actualKeyTypes: keyTypeArray,
|
|
394
|
-
itemKey: item.key,
|
|
395
|
-
suggestion: `Ensure item key matches expected hierarchy: [${keyTypes.join(" > ")}]`
|
|
396
|
-
});
|
|
397
|
-
throw new Error(
|
|
398
|
-
`Item has incorrect key types. Expected [${keyTypes.join(" > ")}], but got [${keyTypeArray.join(" > ")}]. Key: ${JSON.stringify(item.key)}. This indicates a data model mismatch.`
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
return item;
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
// src/validation/QueryValidator.ts
|
|
405
|
-
var logger5 = logger_default.get("validation", "QueryValidator");
|
|
406
|
-
var validateQuery = (query, operation) => {
|
|
407
|
-
if (typeof query === "undefined" || query === null) {
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
if (typeof query !== "object") {
|
|
411
|
-
logger5.error(`Invalid query type for ${operation}`, { query, type: typeof query });
|
|
412
|
-
throw new Error(
|
|
413
|
-
`[${operation}] Invalid query parameter.
|
|
414
|
-
|
|
415
|
-
Expected: object or undefined
|
|
416
|
-
Received: ${typeof query}
|
|
417
|
-
|
|
418
|
-
Example valid queries:
|
|
419
|
-
{}
|
|
420
|
-
{ filter: { status: 'active' } }
|
|
421
|
-
{ limit: 10, sort: { field: 'name', order: 'asc' } }`
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
if (Array.isArray(query)) {
|
|
425
|
-
logger5.error(`Query cannot be an array for ${operation}`, { query });
|
|
426
|
-
throw new Error(
|
|
427
|
-
`[${operation}] Invalid query parameter.
|
|
428
|
-
|
|
429
|
-
Query cannot be an array.
|
|
430
|
-
Received: ${JSON.stringify(query)}`
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
logger5.debug(`Query validation passed for ${operation}`, { query });
|
|
434
|
-
};
|
|
435
|
-
var validateOperationParams = (params, operation) => {
|
|
436
|
-
if (typeof params === "undefined") {
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
if (params === null) {
|
|
440
|
-
logger5.error(`Params cannot be null for ${operation}`, { params });
|
|
441
|
-
throw new Error(
|
|
442
|
-
`[${operation}] Invalid operation parameters.
|
|
443
|
-
|
|
444
|
-
Parameters cannot be null.
|
|
445
|
-
Expected: object or undefined
|
|
446
|
-
Received: null
|
|
447
|
-
|
|
448
|
-
Example valid parameters:
|
|
449
|
-
{}
|
|
450
|
-
{ email: 'user@example.com' }
|
|
451
|
-
{ status: 'active', limit: 10 }`
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
if (typeof params !== "object") {
|
|
455
|
-
logger5.error(`Invalid params type for ${operation}`, { params, type: typeof params });
|
|
456
|
-
throw new Error(
|
|
457
|
-
`[${operation}] Invalid operation parameters.
|
|
458
|
-
|
|
459
|
-
Expected: object or undefined
|
|
460
|
-
Received: ${typeof params}
|
|
461
|
-
|
|
462
|
-
Example valid parameters:
|
|
463
|
-
{}
|
|
464
|
-
{ email: 'user@example.com' }
|
|
465
|
-
{ status: 'active', limit: 10 }`
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
if (Array.isArray(params)) {
|
|
469
|
-
logger5.error(`Params cannot be an array for ${operation}`, { params });
|
|
470
|
-
throw new Error(
|
|
471
|
-
`[${operation}] Invalid operation parameters.
|
|
472
|
-
|
|
473
|
-
Parameters cannot be an array.
|
|
474
|
-
Received: ${JSON.stringify(params)}`
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
for (const [key, value] of Object.entries(params)) {
|
|
478
|
-
const valueType = typeof value;
|
|
479
|
-
const isValidType = valueType === "string" || valueType === "number" || valueType === "boolean" || value instanceof Date || Array.isArray(value) && value.every(
|
|
480
|
-
(v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" || v instanceof Date
|
|
481
|
-
);
|
|
482
|
-
if (!isValidType) {
|
|
483
|
-
logger5.error(`Invalid param value type for ${operation}`, { key, value, valueType });
|
|
484
|
-
throw new Error(
|
|
485
|
-
`[${operation}] Invalid value type for parameter "${key}".
|
|
486
|
-
|
|
487
|
-
Allowed types: string, number, boolean, Date, or arrays of these types
|
|
488
|
-
Received: ${valueType}
|
|
489
|
-
Value: ${JSON.stringify(value)}`
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
logger5.debug(`Operation params validation passed for ${operation}`, { params });
|
|
494
|
-
};
|
|
495
|
-
var validateFinderName = (finder, operation) => {
|
|
496
|
-
if (!finder || typeof finder !== "string") {
|
|
497
|
-
logger5.error(`Invalid finder name for ${operation}`, { finder, type: typeof finder });
|
|
498
|
-
throw new Error(
|
|
499
|
-
`[${operation}] Finder name must be a non-empty string.
|
|
500
|
-
|
|
501
|
-
Received: ${JSON.stringify(finder)}`
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
if (finder.trim().length === 0) {
|
|
505
|
-
logger5.error(`Empty finder name for ${operation}`, { finder });
|
|
506
|
-
throw new Error(
|
|
507
|
-
`[${operation}] Finder name cannot be empty or whitespace only.
|
|
508
|
-
|
|
509
|
-
Received: "${finder}"`
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
logger5.debug(`Finder name validation passed for ${operation}`, { finder });
|
|
513
|
-
};
|
|
514
|
-
var validateActionName = (action, operation) => {
|
|
515
|
-
if (!action || typeof action !== "string") {
|
|
516
|
-
logger5.error(`Invalid action name for ${operation}`, { action, type: typeof action });
|
|
517
|
-
throw new Error(
|
|
518
|
-
`[${operation}] Action name must be a non-empty string.
|
|
519
|
-
|
|
520
|
-
Received: ${JSON.stringify(action)}`
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
if (action.trim().length === 0) {
|
|
524
|
-
logger5.error(`Empty action name for ${operation}`, { action });
|
|
525
|
-
throw new Error(
|
|
526
|
-
`[${operation}] Action name cannot be empty or whitespace only.
|
|
527
|
-
|
|
528
|
-
Received: "${action}"`
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
logger5.debug(`Action name validation passed for ${operation}`, { action });
|
|
532
|
-
};
|
|
533
|
-
var validateFacetName = (facet, operation) => {
|
|
534
|
-
if (!facet || typeof facet !== "string") {
|
|
535
|
-
logger5.error(`Invalid facet name for ${operation}`, { facet, type: typeof facet });
|
|
536
|
-
throw new Error(
|
|
537
|
-
`[${operation}] Facet name must be a non-empty string.
|
|
538
|
-
|
|
539
|
-
Received: ${JSON.stringify(facet)}`
|
|
540
|
-
);
|
|
541
|
-
}
|
|
542
|
-
if (facet.trim().length === 0) {
|
|
543
|
-
logger5.error(`Empty facet name for ${operation}`, { facet });
|
|
544
|
-
throw new Error(
|
|
545
|
-
`[${operation}] Facet name cannot be empty or whitespace only.
|
|
546
|
-
|
|
547
|
-
Received: "${facet}"`
|
|
548
|
-
);
|
|
549
|
-
}
|
|
550
|
-
logger5.debug(`Facet name validation passed for ${operation}`, { facet });
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
// src/errors/ActionError.ts
|
|
554
|
-
var ActionError = class extends Error {
|
|
555
|
-
constructor(errorInfo, cause) {
|
|
556
|
-
super(errorInfo.message);
|
|
557
|
-
this.errorInfo = errorInfo;
|
|
558
|
-
this.name = "ActionError";
|
|
559
|
-
this.cause = cause;
|
|
560
|
-
if (!this.errorInfo.technical) {
|
|
561
|
-
this.errorInfo.technical = { timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
562
|
-
}
|
|
563
|
-
if (!this.errorInfo.technical.timestamp) {
|
|
564
|
-
this.errorInfo.technical.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
toJSON() {
|
|
568
|
-
return this.errorInfo;
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
// src/errors/ValidationError.ts
|
|
573
|
-
var ValidationError = class extends ActionError {
|
|
574
|
-
fieldErrors;
|
|
575
|
-
constructor(message, validOptions, suggestedAction, conflictingValue, fieldErrors) {
|
|
576
|
-
super({
|
|
577
|
-
code: "VALIDATION_ERROR",
|
|
578
|
-
message,
|
|
579
|
-
operation: { type: "create", name: "", params: {} },
|
|
580
|
-
// Will be filled by wrapper
|
|
581
|
-
context: { itemType: "" },
|
|
582
|
-
// Will be filled by wrapper
|
|
583
|
-
details: {
|
|
584
|
-
validOptions,
|
|
585
|
-
suggestedAction: suggestedAction || (validOptions && validOptions.length > 0 ? `Valid options are: ${validOptions.join(", ")}. Please use one of these values.` : "Check the validation requirements and ensure all fields meet the required format, type, and constraints."),
|
|
586
|
-
retryable: true,
|
|
587
|
-
conflictingValue,
|
|
588
|
-
fieldErrors
|
|
589
|
-
},
|
|
590
|
-
technical: {
|
|
591
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
this.fieldErrors = fieldErrors;
|
|
595
|
-
if (fieldErrors) {
|
|
596
|
-
if (!this.errorInfo.details) this.errorInfo.details = {};
|
|
597
|
-
this.errorInfo.details.fieldErrors = fieldErrors;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
// src/validation/schema.ts
|
|
603
|
-
async function validateSchema(data, schema) {
|
|
604
|
-
if (!schema) {
|
|
605
|
-
return data;
|
|
606
|
-
}
|
|
607
|
-
try {
|
|
608
|
-
if (schema.parseAsync) {
|
|
609
|
-
return await schema.parseAsync(data);
|
|
610
|
-
}
|
|
611
|
-
const result = schema.safeParse(data);
|
|
612
|
-
if (result.success) {
|
|
613
|
-
return result.data;
|
|
614
|
-
} else {
|
|
615
|
-
throw result.error;
|
|
616
|
-
}
|
|
617
|
-
} catch (error) {
|
|
618
|
-
if (error && Array.isArray(error.issues)) {
|
|
619
|
-
const fieldErrors = error.issues.map((issue) => ({
|
|
620
|
-
path: issue.path,
|
|
621
|
-
message: issue.message,
|
|
622
|
-
code: issue.code
|
|
623
|
-
}));
|
|
624
|
-
const validationError = new ValidationError(
|
|
625
|
-
"Schema validation failed",
|
|
626
|
-
// eslint-disable-next-line no-undefined
|
|
627
|
-
void 0,
|
|
628
|
-
// eslint-disable-next-line no-undefined
|
|
629
|
-
void 0,
|
|
630
|
-
// eslint-disable-next-line no-undefined
|
|
631
|
-
void 0,
|
|
632
|
-
fieldErrors
|
|
633
|
-
);
|
|
634
|
-
throw validationError;
|
|
635
|
-
}
|
|
636
|
-
if (error instanceof ValidationError) {
|
|
637
|
-
throw error;
|
|
638
|
-
}
|
|
639
|
-
throw new ValidationError(`Validation failed: ${error.message || "Unknown error"}`);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
export {
|
|
643
|
-
isValidLocations,
|
|
644
|
-
validateActionName,
|
|
645
|
-
validateComKey,
|
|
646
|
-
validateFacetName,
|
|
647
|
-
validateFinderName,
|
|
648
|
-
validateKey,
|
|
649
|
-
validateKeys,
|
|
650
|
-
validateLocations,
|
|
651
|
-
validateOperationParams,
|
|
652
|
-
validatePK,
|
|
653
|
-
validatePriKey,
|
|
654
|
-
validateQuery,
|
|
655
|
-
validateSchema
|
|
656
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { SchemaValidator } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* Validates data against a schema validator (Zod, Yup, etc.)
|
|
4
|
-
*
|
|
5
|
-
* Supports both synchronous and asynchronous validation.
|
|
6
|
-
* Transforms validator errors into Fjell ValidationError with FieldError[].
|
|
7
|
-
*
|
|
8
|
-
* @template T - The validated/parsed type
|
|
9
|
-
* @param data - The data to validate
|
|
10
|
-
* @param schema - Optional schema validator
|
|
11
|
-
* @returns Promise resolving to validated/parsed data
|
|
12
|
-
* @throws ValidationError if validation fails
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```typescript
|
|
16
|
-
* import { validateSchema } from '@fjell/core/validation';
|
|
17
|
-
* import { z } from 'zod';
|
|
18
|
-
*
|
|
19
|
-
* const schema = z.object({ name: z.string() });
|
|
20
|
-
* const validated = await validateSchema({ name: 'Alice' }, schema);
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export declare function validateSchema<T>(data: unknown, schema?: SchemaValidator<T>): Promise<T>;
|