@fjell/core 4.4.47 → 4.4.49

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 (83) hide show
  1. package/README.md +92 -0
  2. package/dist/Coordinate.d.ts +7 -0
  3. package/dist/errors/ActionError.d.ts +51 -0
  4. package/dist/errors/BusinessLogicError.d.ts +4 -0
  5. package/dist/errors/DuplicateError.d.ts +4 -0
  6. package/dist/errors/NotFoundError.d.ts +4 -0
  7. package/dist/errors/PermissionError.d.ts +4 -0
  8. package/dist/errors/ValidationError.d.ts +4 -0
  9. package/dist/errors/index.d.ts +6 -0
  10. package/dist/index.d.ts +11 -0
  11. package/dist/index.js +1314 -49
  12. package/dist/item/IUtils.d.ts +6 -3
  13. package/dist/operations/OperationContext.d.ts +10 -0
  14. package/dist/operations/Operations.d.ts +259 -0
  15. package/dist/operations/contained.d.ts +65 -0
  16. package/dist/operations/errorEnhancer.d.ts +79 -0
  17. package/dist/operations/index.d.ts +2 -0
  18. package/dist/operations/methods.d.ts +134 -0
  19. package/dist/operations/primary.d.ts +57 -0
  20. package/dist/operations/specialized.d.ts +41 -0
  21. package/dist/operations/wrappers/createActionWrapper.d.ts +28 -0
  22. package/dist/operations/wrappers/createAllActionWrapper.d.ts +28 -0
  23. package/dist/operations/wrappers/createAllFacetWrapper.d.ts +27 -0
  24. package/dist/operations/wrappers/createAllWrapper.d.ts +28 -0
  25. package/dist/operations/wrappers/createCreateWrapper.d.ts +28 -0
  26. package/dist/operations/wrappers/createFacetWrapper.d.ts +27 -0
  27. package/dist/operations/wrappers/createFindOneWrapper.d.ts +28 -0
  28. package/dist/operations/wrappers/createFindWrapper.d.ts +28 -0
  29. package/dist/operations/wrappers/createGetWrapper.d.ts +28 -0
  30. package/dist/operations/wrappers/createOneWrapper.d.ts +38 -0
  31. package/dist/operations/wrappers/createRemoveWrapper.d.ts +28 -0
  32. package/dist/operations/wrappers/createUpdateWrapper.d.ts +28 -0
  33. package/dist/operations/wrappers/createUpsertWrapper.d.ts +28 -0
  34. package/dist/operations/wrappers/index.d.ts +34 -0
  35. package/dist/operations/wrappers/types.d.ts +48 -0
  36. package/dist/validation/ItemValidator.d.ts +43 -0
  37. package/dist/validation/KeyValidator.d.ts +56 -0
  38. package/dist/validation/LocationValidator.d.ts +39 -0
  39. package/dist/validation/QueryValidator.d.ts +57 -0
  40. package/dist/validation/index.d.ts +15 -0
  41. package/dist/validation/index.js +501 -0
  42. package/dist/validation/types.d.ts +38 -0
  43. package/package.json +7 -2
  44. package/src/Coordinate.ts +35 -0
  45. package/src/errors/ActionError.ts +69 -0
  46. package/src/errors/BusinessLogicError.ts +24 -0
  47. package/src/errors/DuplicateError.ts +57 -0
  48. package/src/errors/NotFoundError.ts +24 -0
  49. package/src/errors/PermissionError.ts +31 -0
  50. package/src/errors/ValidationError.ts +27 -0
  51. package/src/errors/index.ts +7 -0
  52. package/src/index.ts +53 -0
  53. package/src/item/IUtils.ts +9 -80
  54. package/src/key/KUtils.ts +2 -2
  55. package/src/operations/OperationContext.ts +12 -0
  56. package/src/operations/Operations.ts +357 -0
  57. package/src/operations/contained.ts +134 -0
  58. package/src/operations/errorEnhancer.ts +204 -0
  59. package/src/operations/index.ts +2 -0
  60. package/src/operations/methods.ts +363 -0
  61. package/src/operations/primary.ts +101 -0
  62. package/src/operations/specialized.ts +71 -0
  63. package/src/operations/wrappers/createActionWrapper.ts +108 -0
  64. package/src/operations/wrappers/createAllActionWrapper.ts +109 -0
  65. package/src/operations/wrappers/createAllFacetWrapper.ts +98 -0
  66. package/src/operations/wrappers/createAllWrapper.ts +103 -0
  67. package/src/operations/wrappers/createCreateWrapper.ts +117 -0
  68. package/src/operations/wrappers/createFacetWrapper.ts +97 -0
  69. package/src/operations/wrappers/createFindOneWrapper.ts +105 -0
  70. package/src/operations/wrappers/createFindWrapper.ts +105 -0
  71. package/src/operations/wrappers/createGetWrapper.ts +96 -0
  72. package/src/operations/wrappers/createOneWrapper.ts +128 -0
  73. package/src/operations/wrappers/createRemoveWrapper.ts +91 -0
  74. package/src/operations/wrappers/createUpdateWrapper.ts +106 -0
  75. package/src/operations/wrappers/createUpsertWrapper.ts +108 -0
  76. package/src/operations/wrappers/index.ts +39 -0
  77. package/src/operations/wrappers/types.ts +63 -0
  78. package/src/validation/ItemValidator.ts +131 -0
  79. package/src/validation/KeyValidator.ts +365 -0
  80. package/src/validation/LocationValidator.ts +136 -0
  81. package/src/validation/QueryValidator.ts +250 -0
  82. package/src/validation/index.ts +32 -0
  83. package/src/validation/types.ts +45 -0
@@ -0,0 +1,69 @@
1
+ export interface ErrorInfo {
2
+ code: string;
3
+ message: string;
4
+ operation: {
5
+ type: 'get' | 'create' | 'update' | 'remove' | 'upsert' |
6
+ 'all' | 'one' | 'find' | 'findOne' |
7
+ 'action' | 'allAction' | 'facet' | 'allFacet';
8
+ name: string;
9
+ params: Record<string, any>;
10
+ };
11
+ context: {
12
+ itemType: string;
13
+ key?: {
14
+ primary?: string | number;
15
+ composite?: {
16
+ sk: string | number;
17
+ kta: string[];
18
+ locations?: Array<{ lk: string | number; kt: string }>;
19
+ };
20
+ };
21
+ affectedItems?: Array<{
22
+ id: string | number;
23
+ type: string;
24
+ displayName?: string;
25
+ }>;
26
+ parentLocation?: {
27
+ id: string | number;
28
+ type: string;
29
+ };
30
+ requiredPermission?: string;
31
+ };
32
+ details?: {
33
+ validOptions?: string[];
34
+ suggestedAction?: string;
35
+ retryable?: boolean;
36
+ conflictingValue?: any;
37
+ expectedValue?: any;
38
+ };
39
+ technical?: {
40
+ timestamp: string;
41
+ requestId?: string;
42
+ stackTrace?: string;
43
+ cause?: any;
44
+ };
45
+ }
46
+
47
+ export class ActionError extends Error {
48
+ constructor(
49
+ public readonly errorInfo: ErrorInfo,
50
+ cause?: Error
51
+ ) {
52
+ super(errorInfo.message);
53
+ this.name = 'ActionError';
54
+ this.cause = cause;
55
+
56
+ // Ensure timestamp is always set
57
+ if (!this.errorInfo.technical) {
58
+ this.errorInfo.technical = { timestamp: new Date().toISOString() };
59
+ }
60
+ if (!this.errorInfo.technical.timestamp) {
61
+ this.errorInfo.technical.timestamp = new Date().toISOString();
62
+ }
63
+ }
64
+
65
+ toJSON(): ErrorInfo {
66
+ return this.errorInfo;
67
+ }
68
+ }
69
+
@@ -0,0 +1,24 @@
1
+ import { ActionError } from './ActionError';
2
+
3
+ export class BusinessLogicError extends ActionError {
4
+ constructor(
5
+ message: string,
6
+ suggestedAction?: string,
7
+ retryable: boolean = false
8
+ ) {
9
+ super({
10
+ code: 'BUSINESS_LOGIC_ERROR',
11
+ message,
12
+ operation: { type: 'action', name: '', params: {} },
13
+ context: { itemType: '' },
14
+ details: {
15
+ suggestedAction,
16
+ retryable
17
+ },
18
+ technical: {
19
+ timestamp: new Date().toISOString()
20
+ }
21
+ });
22
+ }
23
+ }
24
+
@@ -0,0 +1,57 @@
1
+ import { ActionError } from './ActionError';
2
+
3
+ export class DuplicateError extends ActionError {
4
+ constructor(
5
+ message: string,
6
+ existingItemIdOrKey?: string | number | any,
7
+ duplicateField?: string
8
+ ) {
9
+ // Extract ID and build key info
10
+ let existingItemId: string | number | null = null;
11
+ let keyInfo: any = null;
12
+
13
+ if (typeof existingItemIdOrKey === 'object' && existingItemIdOrKey !== null) {
14
+ // It's a key object - extract the primary key value and build proper key structure
15
+ existingItemId = existingItemIdOrKey.pk || existingItemIdOrKey.id || existingItemIdOrKey.primary || null;
16
+
17
+ // Build key info with primary field set
18
+ if (existingItemId !== null) {
19
+ keyInfo = {
20
+ primary: existingItemId,
21
+ ...existingItemIdOrKey
22
+ };
23
+ } else {
24
+ keyInfo = existingItemIdOrKey;
25
+ }
26
+ } else if (typeof existingItemIdOrKey !== 'undefined') {
27
+ // It's a simple ID
28
+ existingItemId = existingItemIdOrKey;
29
+ keyInfo = { primary: existingItemId };
30
+ }
31
+
32
+ super({
33
+ code: 'DUPLICATE_ERROR',
34
+ message,
35
+ operation: { type: 'create', name: '', params: {} },
36
+ context: {
37
+ itemType: '',
38
+ ...(keyInfo && { key: keyInfo }),
39
+ ...(existingItemId && {
40
+ affectedItems: [{
41
+ id: existingItemId,
42
+ type: '',
43
+ displayName: `Existing item with ${duplicateField || 'key'}`
44
+ }]
45
+ })
46
+ },
47
+ details: {
48
+ retryable: false,
49
+ conflictingValue: duplicateField
50
+ },
51
+ technical: {
52
+ timestamp: new Date().toISOString()
53
+ }
54
+ });
55
+ }
56
+ }
57
+
@@ -0,0 +1,24 @@
1
+ import { ActionError } from './ActionError';
2
+
3
+ export class NotFoundError extends ActionError {
4
+ constructor(
5
+ message: string,
6
+ itemType: string,
7
+ key?: any
8
+ ) {
9
+ super({
10
+ code: 'NOT_FOUND',
11
+ message,
12
+ operation: { type: 'get', name: '', params: {} },
13
+ context: {
14
+ itemType,
15
+ key: typeof key === 'object' ? key : { primary: key }
16
+ },
17
+ details: { retryable: false },
18
+ technical: {
19
+ timestamp: new Date().toISOString()
20
+ }
21
+ });
22
+ }
23
+ }
24
+
@@ -0,0 +1,31 @@
1
+ import { ActionError } from './ActionError';
2
+
3
+ export class PermissionError extends ActionError {
4
+ constructor(
5
+ message: string,
6
+ requiredPermission?: string,
7
+ currentPermissions?: string[]
8
+ ) {
9
+ super({
10
+ code: 'PERMISSION_DENIED',
11
+ message,
12
+ operation: { type: 'action', name: '', params: {} },
13
+ context: {
14
+ itemType: '',
15
+ ...(requiredPermission && { requiredPermission })
16
+ },
17
+ details: {
18
+ ...(requiredPermission && {
19
+ suggestedAction: `Required permission: ${requiredPermission}`,
20
+ expectedValue: requiredPermission
21
+ }),
22
+ ...(currentPermissions && { conflictingValue: currentPermissions }),
23
+ retryable: false
24
+ },
25
+ technical: {
26
+ timestamp: new Date().toISOString()
27
+ }
28
+ });
29
+ }
30
+ }
31
+
@@ -0,0 +1,27 @@
1
+ import { ActionError } from './ActionError';
2
+
3
+ export class ValidationError extends ActionError {
4
+ constructor(
5
+ message: string,
6
+ validOptions?: string[],
7
+ suggestedAction?: string,
8
+ conflictingValue?: any
9
+ ) {
10
+ super({
11
+ code: 'VALIDATION_ERROR',
12
+ message,
13
+ operation: { type: 'create', name: '', params: {} }, // Will be filled by wrapper
14
+ context: { itemType: '' }, // Will be filled by wrapper
15
+ details: {
16
+ validOptions,
17
+ suggestedAction,
18
+ retryable: true,
19
+ conflictingValue
20
+ },
21
+ technical: {
22
+ timestamp: new Date().toISOString()
23
+ }
24
+ });
25
+ }
26
+ }
27
+
@@ -0,0 +1,7 @@
1
+ export * from './ActionError';
2
+ export * from './ValidationError';
3
+ export * from './NotFoundError';
4
+ export * from './BusinessLogicError';
5
+ export * from './PermissionError';
6
+ export * from './DuplicateError';
7
+
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./dictionary";
2
2
  export * from "./keys";
3
3
  export * from "./items";
4
+ export * from "./Coordinate";
4
5
  export { IFactory } from "./item/IFactory";
5
6
  export { AItemService } from "./AItemService";
6
7
 
@@ -11,3 +12,55 @@ export * from './item/IQFactory';
11
12
  export * from './item/IQUtils';
12
13
  export * from './item/IUtils';
13
14
  export * from './item/ItemQuery';
15
+
16
+ // Validation module
17
+ export * from './validation';
18
+
19
+ // Error types and handling
20
+ export * from './errors';
21
+ export * from './operations';
22
+
23
+ // Operations interfaces
24
+ export type {
25
+ Operations,
26
+ OperationParams,
27
+ AffectedKeys,
28
+ CreateOptions
29
+ } from './operations/Operations';
30
+ export {
31
+ isPriKey as isOperationPriKey,
32
+ isComKey as isOperationComKey
33
+ } from './operations/Operations';
34
+ export type {
35
+ GetMethod,
36
+ CreateMethod,
37
+ UpdateMethod,
38
+ RemoveMethod,
39
+ UpsertMethod,
40
+ AllMethod,
41
+ OneMethod,
42
+ FindMethod,
43
+ FindOneMethod,
44
+ FinderMethod,
45
+ ActionMethod,
46
+ ActionOperationMethod,
47
+ AllActionMethod,
48
+ AllActionOperationMethod,
49
+ FacetMethod,
50
+ FacetOperationMethod,
51
+ AllFacetMethod,
52
+ AllFacetOperationMethod,
53
+ OperationsExtensions
54
+ } from './operations/methods';
55
+
56
+ // Operation wrappers - automatic validation for all operations
57
+ export * from './operations/wrappers';
58
+ // Core architectural patterns
59
+ export type { PrimaryOperations } from './operations/primary';
60
+ export type { ContainedOperations } from './operations/contained';
61
+
62
+ // UI usage patterns (React providers, etc.)
63
+ export type {
64
+ CollectionOperations,
65
+ InstanceOperations
66
+ } from './operations/specialized';
@@ -1,88 +1,17 @@
1
1
  /* eslint-disable indent */
2
2
 
3
3
  import { Item } from "../items";
4
- import { isComKey, isPriKey, toKeyTypeArray } from "../key/KUtils";
5
- import { AllItemTypeArrays, ComKey, PriKey } from "../keys";
4
+ import { isComKey, isPriKey } from "../key/KUtils";
5
+ import { ComKey, PriKey } from "../keys";
6
6
 
7
- import LibLogger from '../logger';
7
+ /**
8
+ * @deprecated Use validatePK from @fjell/core/validation instead
9
+ * Re-exported for backward compatibility
10
+ */
11
+ export { validatePK, validateKeys } from '../validation/ItemValidator';
8
12
 
9
- const logger = LibLogger.get('IUtils');
10
-
11
- const validatePKForItem = <
12
- S extends string,
13
- L1 extends string = never,
14
- L2 extends string = never,
15
- L3 extends string = never,
16
- L4 extends string = never,
17
- L5 extends string = never,
18
- >(item: Item<S, L1, L2, L3, L4, L5>, pkType: S): Item<S, L1, L2, L3, L4, L5> => {
19
- if (!item) {
20
- logger.error('Validating PK, Item is undefined', { item });
21
- throw new Error('Validating PK, Item is undefined');
22
- }
23
- if (!item.key) {
24
- logger.error('Validating PK, Item does not have a key', { item });
25
- throw new Error('Validating PK, Item does not have a key');
26
- }
27
-
28
- const keyTypeArray = toKeyTypeArray(item.key as ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>);
29
- if (keyTypeArray[0] !== pkType) {
30
- logger.error('Key Type Array Mismatch', { keyTypeArray, pkType });
31
- throw new Error(`Item does not have the correct primary key type. Expected ${pkType}, got ${keyTypeArray[0]}`);
32
- }
33
- return item;
34
- };
35
-
36
- export const validatePK = <
37
- S extends string,
38
- L1 extends string = never,
39
- L2 extends string = never,
40
- L3 extends string = never,
41
- L4 extends string = never,
42
- L5 extends string = never,
43
- >(
44
- input: Item<S, L1, L2, L3, L4, L5> | Item<S, L1, L2, L3, L4, L5>[],
45
- pkType: S,
46
- ): Item<S, L1, L2, L3, L4, L5> | Item<S, L1, L2, L3, L4, L5>[] => {
47
- logger.trace('Checking Return Type', { input });
48
-
49
- if (Array.isArray(input)) {
50
- return input.map((item) => validatePKForItem(item, pkType));
51
- }
52
- return validatePKForItem(input, pkType);
53
- };
54
-
55
- export const validateKeys = <
56
- S extends string,
57
- L1 extends string = never,
58
- L2 extends string = never,
59
- L3 extends string = never,
60
- L4 extends string = never,
61
- L5 extends string = never,
62
- >(
63
- item: Item<S, L1, L2, L3, L4, L5>,
64
- keyTypes: AllItemTypeArrays<S, L1, L2, L3, L4, L5>,
65
- ): Item<S, L1, L2, L3, L4, L5> => {
66
- logger.trace('Checking Return Type', { item });
67
- if (!item) {
68
- throw new Error('validating keys, item is undefined');
69
- }
70
- if (!item.key) {
71
- throw new Error('validating keys, item does not have a key: ' + JSON.stringify(item));
72
- }
73
-
74
- const keyTypeArray = toKeyTypeArray(item.key as ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>);
75
- if (keyTypeArray.length !== keyTypes.length) {
76
- throw new Error(`Item does not have the correct number of keys. Expected ${keyTypes.length}, but got ${keyTypeArray.length}`);
77
- }
78
-
79
- const match: boolean = JSON.stringify(keyTypeArray) === JSON.stringify(keyTypes);
80
- if (!match) {
81
- logger.error('Key Type Array Mismatch', { keyTypeArray, thisKeyTypes: keyTypes });
82
- throw new Error(`Item does not have the correct key types. Expected [${keyTypes.join(', ')}], but got [${keyTypeArray.join(', ')}]`);
83
- }
84
- return item;
85
- };
13
+ // validatePK and validateKeys have been moved to ../validation/ItemValidator.ts
14
+ // They are re-exported above for backward compatibility
86
15
 
87
16
  export const isPriItem = <
88
17
  S extends string,
package/src/key/KUtils.ts CHANGED
@@ -192,13 +192,13 @@ export const isItemKey = (key: any): boolean => {
192
192
  export const isComKey = (key: any): boolean => {
193
193
  logger.trace('isComKey', { key });
194
194
  return key !== undefined &&
195
- (key.pk !== undefined && key.kt !== undefined) && (key.loc !== undefined && key.loc.length > 0);
195
+ (key.pk !== undefined && key.kt !== undefined) && (key.loc !== undefined && Array.isArray(key.loc));
196
196
  }
197
197
 
198
198
  export const isPriKey = (key: any): boolean => {
199
199
  logger.trace('isPriKey', { key });
200
200
  return key !== undefined &&
201
- (key.pk !== undefined && key.kt !== undefined) && (key.loc === undefined || key.loc.length === 0);
201
+ (key.pk !== undefined && key.kt !== undefined) && (key.loc === undefined);
202
202
  }
203
203
 
204
204
  export const isLocKey = (key: any): boolean => {
@@ -0,0 +1,12 @@
1
+ import { ComKey, LocKeyArray, PriKey } from '../keys';
2
+ import type { ErrorInfo } from '../errors/ActionError';
3
+
4
+ export interface OperationContext {
5
+ itemType: string;
6
+ operationType: ErrorInfo['operation']['type'];
7
+ operationName: string;
8
+ params: Record<string, any>;
9
+ key?: PriKey<any> | ComKey<any, any, any, any, any, any>;
10
+ locations?: LocKeyArray<any, any, any, any, any>;
11
+ }
12
+