@fjell/core 4.4.49 → 4.4.51

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 (58) hide show
  1. package/dist/event/emitter.d.ts +140 -0
  2. package/dist/event/events.d.ts +81 -0
  3. package/dist/event/index.d.ts +38 -0
  4. package/dist/event/matching.d.ts +54 -0
  5. package/dist/event/subscription.d.ts +74 -0
  6. package/dist/event/types.d.ts +186 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +272 -0
  9. package/package.json +3 -3
  10. package/src/AItemService.ts +0 -38
  11. package/src/Coordinate.ts +0 -35
  12. package/src/dictionary.ts +0 -84
  13. package/src/errors/ActionError.ts +0 -69
  14. package/src/errors/BusinessLogicError.ts +0 -24
  15. package/src/errors/DuplicateError.ts +0 -57
  16. package/src/errors/NotFoundError.ts +0 -24
  17. package/src/errors/PermissionError.ts +0 -31
  18. package/src/errors/ValidationError.ts +0 -27
  19. package/src/errors/index.ts +0 -7
  20. package/src/index.ts +0 -66
  21. package/src/item/IFactory.ts +0 -122
  22. package/src/item/IQFactory.ts +0 -163
  23. package/src/item/IQUtils.ts +0 -392
  24. package/src/item/IUtils.ts +0 -40
  25. package/src/item/ItemQuery.ts +0 -88
  26. package/src/items.ts +0 -120
  27. package/src/key/KUtils.ts +0 -484
  28. package/src/keys.ts +0 -95
  29. package/src/logger.ts +0 -5
  30. package/src/operations/OperationContext.ts +0 -12
  31. package/src/operations/Operations.ts +0 -357
  32. package/src/operations/contained.ts +0 -134
  33. package/src/operations/errorEnhancer.ts +0 -204
  34. package/src/operations/index.ts +0 -2
  35. package/src/operations/methods.ts +0 -363
  36. package/src/operations/primary.ts +0 -101
  37. package/src/operations/specialized.ts +0 -71
  38. package/src/operations/wrappers/createActionWrapper.ts +0 -108
  39. package/src/operations/wrappers/createAllActionWrapper.ts +0 -109
  40. package/src/operations/wrappers/createAllFacetWrapper.ts +0 -98
  41. package/src/operations/wrappers/createAllWrapper.ts +0 -103
  42. package/src/operations/wrappers/createCreateWrapper.ts +0 -117
  43. package/src/operations/wrappers/createFacetWrapper.ts +0 -97
  44. package/src/operations/wrappers/createFindOneWrapper.ts +0 -105
  45. package/src/operations/wrappers/createFindWrapper.ts +0 -105
  46. package/src/operations/wrappers/createGetWrapper.ts +0 -96
  47. package/src/operations/wrappers/createOneWrapper.ts +0 -128
  48. package/src/operations/wrappers/createRemoveWrapper.ts +0 -91
  49. package/src/operations/wrappers/createUpdateWrapper.ts +0 -106
  50. package/src/operations/wrappers/createUpsertWrapper.ts +0 -108
  51. package/src/operations/wrappers/index.ts +0 -39
  52. package/src/operations/wrappers/types.ts +0 -63
  53. package/src/validation/ItemValidator.ts +0 -131
  54. package/src/validation/KeyValidator.ts +0 -365
  55. package/src/validation/LocationValidator.ts +0 -136
  56. package/src/validation/QueryValidator.ts +0 -250
  57. package/src/validation/index.ts +0 -32
  58. package/src/validation/types.ts +0 -45
package/dist/index.js CHANGED
@@ -1519,6 +1519,50 @@ function getErrorInfo(error) {
1519
1519
  };
1520
1520
  }
1521
1521
 
1522
+ // src/event/events.ts
1523
+ function isCreateEvent(event) {
1524
+ return event.eventType === "create";
1525
+ }
1526
+ function isUpdateEvent(event) {
1527
+ return event.eventType === "update";
1528
+ }
1529
+ function isDeleteEvent(event) {
1530
+ return event.eventType === "delete";
1531
+ }
1532
+ function isActionEvent(event) {
1533
+ return event.eventType === "action";
1534
+ }
1535
+
1536
+ // src/event/subscription.ts
1537
+ function isItemSubscription(subscription) {
1538
+ return "key" in subscription;
1539
+ }
1540
+ function isLocationSubscription(subscription) {
1541
+ return "kta" in subscription && "location" in subscription;
1542
+ }
1543
+ function generateSubscriptionId() {
1544
+ return `sub-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1545
+ }
1546
+ function createItemSubscription(key, options) {
1547
+ return {
1548
+ id: generateSubscriptionId(),
1549
+ key,
1550
+ eventTypes: options?.eventTypes,
1551
+ scopes: options?.scopes,
1552
+ query: options?.query
1553
+ };
1554
+ }
1555
+ function createLocationSubscription(kta, location, options) {
1556
+ return {
1557
+ id: generateSubscriptionId(),
1558
+ kta,
1559
+ location,
1560
+ eventTypes: options?.eventTypes,
1561
+ scopes: options?.scopes,
1562
+ query: options?.query
1563
+ };
1564
+ }
1565
+
1522
1566
  // src/operations/Operations.ts
1523
1567
  function isPriKey2(key) {
1524
1568
  return !("loc" in key) || !key.loc;
@@ -1527,6 +1571,203 @@ function isComKey2(key) {
1527
1571
  return "loc" in key && key.loc && Array.isArray(key.loc) && key.loc.length > 0;
1528
1572
  }
1529
1573
 
1574
+ // src/event/matching.ts
1575
+ function doesEventMatchSubscription(event, subscription) {
1576
+ if (!doesScopeMatch(event.scopes, subscription.scopes)) {
1577
+ return false;
1578
+ }
1579
+ if (!doesEventTypeMatch(event.eventType, subscription.eventTypes)) {
1580
+ return false;
1581
+ }
1582
+ if (isItemSubscription(subscription)) {
1583
+ return doesKeyMatch(event.key, subscription.key);
1584
+ } else if (isLocationSubscription(subscription)) {
1585
+ return doesKeyMatchLocation(event.key, subscription.kta, subscription.location);
1586
+ }
1587
+ return false;
1588
+ }
1589
+ function doesScopeMatch(eventScopes, subscriptionScopes) {
1590
+ if (!subscriptionScopes || subscriptionScopes.length === 0) {
1591
+ return true;
1592
+ }
1593
+ return subscriptionScopes.some(
1594
+ (requiredScope) => eventScopes.includes(requiredScope)
1595
+ );
1596
+ }
1597
+ function doesEventTypeMatch(eventType, subscriptionEventTypes) {
1598
+ if (!subscriptionEventTypes || subscriptionEventTypes.length === 0) {
1599
+ return true;
1600
+ }
1601
+ return subscriptionEventTypes.includes(eventType);
1602
+ }
1603
+ function doesKeyMatch(eventKey, subscriptionKey) {
1604
+ if (isPriKey2(eventKey) && isPriKey2(subscriptionKey)) {
1605
+ return eventKey.pk === subscriptionKey.pk && eventKey.kt === subscriptionKey.kt;
1606
+ }
1607
+ if (isComKey2(eventKey) && isComKey2(subscriptionKey)) {
1608
+ const eventComKey = eventKey;
1609
+ const subscriptionComKey = subscriptionKey;
1610
+ if (eventComKey.pk !== subscriptionComKey.pk || eventComKey.kt !== subscriptionComKey.kt) {
1611
+ return false;
1612
+ }
1613
+ if (eventComKey.loc.length !== subscriptionComKey.loc.length) {
1614
+ return false;
1615
+ }
1616
+ return eventComKey.loc.every((eventLocKey, index) => {
1617
+ const subLocKey = subscriptionComKey.loc[index];
1618
+ return eventLocKey.lk === subLocKey.lk && eventLocKey.kt === subLocKey.kt;
1619
+ });
1620
+ }
1621
+ return false;
1622
+ }
1623
+ function doesKeyMatchLocation(eventKey, subscriptionKta, subscriptionLocation) {
1624
+ const targetItemType = subscriptionKta[subscriptionKta.length - 1];
1625
+ if (eventKey.kt !== targetItemType) {
1626
+ return false;
1627
+ }
1628
+ if (isPriKey2(eventKey)) {
1629
+ return subscriptionLocation.length === 0;
1630
+ }
1631
+ if (isComKey2(eventKey)) {
1632
+ const comKey = eventKey;
1633
+ return doesLocationMatch(comKey.loc, subscriptionLocation, subscriptionKta);
1634
+ }
1635
+ return false;
1636
+ }
1637
+ function doesLocationMatch(eventLocation, subscriptionLocation, _subscriptionKta) {
1638
+ if (subscriptionLocation.length === 0) {
1639
+ return true;
1640
+ }
1641
+ if (eventLocation.length < subscriptionLocation.length) {
1642
+ return false;
1643
+ }
1644
+ for (let i = 0; i < subscriptionLocation.length; i++) {
1645
+ const eventLocKey = eventLocation[i];
1646
+ const subLocKey = subscriptionLocation[i];
1647
+ if (!eventLocKey || !subLocKey) {
1648
+ return false;
1649
+ }
1650
+ if (eventLocKey.lk !== subLocKey.lk || eventLocKey.kt !== subLocKey.kt) {
1651
+ return false;
1652
+ }
1653
+ }
1654
+ return true;
1655
+ }
1656
+ function findMatchingSubscriptions(event, subscriptions) {
1657
+ return subscriptions.filter(
1658
+ (subscription) => doesEventMatchSubscription(event, subscription)
1659
+ );
1660
+ }
1661
+ function extractLocationValues(location) {
1662
+ return location.map((locKey) => String(locKey.lk));
1663
+ }
1664
+ function compareLocationValues(location1, location2) {
1665
+ if (location1.length !== location2.length) {
1666
+ return false;
1667
+ }
1668
+ return location1.every((locKey1, index) => {
1669
+ const locKey2 = location2[index];
1670
+ return locKey1.lk === locKey2.lk && locKey1.kt === locKey2.kt;
1671
+ });
1672
+ }
1673
+
1674
+ // src/event/types.ts
1675
+ var STANDARD_EVENT_TYPES = {
1676
+ CREATE: "create",
1677
+ UPDATE: "update",
1678
+ DELETE: "delete",
1679
+ ACTION: "action"
1680
+ };
1681
+ var STANDARD_SCOPES = {
1682
+ FIRESTORE: "firestore",
1683
+ SEQUELIZE: "sequelize",
1684
+ POSTGRESQL: "postgresql",
1685
+ MYSQL: "mysql",
1686
+ MONGODB: "mongodb",
1687
+ REDIS: "redis"
1688
+ };
1689
+ var SubscriptionStatus = /* @__PURE__ */ ((SubscriptionStatus2) => {
1690
+ SubscriptionStatus2["PENDING"] = "pending";
1691
+ SubscriptionStatus2["ACTIVE"] = "active";
1692
+ SubscriptionStatus2["PAUSED"] = "paused";
1693
+ SubscriptionStatus2["ERROR"] = "error";
1694
+ SubscriptionStatus2["CANCELLED"] = "cancelled";
1695
+ return SubscriptionStatus2;
1696
+ })(SubscriptionStatus || {});
1697
+ var DEFAULT_EVENT_CONFIG = {
1698
+ maxBatchSize: 100,
1699
+ maxBatchWaitTime: 50,
1700
+ // 50ms
1701
+ maxRetryAttempts: 3,
1702
+ retryDelay: 1e3,
1703
+ // 1 second
1704
+ enableStats: true,
1705
+ maxSubscriptions: 1e3,
1706
+ subscriptionCleanupInterval: 3e5
1707
+ // 5 minutes
1708
+ };
1709
+ var EventSystemError = class extends Error {
1710
+ constructor(message, code, details) {
1711
+ super(message);
1712
+ this.code = code;
1713
+ this.details = details;
1714
+ this.name = "EventSystemError";
1715
+ }
1716
+ };
1717
+ var SubscriptionError = class extends EventSystemError {
1718
+ constructor(message, subscriptionId, details) {
1719
+ super(message, "SUBSCRIPTION_ERROR", { subscriptionId, ...details });
1720
+ this.subscriptionId = subscriptionId;
1721
+ this.name = "SubscriptionError";
1722
+ }
1723
+ };
1724
+ var EventEmissionError = class extends EventSystemError {
1725
+ constructor(message, eventType, details) {
1726
+ super(message, "EVENT_EMISSION_ERROR", { eventType, ...details });
1727
+ this.eventType = eventType;
1728
+ this.name = "EventEmissionError";
1729
+ }
1730
+ };
1731
+ var EventMatchingError = class extends EventSystemError {
1732
+ constructor(message, details) {
1733
+ super(message, "EVENT_MATCHING_ERROR", details);
1734
+ this.name = "EventMatchingError";
1735
+ }
1736
+ };
1737
+ function createEventSystemError(type, message, details) {
1738
+ switch (type) {
1739
+ case "subscription":
1740
+ return new SubscriptionError(message, details?.subscriptionId || "unknown", details);
1741
+ case "emission":
1742
+ return new EventEmissionError(message, details?.eventType || "unknown", details);
1743
+ case "matching":
1744
+ return new EventMatchingError(message, details);
1745
+ case "general":
1746
+ default:
1747
+ return new EventSystemError(message, "GENERAL_ERROR", details);
1748
+ }
1749
+ }
1750
+ function isEventSystemError(error) {
1751
+ return error instanceof EventSystemError;
1752
+ }
1753
+
1754
+ // src/event/index.ts
1755
+ var EVENT_SYSTEM_VERSION = "1.0.0";
1756
+ var SUPPORTED_EVENT_TYPES = [
1757
+ "create",
1758
+ "update",
1759
+ "delete",
1760
+ "action"
1761
+ ];
1762
+ var SUPPORTED_SCOPES = [
1763
+ "firestore",
1764
+ "sequelize",
1765
+ "postgresql",
1766
+ "mysql",
1767
+ "mongodb",
1768
+ "redis"
1769
+ ];
1770
+
1530
1771
  // src/operations/wrappers/createOneWrapper.ts
1531
1772
  var logger9 = logger_default.get("operations", "wrappers", "one");
1532
1773
  function createOneWrapper(coordinate, implementation, options = {}) {
@@ -2078,12 +2319,23 @@ export {
2078
2319
  AItemService,
2079
2320
  ActionError,
2080
2321
  BusinessLogicError,
2322
+ DEFAULT_EVENT_CONFIG,
2081
2323
  Dictionary,
2082
2324
  DuplicateError,
2325
+ EVENT_SYSTEM_VERSION,
2326
+ EventEmissionError,
2327
+ EventMatchingError,
2328
+ EventSystemError,
2083
2329
  IFactory,
2084
2330
  IQFactory,
2085
2331
  NotFoundError,
2086
2332
  PermissionError,
2333
+ STANDARD_EVENT_TYPES,
2334
+ STANDARD_SCOPES,
2335
+ SUPPORTED_EVENT_TYPES,
2336
+ SUPPORTED_SCOPES,
2337
+ SubscriptionError,
2338
+ SubscriptionStatus,
2087
2339
  ValidationError,
2088
2340
  abbrevAgg,
2089
2341
  abbrevCompoundCondition,
@@ -2093,6 +2345,7 @@ export {
2093
2345
  abbrevQuery,
2094
2346
  abbrevRef,
2095
2347
  cPK,
2348
+ compareLocationValues,
2096
2349
  constructPriKey,
2097
2350
  createActionWrapper,
2098
2351
  createAllActionWrapper,
@@ -2100,34 +2353,52 @@ export {
2100
2353
  createAllWrapper,
2101
2354
  createCoordinate,
2102
2355
  createCreateWrapper,
2356
+ createEventSystemError,
2103
2357
  createFacetWrapper,
2104
2358
  createFindOneWrapper,
2105
2359
  createFindWrapper,
2106
2360
  createGetWrapper,
2361
+ createItemSubscription,
2362
+ createLocationSubscription,
2107
2363
  createNormalizedHashFunction,
2108
2364
  createOneWrapper,
2109
2365
  createRemoveWrapper,
2110
2366
  createUpdateWrapper,
2111
2367
  createUpsertWrapper,
2368
+ doesEventMatchSubscription,
2369
+ doesEventTypeMatch,
2370
+ doesKeyMatch,
2371
+ doesKeyMatchLocation,
2372
+ doesLocationMatch,
2373
+ doesScopeMatch,
2112
2374
  enhanceError,
2113
2375
  executeWithContext,
2114
2376
  executeWithContextSync,
2115
2377
  extractKeyTypeArray,
2378
+ extractLocationValues,
2379
+ findMatchingSubscriptions,
2116
2380
  generateKeyArray,
2381
+ generateSubscriptionId,
2117
2382
  getErrorInfo,
2118
2383
  ikToLKA,
2119
2384
  isActionError,
2385
+ isActionEvent,
2120
2386
  isComItem,
2121
2387
  isComKey,
2122
2388
  isComKeyEqual,
2123
2389
  isComKeyEqualNormalized,
2124
2390
  isCondition,
2391
+ isCreateEvent,
2392
+ isDeleteEvent,
2393
+ isEventSystemError,
2125
2394
  isItemKey,
2126
2395
  isItemKeyEqual,
2127
2396
  isItemKeyEqualNormalized,
2397
+ isItemSubscription,
2128
2398
  isLocKey,
2129
2399
  isLocKeyEqual,
2130
2400
  isLocKeyEqualNormalized,
2401
+ isLocationSubscription,
2131
2402
  isComKey2 as isOperationComKey,
2132
2403
  isPriKey2 as isOperationPriKey,
2133
2404
  isPriItem,
@@ -2135,6 +2406,7 @@ export {
2135
2406
  isPriKeyEqual,
2136
2407
  isPriKeyEqualNormalized,
2137
2408
  isQueryMatch,
2409
+ isUpdateEvent,
2138
2410
  isValidComKey,
2139
2411
  isValidItemKey,
2140
2412
  isValidLocKey,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fjell/core",
3
3
  "description": "Core Item and Key Framework for Fjell",
4
- "version": "4.4.49",
4
+ "version": "4.4.51",
5
5
  "keywords": [
6
6
  "core",
7
7
  "fjell"
@@ -41,14 +41,14 @@
41
41
  "docs:test": "cd docs && npm run test"
42
42
  },
43
43
  "dependencies": {
44
- "@fjell/logging": "^4.4.49",
44
+ "@fjell/logging": "^4.4.50",
45
45
  "deepmerge": "^4.3.1",
46
46
  "luxon": "^3.7.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@eslint/eslintrc": "^3.3.1",
50
50
  "@eslint/js": "^9.32.0",
51
- "@fjell/eslint-config": "^1.1.25",
51
+ "@fjell/eslint-config": "^1.1.28",
52
52
  "@swc/core": "^1.13.2",
53
53
  "@tsconfig/recommended": "^1.0.10",
54
54
  "@types/luxon": "^3.6.2",
@@ -1,38 +0,0 @@
1
- import { AllItemTypeArrays } from "./keys";
2
-
3
- export class AItemService<
4
- S extends string,
5
- L1 extends string,
6
- L2 extends string = never,
7
- L3 extends string = never,
8
- L4 extends string = never,
9
- L5 extends string = never
10
- > {
11
-
12
- private pkType: S;
13
- private parentService: AItemService<L1, L2, L3, L4, L5, never> | null = null;
14
-
15
- constructor(
16
- pkType: S,
17
- parentService?: AItemService<L1, L2, L3, L4, L5, never>,
18
- ) {
19
- this.pkType = pkType;
20
- if (parentService) {
21
- this.parentService = parentService;
22
- }
23
- }
24
-
25
- public getPkType = (): S => {
26
- return this.pkType;
27
- }
28
-
29
- public getKeyTypes = (): AllItemTypeArrays<S, L1, L2, L3, L4, L5> => {
30
- let keyTypes: readonly string[] = [this.getPkType()];
31
-
32
- if (this.parentService) {
33
- keyTypes = keyTypes.concat(this.parentService.getKeyTypes());
34
- }
35
- return keyTypes as AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
36
- }
37
-
38
- }
package/src/Coordinate.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { ItemTypeArray } from "./keys";
2
- import LibLogger from "./logger";
3
-
4
- const logger = LibLogger.get("Coordinate");
5
-
6
- export interface Coordinate<
7
- S extends string,
8
- L1 extends string = never,
9
- L2 extends string = never,
10
- L3 extends string = never,
11
- L4 extends string = never,
12
- L5 extends string = never,
13
- > {
14
- kta: ItemTypeArray<S, L1, L2, L3, L4, L5>;
15
- scopes: string[];
16
- toString: () => string;
17
- }
18
-
19
- export const createCoordinate = <
20
- S extends string,
21
- L1 extends string = never,
22
- L2 extends string = never,
23
- L3 extends string = never,
24
- L4 extends string = never,
25
- L5 extends string = never,
26
- >(kta: ItemTypeArray<S, L1, L2, L3, L4, L5> | S, scopes: string[] = []): Coordinate<S, L1, L2, L3, L4, L5> => {
27
- const ktArray = Array.isArray(kta) ? kta : [kta];
28
- const toString = () => {
29
- logger.debug("toString", { kta, scopes });
30
- return `${ktArray.join(', ')} - ${scopes.join(', ')}`;
31
- }
32
- logger.debug("createCoordinate", { kta: ktArray, scopes, toString });
33
- return { kta: ktArray as ItemTypeArray<S, L1, L2, L3, L4, L5>, scopes, toString };
34
- }
35
-
package/src/dictionary.ts DELETED
@@ -1,84 +0,0 @@
1
- import LibLogger from "./logger";
2
-
3
- const logger = LibLogger.get("Dictionary");
4
-
5
- interface DictionaryEntry<T, V> {
6
- originalKey: T;
7
- value: V;
8
- }
9
-
10
- export class Dictionary<T, V> {
11
- protected map: { [key: string]: DictionaryEntry<T, V> } = {}
12
- protected hashFunction = (key: T) => JSON.stringify(key);
13
-
14
- constructor(map?: { [key: string]: V }, hashFunction?: (key: T) => string) {
15
- if (hashFunction) {
16
- this.hashFunction = hashFunction
17
- }
18
- if (map) {
19
- // Convert legacy map format to new format
20
- Object.entries(map).forEach(([hashedKey, value]) => {
21
- try {
22
- // Try to parse the key if it looks like JSON
23
- const originalKey = JSON.parse(hashedKey) as T;
24
- this.map[hashedKey] = { originalKey, value };
25
- } catch {
26
- // If parsing fails, we can't recover the original key
27
- logger.warning('Cannot recover original key from legacy map entry', { hashedKey });
28
- }
29
- });
30
- }
31
- }
32
-
33
- public set(key: T, item: V): void {
34
- logger.trace('set', { key, item });
35
- const hashedKey = this.hashFunction(key);
36
- this.map[hashedKey] = { originalKey: key, value: item };
37
- }
38
-
39
- public get(key: T): V | null {
40
- logger.trace('get', { key });
41
- const hashedKey = this.hashFunction(key);
42
- const entry = this.map[hashedKey];
43
- // Check if entry exists AND the original key matches the requested key
44
- return entry && this.keysEqual(entry.originalKey, key) ? entry.value : null;
45
- }
46
-
47
- private keysEqual(key1: T, key2: T): boolean {
48
- // For basic equality check - this works for primitives and object references
49
- // For deep equality, users can provide a custom hash function that avoids collisions
50
- return key1 === key2;
51
- }
52
-
53
- public delete(key: T): void {
54
- logger.trace('delete', { key });
55
- const hashedKey = this.hashFunction(key);
56
- delete this.map[hashedKey];
57
- }
58
-
59
- public keys(): T[] {
60
- return Object.values(this.map).map(entry => entry.originalKey);
61
- }
62
-
63
- public values(): V[] {
64
- return Object.values(this.map).map(entry => entry.value);
65
- }
66
-
67
- public includesKey(key: T): boolean {
68
- const hashedKey = this.hashFunction(key);
69
- const entry = this.map[hashedKey];
70
- return entry ? this.keysEqual(entry.originalKey, key) : false;
71
- }
72
-
73
- public clone(): Dictionary<T, V> {
74
- const clonedMap: { [key: string]: V } = {};
75
- Object.entries(this.map).forEach(([hashedKey, entry]) => {
76
- clonedMap[hashedKey] = entry.value;
77
- });
78
-
79
- const clone = new Dictionary<T, V>(clonedMap, this.hashFunction);
80
- // Copy the entries directly to preserve original keys
81
- clone.map = Object.assign({}, this.map);
82
- return clone;
83
- }
84
- }
@@ -1,69 +0,0 @@
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
-
@@ -1,24 +0,0 @@
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
-
@@ -1,57 +0,0 @@
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
-
@@ -1,24 +0,0 @@
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
-