@fjell/core 4.4.48 → 4.4.50
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 +92 -0
- package/dist/Coordinate.d.ts +7 -0
- package/dist/errors/ActionError.d.ts +51 -0
- package/dist/errors/BusinessLogicError.d.ts +4 -0
- package/dist/errors/DuplicateError.d.ts +4 -0
- package/dist/errors/NotFoundError.d.ts +4 -0
- package/dist/errors/PermissionError.d.ts +4 -0
- package/dist/errors/ValidationError.d.ts +4 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/event/emitter.d.ts +140 -0
- package/dist/event/events.d.ts +81 -0
- package/dist/event/index.d.ts +38 -0
- package/dist/event/matching.d.ts +54 -0
- package/dist/event/subscription.d.ts +74 -0
- package/dist/event/types.d.ts +186 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1584 -47
- package/dist/item/IUtils.d.ts +6 -3
- package/dist/operations/OperationContext.d.ts +10 -0
- package/dist/operations/Operations.d.ts +259 -0
- package/dist/operations/contained.d.ts +65 -0
- package/dist/operations/errorEnhancer.d.ts +79 -0
- package/dist/operations/index.d.ts +2 -0
- package/dist/operations/methods.d.ts +134 -0
- package/dist/operations/primary.d.ts +57 -0
- package/dist/operations/specialized.d.ts +41 -0
- package/dist/operations/wrappers/createActionWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createAllActionWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createAllFacetWrapper.d.ts +27 -0
- package/dist/operations/wrappers/createAllWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createCreateWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createFacetWrapper.d.ts +27 -0
- package/dist/operations/wrappers/createFindOneWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createFindWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createGetWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createOneWrapper.d.ts +38 -0
- package/dist/operations/wrappers/createRemoveWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createUpdateWrapper.d.ts +28 -0
- package/dist/operations/wrappers/createUpsertWrapper.d.ts +28 -0
- package/dist/operations/wrappers/index.d.ts +34 -0
- package/dist/operations/wrappers/types.d.ts +48 -0
- package/dist/validation/ItemValidator.d.ts +43 -0
- package/dist/validation/KeyValidator.d.ts +56 -0
- package/dist/validation/LocationValidator.d.ts +39 -0
- package/dist/validation/QueryValidator.d.ts +57 -0
- package/dist/validation/index.d.ts +15 -0
- package/dist/validation/index.js +501 -0
- package/dist/validation/types.d.ts +38 -0
- package/package.json +7 -2
- package/src/Coordinate.ts +35 -0
- package/src/errors/ActionError.ts +69 -0
- package/src/errors/BusinessLogicError.ts +24 -0
- package/src/errors/DuplicateError.ts +57 -0
- package/src/errors/NotFoundError.ts +24 -0
- package/src/errors/PermissionError.ts +31 -0
- package/src/errors/ValidationError.ts +27 -0
- package/src/errors/index.ts +7 -0
- package/src/event/emitter.ts +247 -0
- package/src/event/events.ts +178 -0
- package/src/event/index.ts +130 -0
- package/src/event/matching.ts +264 -0
- package/src/event/subscription.ts +181 -0
- package/src/event/types.ts +282 -0
- package/src/index.ts +57 -0
- package/src/item/IUtils.ts +9 -80
- package/src/operations/OperationContext.ts +12 -0
- package/src/operations/Operations.ts +357 -0
- package/src/operations/contained.ts +134 -0
- package/src/operations/errorEnhancer.ts +204 -0
- package/src/operations/index.ts +2 -0
- package/src/operations/methods.ts +363 -0
- package/src/operations/primary.ts +101 -0
- package/src/operations/specialized.ts +71 -0
- package/src/operations/wrappers/createActionWrapper.ts +108 -0
- package/src/operations/wrappers/createAllActionWrapper.ts +109 -0
- package/src/operations/wrappers/createAllFacetWrapper.ts +98 -0
- package/src/operations/wrappers/createAllWrapper.ts +103 -0
- package/src/operations/wrappers/createCreateWrapper.ts +117 -0
- package/src/operations/wrappers/createFacetWrapper.ts +97 -0
- package/src/operations/wrappers/createFindOneWrapper.ts +105 -0
- package/src/operations/wrappers/createFindWrapper.ts +105 -0
- package/src/operations/wrappers/createGetWrapper.ts +96 -0
- package/src/operations/wrappers/createOneWrapper.ts +128 -0
- package/src/operations/wrappers/createRemoveWrapper.ts +91 -0
- package/src/operations/wrappers/createUpdateWrapper.ts +106 -0
- package/src/operations/wrappers/createUpsertWrapper.ts +108 -0
- package/src/operations/wrappers/index.ts +39 -0
- package/src/operations/wrappers/types.ts +63 -0
- package/src/validation/ItemValidator.ts +131 -0
- package/src/validation/KeyValidator.ts +365 -0
- package/src/validation/LocationValidator.ts +136 -0
- package/src/validation/QueryValidator.ts +250 -0
- package/src/validation/index.ts +32 -0
- package/src/validation/types.ts +45 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query and parameter validation
|
|
3
|
+
*
|
|
4
|
+
* Validates ItemQuery and OperationParams structures.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ItemQuery } from "../item/ItemQuery";
|
|
8
|
+
import type { OperationParams } from "../operations/Operations";
|
|
9
|
+
import LibLogger from "../logger";
|
|
10
|
+
|
|
11
|
+
const logger = LibLogger.get('validation', 'QueryValidator');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validates that a query parameter is a valid ItemQuery object.
|
|
15
|
+
*
|
|
16
|
+
* @param query - The query to validate
|
|
17
|
+
* @param operation - The operation name (for error messages)
|
|
18
|
+
* @throws Error if query is invalid
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* validateQuery({ filter: { status: 'active' } }, 'one');
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const validateQuery = (
|
|
26
|
+
query: ItemQuery | undefined,
|
|
27
|
+
operation: string
|
|
28
|
+
): void => {
|
|
29
|
+
// undefined and null are allowed - they default to empty query
|
|
30
|
+
if (typeof query === 'undefined' || query === null) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (typeof query !== 'object') {
|
|
35
|
+
logger.error(`Invalid query type for ${operation}`, { query, type: typeof query });
|
|
36
|
+
throw new Error(
|
|
37
|
+
`[${operation}] Invalid query parameter.\n` +
|
|
38
|
+
`\n` +
|
|
39
|
+
`Expected: object or undefined\n` +
|
|
40
|
+
`Received: ${typeof query}\n` +
|
|
41
|
+
`\n` +
|
|
42
|
+
`Example valid queries:\n` +
|
|
43
|
+
` {}\n` +
|
|
44
|
+
` { filter: { status: 'active' } }\n` +
|
|
45
|
+
` { limit: 10, sort: { field: 'name', order: 'asc' } }`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (Array.isArray(query)) {
|
|
50
|
+
logger.error(`Query cannot be an array for ${operation}`, { query });
|
|
51
|
+
throw new Error(
|
|
52
|
+
`[${operation}] Invalid query parameter.\n` +
|
|
53
|
+
`\n` +
|
|
54
|
+
`Query cannot be an array.\n` +
|
|
55
|
+
`Received: ${JSON.stringify(query)}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
logger.debug(`Query validation passed for ${operation}`, { query });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validates that operation parameters are valid.
|
|
64
|
+
*
|
|
65
|
+
* @param params - The parameters to validate
|
|
66
|
+
* @param operation - The operation name (for error messages)
|
|
67
|
+
* @throws Error if parameters are invalid
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* validateOperationParams({ email: 'test@example.com' }, 'find');
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export const validateOperationParams = (
|
|
75
|
+
params: OperationParams | undefined,
|
|
76
|
+
operation: string
|
|
77
|
+
): void => {
|
|
78
|
+
// undefined is allowed - defaults to empty params
|
|
79
|
+
if (typeof params === 'undefined') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// null is not valid - must be object or undefined
|
|
84
|
+
if (params === null) {
|
|
85
|
+
logger.error(`Params cannot be null for ${operation}`, { params });
|
|
86
|
+
throw new Error(
|
|
87
|
+
`[${operation}] Invalid operation parameters.\n` +
|
|
88
|
+
`\n` +
|
|
89
|
+
`Parameters cannot be null.\n` +
|
|
90
|
+
`Expected: object or undefined\n` +
|
|
91
|
+
`Received: null\n` +
|
|
92
|
+
`\n` +
|
|
93
|
+
`Example valid parameters:\n` +
|
|
94
|
+
` {}\n` +
|
|
95
|
+
` { email: 'user@example.com' }\n` +
|
|
96
|
+
` { status: 'active', limit: 10 }`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof params !== 'object') {
|
|
101
|
+
logger.error(`Invalid params type for ${operation}`, { params, type: typeof params });
|
|
102
|
+
throw new Error(
|
|
103
|
+
`[${operation}] Invalid operation parameters.\n` +
|
|
104
|
+
`\n` +
|
|
105
|
+
`Expected: object or undefined\n` +
|
|
106
|
+
`Received: ${typeof params}\n` +
|
|
107
|
+
`\n` +
|
|
108
|
+
`Example valid parameters:\n` +
|
|
109
|
+
` {}\n` +
|
|
110
|
+
` { email: 'user@example.com' }\n` +
|
|
111
|
+
` { status: 'active', limit: 10 }`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (Array.isArray(params)) {
|
|
116
|
+
logger.error(`Params cannot be an array for ${operation}`, { params });
|
|
117
|
+
throw new Error(
|
|
118
|
+
`[${operation}] Invalid operation parameters.\n` +
|
|
119
|
+
`\n` +
|
|
120
|
+
`Parameters cannot be an array.\n` +
|
|
121
|
+
`Received: ${JSON.stringify(params)}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Validate parameter values are of allowed types
|
|
126
|
+
for (const [key, value] of Object.entries(params)) {
|
|
127
|
+
const valueType = typeof value;
|
|
128
|
+
const isValidType =
|
|
129
|
+
valueType === 'string' ||
|
|
130
|
+
valueType === 'number' ||
|
|
131
|
+
valueType === 'boolean' ||
|
|
132
|
+
value instanceof Date ||
|
|
133
|
+
(Array.isArray(value) && value.every(v =>
|
|
134
|
+
typeof v === 'string' ||
|
|
135
|
+
typeof v === 'number' ||
|
|
136
|
+
typeof v === 'boolean' ||
|
|
137
|
+
v instanceof Date
|
|
138
|
+
));
|
|
139
|
+
|
|
140
|
+
if (!isValidType) {
|
|
141
|
+
logger.error(`Invalid param value type for ${operation}`, { key, value, valueType });
|
|
142
|
+
throw new Error(
|
|
143
|
+
`[${operation}] Invalid value type for parameter "${key}".\n` +
|
|
144
|
+
`\n` +
|
|
145
|
+
`Allowed types: string, number, boolean, Date, or arrays of these types\n` +
|
|
146
|
+
`Received: ${valueType}\n` +
|
|
147
|
+
`Value: ${JSON.stringify(value)}`
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
logger.debug(`Operation params validation passed for ${operation}`, { params });
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Validates that a finder name is valid.
|
|
157
|
+
*
|
|
158
|
+
* @param finder - The finder name to validate
|
|
159
|
+
* @param operation - The operation name (for error messages)
|
|
160
|
+
* @throws Error if finder name is invalid
|
|
161
|
+
*/
|
|
162
|
+
export const validateFinderName = (
|
|
163
|
+
finder: string | undefined,
|
|
164
|
+
operation: string
|
|
165
|
+
): void => {
|
|
166
|
+
if (!finder || typeof finder !== 'string') {
|
|
167
|
+
logger.error(`Invalid finder name for ${operation}`, { finder, type: typeof finder });
|
|
168
|
+
throw new Error(
|
|
169
|
+
`[${operation}] Finder name must be a non-empty string.\n` +
|
|
170
|
+
`\n` +
|
|
171
|
+
`Received: ${JSON.stringify(finder)}`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (finder.trim().length === 0) {
|
|
176
|
+
logger.error(`Empty finder name for ${operation}`, { finder });
|
|
177
|
+
throw new Error(
|
|
178
|
+
`[${operation}] Finder name cannot be empty or whitespace only.\n` +
|
|
179
|
+
`\n` +
|
|
180
|
+
`Received: "${finder}"`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
logger.debug(`Finder name validation passed for ${operation}`, { finder });
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Validates that an action name is valid.
|
|
189
|
+
*
|
|
190
|
+
* @param action - The action name to validate
|
|
191
|
+
* @param operation - The operation name (for error messages)
|
|
192
|
+
* @throws Error if action name is invalid
|
|
193
|
+
*/
|
|
194
|
+
export const validateActionName = (
|
|
195
|
+
action: string | undefined,
|
|
196
|
+
operation: string
|
|
197
|
+
): void => {
|
|
198
|
+
if (!action || typeof action !== 'string') {
|
|
199
|
+
logger.error(`Invalid action name for ${operation}`, { action, type: typeof action });
|
|
200
|
+
throw new Error(
|
|
201
|
+
`[${operation}] Action name must be a non-empty string.\n` +
|
|
202
|
+
`\n` +
|
|
203
|
+
`Received: ${JSON.stringify(action)}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (action.trim().length === 0) {
|
|
208
|
+
logger.error(`Empty action name for ${operation}`, { action });
|
|
209
|
+
throw new Error(
|
|
210
|
+
`[${operation}] Action name cannot be empty or whitespace only.\n` +
|
|
211
|
+
`\n` +
|
|
212
|
+
`Received: "${action}"`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
logger.debug(`Action name validation passed for ${operation}`, { action });
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Validates that a facet name is valid.
|
|
221
|
+
*
|
|
222
|
+
* @param facet - The facet name to validate
|
|
223
|
+
* @param operation - The operation name (for error messages)
|
|
224
|
+
* @throws Error if facet name is invalid
|
|
225
|
+
*/
|
|
226
|
+
export const validateFacetName = (
|
|
227
|
+
facet: string | undefined,
|
|
228
|
+
operation: string
|
|
229
|
+
): void => {
|
|
230
|
+
if (!facet || typeof facet !== 'string') {
|
|
231
|
+
logger.error(`Invalid facet name for ${operation}`, { facet, type: typeof facet });
|
|
232
|
+
throw new Error(
|
|
233
|
+
`[${operation}] Facet name must be a non-empty string.\n` +
|
|
234
|
+
`\n` +
|
|
235
|
+
`Received: ${JSON.stringify(facet)}`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (facet.trim().length === 0) {
|
|
240
|
+
logger.error(`Empty facet name for ${operation}`, { facet });
|
|
241
|
+
throw new Error(
|
|
242
|
+
`[${operation}] Facet name cannot be empty or whitespace only.\n` +
|
|
243
|
+
`\n` +
|
|
244
|
+
`Received: "${facet}"`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
logger.debug(`Facet name validation passed for ${operation}`, { facet });
|
|
249
|
+
};
|
|
250
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation module
|
|
3
|
+
*
|
|
4
|
+
* Provides centralized validation functions for:
|
|
5
|
+
* - Location arrays (LocKeyArray validation against Coordinate hierarchy)
|
|
6
|
+
* - Keys (PriKey, ComKey validation)
|
|
7
|
+
* - Items (Item key type validation)
|
|
8
|
+
* - Queries (ItemQuery validation)
|
|
9
|
+
* - Operation parameters (OperationParams validation)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Types
|
|
13
|
+
export type { ValidationOptions, ValidationResult } from './types';
|
|
14
|
+
|
|
15
|
+
// Location validation
|
|
16
|
+
export { validateLocations, isValidLocations } from './LocationValidator';
|
|
17
|
+
|
|
18
|
+
// Key validation
|
|
19
|
+
export { validateKey, validatePriKey, validateComKey } from './KeyValidator';
|
|
20
|
+
|
|
21
|
+
// Item validation
|
|
22
|
+
export { validatePK, validateKeys } from './ItemValidator';
|
|
23
|
+
|
|
24
|
+
// Query and parameter validation
|
|
25
|
+
export {
|
|
26
|
+
validateQuery,
|
|
27
|
+
validateOperationParams,
|
|
28
|
+
validateFinderName,
|
|
29
|
+
validateActionName,
|
|
30
|
+
validateFacetName
|
|
31
|
+
} from './QueryValidator';
|
|
32
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared validation types and options
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for validation functions
|
|
7
|
+
*/
|
|
8
|
+
export interface ValidationOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Custom error message prefix
|
|
11
|
+
*/
|
|
12
|
+
errorPrefix?: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Whether to allow undefined (treated as empty array for location validation)
|
|
16
|
+
*/
|
|
17
|
+
allowUndefined?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether to throw errors or return validation results
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
throwOnError?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Result of a validation operation (for non-throwing mode)
|
|
28
|
+
*/
|
|
29
|
+
export interface ValidationResult {
|
|
30
|
+
/**
|
|
31
|
+
* Whether validation passed
|
|
32
|
+
*/
|
|
33
|
+
valid: boolean;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Error message if validation failed
|
|
37
|
+
*/
|
|
38
|
+
error?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Detailed validation context
|
|
42
|
+
*/
|
|
43
|
+
context?: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
|