@fjell/core 4.4.72 → 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 +980 -1008
- 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 -592
- package/dist/validation/schema.d.ts +0 -23
- package/dist/validation/types.d.ts +0 -69
package/dist/validation/index.js
DELETED
|
@@ -1,592 +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("Validating PK, Item is undefined", { item });
|
|
300
|
-
throw new Error("Validating PK, Item is undefined");
|
|
301
|
-
}
|
|
302
|
-
if (!item.key) {
|
|
303
|
-
logger4.error("Validating PK, Item does not have a key", { item });
|
|
304
|
-
throw new Error("Validating PK, Item does not have a key");
|
|
305
|
-
}
|
|
306
|
-
const keyTypeArray = toKeyTypeArray(item.key);
|
|
307
|
-
if (keyTypeArray[0] !== pkType) {
|
|
308
|
-
logger4.error("Key Type Array Mismatch", { keyTypeArray, pkType });
|
|
309
|
-
throw new Error(`Item does not have the correct primary key type. Expected ${pkType}, got ${keyTypeArray[0]}`);
|
|
310
|
-
}
|
|
311
|
-
return item;
|
|
312
|
-
};
|
|
313
|
-
var validatePK = (input, pkType) => {
|
|
314
|
-
logger4.trace("Checking Return Type", { input });
|
|
315
|
-
if (Array.isArray(input)) {
|
|
316
|
-
return input.map((item) => validatePKForItem(item, pkType));
|
|
317
|
-
}
|
|
318
|
-
return validatePKForItem(input, pkType);
|
|
319
|
-
};
|
|
320
|
-
var validateKeys = (item, keyTypes) => {
|
|
321
|
-
logger4.trace("Checking Return Type", { item });
|
|
322
|
-
if (!item) {
|
|
323
|
-
throw new Error("validating keys, item is undefined");
|
|
324
|
-
}
|
|
325
|
-
if (!item.key) {
|
|
326
|
-
throw new Error("validating keys, item does not have a key: " + JSON.stringify(item));
|
|
327
|
-
}
|
|
328
|
-
const keyTypeArray = toKeyTypeArray(item.key);
|
|
329
|
-
if (keyTypeArray.length !== keyTypes.length) {
|
|
330
|
-
throw new Error(`Item does not have the correct number of keys. Expected ${keyTypes.length}, but got ${keyTypeArray.length}`);
|
|
331
|
-
}
|
|
332
|
-
const match = JSON.stringify(keyTypeArray) === JSON.stringify(keyTypes);
|
|
333
|
-
if (!match) {
|
|
334
|
-
logger4.error("Key Type Array Mismatch", { keyTypeArray, thisKeyTypes: keyTypes });
|
|
335
|
-
throw new Error(`Item does not have the correct key types. Expected [${keyTypes.join(", ")}], but got [${keyTypeArray.join(", ")}]`);
|
|
336
|
-
}
|
|
337
|
-
return item;
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
// src/validation/QueryValidator.ts
|
|
341
|
-
var logger5 = logger_default.get("validation", "QueryValidator");
|
|
342
|
-
var validateQuery = (query, operation) => {
|
|
343
|
-
if (typeof query === "undefined" || query === null) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
if (typeof query !== "object") {
|
|
347
|
-
logger5.error(`Invalid query type for ${operation}`, { query, type: typeof query });
|
|
348
|
-
throw new Error(
|
|
349
|
-
`[${operation}] Invalid query parameter.
|
|
350
|
-
|
|
351
|
-
Expected: object or undefined
|
|
352
|
-
Received: ${typeof query}
|
|
353
|
-
|
|
354
|
-
Example valid queries:
|
|
355
|
-
{}
|
|
356
|
-
{ filter: { status: 'active' } }
|
|
357
|
-
{ limit: 10, sort: { field: 'name', order: 'asc' } }`
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
if (Array.isArray(query)) {
|
|
361
|
-
logger5.error(`Query cannot be an array for ${operation}`, { query });
|
|
362
|
-
throw new Error(
|
|
363
|
-
`[${operation}] Invalid query parameter.
|
|
364
|
-
|
|
365
|
-
Query cannot be an array.
|
|
366
|
-
Received: ${JSON.stringify(query)}`
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
logger5.debug(`Query validation passed for ${operation}`, { query });
|
|
370
|
-
};
|
|
371
|
-
var validateOperationParams = (params, operation) => {
|
|
372
|
-
if (typeof params === "undefined") {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
if (params === null) {
|
|
376
|
-
logger5.error(`Params cannot be null for ${operation}`, { params });
|
|
377
|
-
throw new Error(
|
|
378
|
-
`[${operation}] Invalid operation parameters.
|
|
379
|
-
|
|
380
|
-
Parameters cannot be null.
|
|
381
|
-
Expected: object or undefined
|
|
382
|
-
Received: null
|
|
383
|
-
|
|
384
|
-
Example valid parameters:
|
|
385
|
-
{}
|
|
386
|
-
{ email: 'user@example.com' }
|
|
387
|
-
{ status: 'active', limit: 10 }`
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
if (typeof params !== "object") {
|
|
391
|
-
logger5.error(`Invalid params type for ${operation}`, { params, type: typeof params });
|
|
392
|
-
throw new Error(
|
|
393
|
-
`[${operation}] Invalid operation parameters.
|
|
394
|
-
|
|
395
|
-
Expected: object or undefined
|
|
396
|
-
Received: ${typeof params}
|
|
397
|
-
|
|
398
|
-
Example valid parameters:
|
|
399
|
-
{}
|
|
400
|
-
{ email: 'user@example.com' }
|
|
401
|
-
{ status: 'active', limit: 10 }`
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
if (Array.isArray(params)) {
|
|
405
|
-
logger5.error(`Params cannot be an array for ${operation}`, { params });
|
|
406
|
-
throw new Error(
|
|
407
|
-
`[${operation}] Invalid operation parameters.
|
|
408
|
-
|
|
409
|
-
Parameters cannot be an array.
|
|
410
|
-
Received: ${JSON.stringify(params)}`
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
for (const [key, value] of Object.entries(params)) {
|
|
414
|
-
const valueType = typeof value;
|
|
415
|
-
const isValidType = valueType === "string" || valueType === "number" || valueType === "boolean" || value instanceof Date || Array.isArray(value) && value.every(
|
|
416
|
-
(v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" || v instanceof Date
|
|
417
|
-
);
|
|
418
|
-
if (!isValidType) {
|
|
419
|
-
logger5.error(`Invalid param value type for ${operation}`, { key, value, valueType });
|
|
420
|
-
throw new Error(
|
|
421
|
-
`[${operation}] Invalid value type for parameter "${key}".
|
|
422
|
-
|
|
423
|
-
Allowed types: string, number, boolean, Date, or arrays of these types
|
|
424
|
-
Received: ${valueType}
|
|
425
|
-
Value: ${JSON.stringify(value)}`
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
logger5.debug(`Operation params validation passed for ${operation}`, { params });
|
|
430
|
-
};
|
|
431
|
-
var validateFinderName = (finder, operation) => {
|
|
432
|
-
if (!finder || typeof finder !== "string") {
|
|
433
|
-
logger5.error(`Invalid finder name for ${operation}`, { finder, type: typeof finder });
|
|
434
|
-
throw new Error(
|
|
435
|
-
`[${operation}] Finder name must be a non-empty string.
|
|
436
|
-
|
|
437
|
-
Received: ${JSON.stringify(finder)}`
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
if (finder.trim().length === 0) {
|
|
441
|
-
logger5.error(`Empty finder name for ${operation}`, { finder });
|
|
442
|
-
throw new Error(
|
|
443
|
-
`[${operation}] Finder name cannot be empty or whitespace only.
|
|
444
|
-
|
|
445
|
-
Received: "${finder}"`
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
logger5.debug(`Finder name validation passed for ${operation}`, { finder });
|
|
449
|
-
};
|
|
450
|
-
var validateActionName = (action, operation) => {
|
|
451
|
-
if (!action || typeof action !== "string") {
|
|
452
|
-
logger5.error(`Invalid action name for ${operation}`, { action, type: typeof action });
|
|
453
|
-
throw new Error(
|
|
454
|
-
`[${operation}] Action name must be a non-empty string.
|
|
455
|
-
|
|
456
|
-
Received: ${JSON.stringify(action)}`
|
|
457
|
-
);
|
|
458
|
-
}
|
|
459
|
-
if (action.trim().length === 0) {
|
|
460
|
-
logger5.error(`Empty action name for ${operation}`, { action });
|
|
461
|
-
throw new Error(
|
|
462
|
-
`[${operation}] Action name cannot be empty or whitespace only.
|
|
463
|
-
|
|
464
|
-
Received: "${action}"`
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
logger5.debug(`Action name validation passed for ${operation}`, { action });
|
|
468
|
-
};
|
|
469
|
-
var validateFacetName = (facet, operation) => {
|
|
470
|
-
if (!facet || typeof facet !== "string") {
|
|
471
|
-
logger5.error(`Invalid facet name for ${operation}`, { facet, type: typeof facet });
|
|
472
|
-
throw new Error(
|
|
473
|
-
`[${operation}] Facet name must be a non-empty string.
|
|
474
|
-
|
|
475
|
-
Received: ${JSON.stringify(facet)}`
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
if (facet.trim().length === 0) {
|
|
479
|
-
logger5.error(`Empty facet name for ${operation}`, { facet });
|
|
480
|
-
throw new Error(
|
|
481
|
-
`[${operation}] Facet name cannot be empty or whitespace only.
|
|
482
|
-
|
|
483
|
-
Received: "${facet}"`
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
logger5.debug(`Facet name validation passed for ${operation}`, { facet });
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
// src/errors/ActionError.ts
|
|
490
|
-
var ActionError = class extends Error {
|
|
491
|
-
constructor(errorInfo, cause) {
|
|
492
|
-
super(errorInfo.message);
|
|
493
|
-
this.errorInfo = errorInfo;
|
|
494
|
-
this.name = "ActionError";
|
|
495
|
-
this.cause = cause;
|
|
496
|
-
if (!this.errorInfo.technical) {
|
|
497
|
-
this.errorInfo.technical = { timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
498
|
-
}
|
|
499
|
-
if (!this.errorInfo.technical.timestamp) {
|
|
500
|
-
this.errorInfo.technical.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
toJSON() {
|
|
504
|
-
return this.errorInfo;
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
// src/errors/ValidationError.ts
|
|
509
|
-
var ValidationError = class extends ActionError {
|
|
510
|
-
fieldErrors;
|
|
511
|
-
constructor(message, validOptions, suggestedAction, conflictingValue, fieldErrors) {
|
|
512
|
-
super({
|
|
513
|
-
code: "VALIDATION_ERROR",
|
|
514
|
-
message,
|
|
515
|
-
operation: { type: "create", name: "", params: {} },
|
|
516
|
-
// Will be filled by wrapper
|
|
517
|
-
context: { itemType: "" },
|
|
518
|
-
// Will be filled by wrapper
|
|
519
|
-
details: {
|
|
520
|
-
validOptions,
|
|
521
|
-
suggestedAction,
|
|
522
|
-
retryable: true,
|
|
523
|
-
conflictingValue,
|
|
524
|
-
fieldErrors
|
|
525
|
-
},
|
|
526
|
-
technical: {
|
|
527
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
this.fieldErrors = fieldErrors;
|
|
531
|
-
if (fieldErrors) {
|
|
532
|
-
if (!this.errorInfo.details) this.errorInfo.details = {};
|
|
533
|
-
this.errorInfo.details.fieldErrors = fieldErrors;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
// src/validation/schema.ts
|
|
539
|
-
async function validateSchema(data, schema) {
|
|
540
|
-
if (!schema) {
|
|
541
|
-
return data;
|
|
542
|
-
}
|
|
543
|
-
try {
|
|
544
|
-
if (schema.parseAsync) {
|
|
545
|
-
return await schema.parseAsync(data);
|
|
546
|
-
}
|
|
547
|
-
const result = schema.safeParse(data);
|
|
548
|
-
if (result.success) {
|
|
549
|
-
return result.data;
|
|
550
|
-
} else {
|
|
551
|
-
throw result.error;
|
|
552
|
-
}
|
|
553
|
-
} catch (error) {
|
|
554
|
-
if (error && Array.isArray(error.issues)) {
|
|
555
|
-
const fieldErrors = error.issues.map((issue) => ({
|
|
556
|
-
path: issue.path,
|
|
557
|
-
message: issue.message,
|
|
558
|
-
code: issue.code
|
|
559
|
-
}));
|
|
560
|
-
const validationError = new ValidationError(
|
|
561
|
-
"Schema validation failed",
|
|
562
|
-
// eslint-disable-next-line no-undefined
|
|
563
|
-
void 0,
|
|
564
|
-
// eslint-disable-next-line no-undefined
|
|
565
|
-
void 0,
|
|
566
|
-
// eslint-disable-next-line no-undefined
|
|
567
|
-
void 0,
|
|
568
|
-
fieldErrors
|
|
569
|
-
);
|
|
570
|
-
throw validationError;
|
|
571
|
-
}
|
|
572
|
-
if (error instanceof ValidationError) {
|
|
573
|
-
throw error;
|
|
574
|
-
}
|
|
575
|
-
throw new ValidationError(`Validation failed: ${error.message || "Unknown error"}`);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
export {
|
|
579
|
-
isValidLocations,
|
|
580
|
-
validateActionName,
|
|
581
|
-
validateComKey,
|
|
582
|
-
validateFacetName,
|
|
583
|
-
validateFinderName,
|
|
584
|
-
validateKey,
|
|
585
|
-
validateKeys,
|
|
586
|
-
validateLocations,
|
|
587
|
-
validateOperationParams,
|
|
588
|
-
validatePK,
|
|
589
|
-
validatePriKey,
|
|
590
|
-
validateQuery,
|
|
591
|
-
validateSchema
|
|
592
|
-
};
|
|
@@ -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>;
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared validation types and options
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Options for validation functions
|
|
6
|
-
*/
|
|
7
|
-
export interface ValidationOptions {
|
|
8
|
-
/**
|
|
9
|
-
* Custom error message prefix
|
|
10
|
-
*/
|
|
11
|
-
errorPrefix?: string;
|
|
12
|
-
/**
|
|
13
|
-
* Whether to allow undefined (treated as empty array for location validation)
|
|
14
|
-
*/
|
|
15
|
-
allowUndefined?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Whether to throw errors or return validation results
|
|
18
|
-
* @default true
|
|
19
|
-
*/
|
|
20
|
-
throwOnError?: boolean;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Result of a validation operation (for non-throwing mode)
|
|
24
|
-
*/
|
|
25
|
-
export interface ValidationResult {
|
|
26
|
-
/**
|
|
27
|
-
* Whether validation passed
|
|
28
|
-
*/
|
|
29
|
-
valid: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Error message if validation failed
|
|
32
|
-
*/
|
|
33
|
-
error?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Detailed validation context
|
|
36
|
-
*/
|
|
37
|
-
context?: Record<string, unknown>;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Generic interface for schema validators (Zod, Yup, Joi, etc.)
|
|
41
|
-
*
|
|
42
|
-
* This interface enables duck typing - any validator that implements
|
|
43
|
-
* these methods will work with validateSchema.
|
|
44
|
-
*
|
|
45
|
-
* @template T - The validated/parsed type
|
|
46
|
-
*/
|
|
47
|
-
export interface SchemaValidator<T> {
|
|
48
|
-
/**
|
|
49
|
-
* Synchronous parse method.
|
|
50
|
-
* Should throw an error if invalid, or return the parsed data.
|
|
51
|
-
*/
|
|
52
|
-
parse: (data: unknown) => T;
|
|
53
|
-
/**
|
|
54
|
-
* Safe parse method that returns a result object instead of throwing.
|
|
55
|
-
* Used as fallback if parseAsync is not available.
|
|
56
|
-
*/
|
|
57
|
-
safeParse: (data: unknown) => {
|
|
58
|
-
success: true;
|
|
59
|
-
data: T;
|
|
60
|
-
} | {
|
|
61
|
-
success: false;
|
|
62
|
-
error: any;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Optional asynchronous parse method.
|
|
66
|
-
* Preferred over parse/safeParse if available.
|
|
67
|
-
*/
|
|
68
|
-
parseAsync?: (data: unknown) => Promise<T>;
|
|
69
|
-
}
|