@karmaniverous/entity-manager 6.4.2 → 6.4.4

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 (39) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/EntityManager.js +3 -1
  3. package/dist/cjs/addKeys.js +12 -0
  4. package/dist/cjs/decodeEntityElement.js +12 -0
  5. package/dist/cjs/decodeGeneratedProperty.js +7 -0
  6. package/dist/cjs/dehydrateIndexItem.js +13 -0
  7. package/dist/cjs/dehydratePageKeyMap.js +14 -0
  8. package/dist/cjs/encodeEntityElement.js +8 -0
  9. package/dist/cjs/encodeGeneratedProperty.js +12 -0
  10. package/dist/cjs/getHashKeySpace.js +12 -0
  11. package/dist/cjs/index.js +0 -2
  12. package/dist/cjs/query.js +26 -0
  13. package/dist/cjs/rehydrateIndexItem.js +14 -0
  14. package/dist/cjs/rehydratePageKeyMap.js +12 -0
  15. package/dist/cjs/removeKeys.js +7 -0
  16. package/dist/cjs/unwrapIndex.js +2 -0
  17. package/dist/cjs/updateItemHashKey.js +17 -0
  18. package/dist/cjs/updateItemRangeKey.js +17 -0
  19. package/dist/index.d.ts +19 -80
  20. package/dist/mjs/EntityManager.js +3 -1
  21. package/dist/mjs/addKeys.js +12 -0
  22. package/dist/mjs/decodeEntityElement.js +12 -0
  23. package/dist/mjs/decodeGeneratedProperty.js +7 -0
  24. package/dist/mjs/dehydrateIndexItem.js +13 -0
  25. package/dist/mjs/dehydratePageKeyMap.js +14 -0
  26. package/dist/mjs/encodeEntityElement.js +8 -0
  27. package/dist/mjs/encodeGeneratedProperty.js +12 -0
  28. package/dist/mjs/getHashKeySpace.js +12 -0
  29. package/dist/mjs/index.js +0 -1
  30. package/dist/mjs/query.js +26 -0
  31. package/dist/mjs/rehydrateIndexItem.js +14 -0
  32. package/dist/mjs/rehydratePageKeyMap.js +12 -0
  33. package/dist/mjs/removeKeys.js +7 -0
  34. package/dist/mjs/unwrapIndex.js +2 -0
  35. package/dist/mjs/updateItemHashKey.js +17 -0
  36. package/dist/mjs/updateItemRangeKey.js +17 -0
  37. package/package.json +14 -14
  38. package/dist/cjs/EntityManagerClient.js +0 -90
  39. package/dist/mjs/EntityManagerClient.js +0 -88
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **EntityManager implements rational indexing & cross-shard querying at scale in your NoSQL database so you can focus on your application logic.**
10
10
 
11
- I've just released a full Typescript refactor. Everything works beatuifully, but I'm still fleshing out [the documentation](https://karmanivero.us/projects/entity-manager/intro/).
11
+ I've just released a full Typescript refactor. Everything works beautifully, but I'm still fleshing out [the documentation](https://karmanivero.us/projects/entity-manager/intro/).
12
12
 
13
13
  If you have any questions, please [start a discussion](https://github.com/karmaniverous/entity-manager/discussions). Otherwise stay tuned!
14
14
 
@@ -18,10 +18,12 @@ class EntityManager {
18
18
  * Create an EntityManager instance.
19
19
  *
20
20
  * @param config - EntityManager {@link Config | `Config`} object.
21
+ * @param logger - Logger object (defaults to `console`, must support `debug` & `error` methods).
21
22
  */
22
- constructor(config) {
23
+ constructor(config, logger = console) {
23
24
  _EntityManager_config.set(this, void 0);
24
25
  tslib.__classPrivateFieldSet(this, _EntityManager_config, ParsedConfig.configSchema.parse(config), "f");
26
+ this.logger = logger;
25
27
  }
26
28
  /**
27
29
  * Get the current EntityManager {@link Config | `Config`} object.
@@ -37,9 +37,21 @@ function addKeys(entityManager, item, entityToken, overwrite = false) {
37
37
  delete newItem[property];
38
38
  }
39
39
  }
40
+ entityManager.logger.debug('updated entity item generated properties', {
41
+ item,
42
+ entityToken,
43
+ overwrite,
44
+ newItem,
45
+ });
40
46
  return newItem;
41
47
  }
42
48
  catch (error) {
49
+ if (error instanceof Error)
50
+ entityManager.logger.error(error.message, {
51
+ item,
52
+ entityToken,
53
+ overwrite,
54
+ });
43
55
  throw error;
44
56
  }
45
57
  }
@@ -27,9 +27,21 @@ function decodeEntityElement(entityManager, value, entityToken, element) {
27
27
  if ([hashKey, rangeKey].includes(element))
28
28
  return value;
29
29
  const decoded = transcodes[entities[entityToken].elementTranscodes[element]].decode(value);
30
+ entityManager.logger.debug('decoded entity element', {
31
+ value,
32
+ entityToken,
33
+ element,
34
+ decoded,
35
+ });
30
36
  return decoded;
31
37
  }
32
38
  catch (error) {
39
+ if (error instanceof Error)
40
+ entityManager.logger.error(error.message, {
41
+ value,
42
+ entityToken,
43
+ element,
44
+ });
33
45
  throw error;
34
46
  }
35
47
  }
@@ -38,9 +38,16 @@ function decodeGeneratedProperty(entityManager, encoded, entityToken) {
38
38
  });
39
39
  // Assign decoded properties.
40
40
  Object.assign(decoded, radash.objectify(values, ([key]) => key, ([key, value]) => decodeEntityElement.decodeEntityElement(entityManager, value, entityToken, key)));
41
+ entityManager.logger.debug('decoded generated property', {
42
+ encoded,
43
+ entityToken,
44
+ decoded,
45
+ });
41
46
  return decoded;
42
47
  }
43
48
  catch (error) {
49
+ if (error instanceof Error)
50
+ entityManager.logger.error(error.message, { encoded, entityToken });
44
51
  throw error;
45
52
  }
46
53
  }
@@ -42,9 +42,22 @@ function dehydrateIndexItem(entityManager, item, entityToken, indexToken, omit =
42
42
  const dehydrated = elements
43
43
  .map((element) => encodeEntityElement.encodeEntityElement(entityManager, item, entityToken, element))
44
44
  .join(generatedKeyDelimiter);
45
+ entityManager.logger.debug('dehydrated index', {
46
+ item,
47
+ entityToken,
48
+ indexToken,
49
+ elements,
50
+ dehydrated,
51
+ });
45
52
  return dehydrated;
46
53
  }
47
54
  catch (error) {
55
+ if (error instanceof Error)
56
+ entityManager.logger.error(error.message, {
57
+ item,
58
+ entityToken,
59
+ indexToken,
60
+ });
48
61
  throw error;
49
62
  }
50
63
  }
@@ -31,6 +31,11 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
31
31
  // Shortcut empty pageKeyMap.
32
32
  if (!Object.keys(pageKeyMap).length) {
33
33
  const dehydrated = [];
34
+ entityManager.logger.debug('dehydrated empty page key map', {
35
+ pageKeyMap,
36
+ entityToken,
37
+ dehydrated,
38
+ });
34
39
  return dehydrated;
35
40
  }
36
41
  // Extract, sort & validate indexs.
@@ -65,9 +70,18 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
65
70
  // Replace with empty array if all pageKeys are empty strings.
66
71
  if (dehydrated.every((pageKey) => pageKey === ''))
67
72
  dehydrated = [];
73
+ entityManager.logger.debug('dehydrated page key map', {
74
+ pageKeyMap,
75
+ entityToken,
76
+ indexes,
77
+ hashKeys,
78
+ dehydrated,
79
+ });
68
80
  return dehydrated;
69
81
  }
70
82
  catch (error) {
83
+ if (error instanceof Error)
84
+ entityManager.logger.error(error.message, { entityToken, pageKeyMap });
71
85
  throw error;
72
86
  }
73
87
  }
@@ -26,9 +26,17 @@ function encodeEntityElement(entityManager, item, entityToken, element) {
26
26
  if (value === undefined || [hashKey, rangeKey].includes(element))
27
27
  return value;
28
28
  const encoded = transcodes[entities[entityToken].elementTranscodes[element]].encode(item[element]) || undefined;
29
+ entityManager.logger.debug('encoded entity element', {
30
+ item,
31
+ entityToken,
32
+ element,
33
+ encoded,
34
+ });
29
35
  return encoded;
30
36
  }
31
37
  catch (error) {
38
+ if (error instanceof Error)
39
+ entityManager.logger.error(error.message, { item, entityToken, element });
32
40
  throw error;
33
41
  }
34
42
  }
@@ -34,9 +34,21 @@ function encodeGeneratedProperty(entityManager, item, entityToken, property) {
34
34
  ...(sharded ? [item[entityManager.config.hashKey]] : []),
35
35
  ...elementMap.map(([element, value]) => [element, (value ?? '').toString()].join(entityManager.config.generatedValueDelimiter)),
36
36
  ].join(entityManager.config.generatedKeyDelimiter);
37
+ entityManager.logger.debug('encoded generated property', {
38
+ item,
39
+ entityToken,
40
+ property,
41
+ encoded,
42
+ });
37
43
  return encoded;
38
44
  }
39
45
  catch (error) {
46
+ if (error instanceof Error)
47
+ entityManager.logger.error(error.message, {
48
+ item,
49
+ entityToken,
50
+ property,
51
+ });
40
52
  throw error;
41
53
  }
42
54
  }
@@ -31,9 +31,21 @@ function getHashKeySpace(entityManager, entityToken, timestampFrom = 0, timestam
31
31
  : '';
32
32
  })
33
33
  .map((shardKey) => `${entityToken}${entityManager.config.shardKeyDelimiter}${shardKey}`);
34
+ entityManager.logger.debug('generated hash key space', {
35
+ entityToken,
36
+ timestampFrom,
37
+ timestampTo,
38
+ hashKeySpace,
39
+ });
34
40
  return hashKeySpace;
35
41
  }
36
42
  catch (error) {
43
+ if (error instanceof Error)
44
+ entityManager.logger.error(error.message, {
45
+ entityToken,
46
+ timestampFrom,
47
+ timestampTo,
48
+ });
37
49
  throw error;
38
50
  }
39
51
  }
package/dist/cjs/index.js CHANGED
@@ -2,12 +2,10 @@
2
2
 
3
3
  var conditionalize = require('./conditionalize.js');
4
4
  var EntityManager = require('./EntityManager.js');
5
- var EntityManagerClient = require('./EntityManagerClient.js');
6
5
  var ShardQueryMapBuilder = require('./ShardQueryMapBuilder.js');
7
6
 
8
7
 
9
8
 
10
9
  exports.conditionalize = conditionalize.conditionalize;
11
10
  exports.EntityManager = EntityManager.EntityManager;
12
- exports.EntityManagerClient = EntityManagerClient.EntityManagerClient;
13
11
  exports.ShardQueryMapBuilder = ShardQueryMapBuilder.ShardQueryMapBuilder;
package/dist/cjs/query.js CHANGED
@@ -92,9 +92,35 @@ async function query(entityManager, { entityToken, hashKey, limit, pageKeyMap, p
92
92
  items: workingResult.items,
93
93
  pageKeyMap: compressToEncodedURIComponent(JSON.stringify(dehydratePageKeyMap.dehydratePageKeyMap(entityManager, workingResult.pageKeyMap, entityToken))),
94
94
  };
95
+ entityManager.logger.debug('queried entityToken across shards', {
96
+ entityToken,
97
+ hashKey,
98
+ limit,
99
+ pageKeyMap,
100
+ pageSize,
101
+ shardQueryMap,
102
+ timestampFrom,
103
+ timestampTo,
104
+ throttle,
105
+ rehydratedPageKeyMap,
106
+ workingResult,
107
+ result,
108
+ });
95
109
  return result;
96
110
  }
97
111
  catch (error) {
112
+ if (error instanceof Error)
113
+ entityManager.logger.error(error.message, {
114
+ entityToken,
115
+ hashKey,
116
+ limit,
117
+ pageKeyMap,
118
+ pageSize,
119
+ shardQueryMap,
120
+ timestampFrom,
121
+ timestampTo,
122
+ throttle,
123
+ });
98
124
  throw error;
99
125
  }
100
126
  }
@@ -37,9 +37,23 @@ function rehydrateIndexItem(entityManager, dehydrated, entityToken, indexToken,
37
37
  throw new Error('index rehydration key-value mismatch');
38
38
  // Assign values to elements.
39
39
  const rehydrated = radash.shake(radash.zipToObject(elements, values.map((value, i) => decodeEntityElement.decodeEntityElement(entityManager, value, entityToken, elements[i]))));
40
+ entityManager.logger.debug('rehydrated index', {
41
+ dehydrated,
42
+ entityToken,
43
+ indexToken,
44
+ elements,
45
+ values,
46
+ rehydrated,
47
+ });
40
48
  return rehydrated;
41
49
  }
42
50
  catch (error) {
51
+ if (error instanceof Error)
52
+ entityManager.logger.error(error.message, {
53
+ dehydrated,
54
+ entityToken,
55
+ indexToken,
56
+ });
43
57
  throw error;
44
58
  }
45
59
  }
@@ -55,9 +55,21 @@ function rehydratePageKeyMap(entityManager, dehydrated, entityToken, indexTokens
55
55
  ? encodeGeneratedProperty.encodeGeneratedProperty(entityManager, item, entityToken, component)
56
56
  : item[component]);
57
57
  }));
58
+ entityManager.logger.debug('rehydrated page key map', {
59
+ dehydrated,
60
+ entityToken,
61
+ indexTokens,
62
+ rehydrated,
63
+ });
58
64
  return rehydrated;
59
65
  }
60
66
  catch (error) {
67
+ if (error instanceof Error)
68
+ entityManager.logger.error(error.message, {
69
+ dehydrated,
70
+ entityToken,
71
+ indexTokens,
72
+ });
61
73
  throw error;
62
74
  }
63
75
  }
@@ -24,9 +24,16 @@ function removeKeys(entityManager, item, entityToken) {
24
24
  // Delete generated properties.
25
25
  for (const property in entityManager.config.entities[entityToken].generated)
26
26
  delete newItem[property];
27
+ entityManager.logger.debug('stripped entity item generated properties', {
28
+ item,
29
+ entityToken,
30
+ newItem,
31
+ });
27
32
  return newItem;
28
33
  }
29
34
  catch (error) {
35
+ if (error instanceof Error)
36
+ entityManager.logger.error(error.message, { item, entityToken });
30
37
  throw error;
31
38
  }
32
39
  }
@@ -33,6 +33,8 @@ function unwrapIndex(entityManager, entityToken, indexToken) {
33
33
  .sort();
34
34
  }
35
35
  catch (error) {
36
+ if (error instanceof Error)
37
+ entityManager.logger.error(error.message, { indexToken, entityToken });
36
38
  throw error;
37
39
  }
38
40
  }
@@ -23,6 +23,11 @@ function updateItemHashKey(entityManager, item, entityToken, overwrite = false)
23
23
  validateEntityToken.validateEntityToken(entityManager, entityToken);
24
24
  // Return current item if hashKey exists and overwrite is false.
25
25
  if (item[entityManager.config.hashKey] && !overwrite) {
26
+ entityManager.logger.debug('did not overwrite existing entity item hash key', {
27
+ item,
28
+ entityToken,
29
+ overwrite,
30
+ });
26
31
  return { ...item };
27
32
  }
28
33
  // Get item timestamp property & validate.
@@ -45,9 +50,21 @@ function updateItemHashKey(entityManager, item, entityToken, overwrite = false)
45
50
  .padStart(chars, '0');
46
51
  }
47
52
  const newItem = Object.assign({ ...item }, { [entityManager.config.hashKey]: hashKey });
53
+ entityManager.logger.debug('updated entity item hash key', {
54
+ entityToken,
55
+ overwrite,
56
+ item,
57
+ newItem,
58
+ });
48
59
  return newItem;
49
60
  }
50
61
  catch (error) {
62
+ if (error instanceof Error)
63
+ entityManager.logger.error(error.message, {
64
+ item,
65
+ entityToken,
66
+ overwrite,
67
+ });
51
68
  throw error;
52
69
  }
53
70
  }
@@ -22,6 +22,11 @@ function updateItemRangeKey(entityManager, item, entityToken, overwrite = false)
22
22
  validateEntityToken.validateEntityToken(entityManager, entityToken);
23
23
  // Return current item if rangeKey exists and overwrite is false.
24
24
  if (item[entityManager.config.rangeKey] && !overwrite) {
25
+ entityManager.logger.debug('did not overwrite existing entity item range key', {
26
+ item,
27
+ entityToken,
28
+ overwrite,
29
+ });
25
30
  return { ...item };
26
31
  }
27
32
  // Get item unique property & validate.
@@ -35,9 +40,21 @@ function updateItemRangeKey(entityManager, item, entityToken, overwrite = false)
35
40
  uniqueProperty,
36
41
  ].join(entityManager.config.generatedValueDelimiter),
37
42
  });
43
+ entityManager.logger.debug('updated entity item range key', {
44
+ entityToken,
45
+ overwrite,
46
+ item,
47
+ newItem,
48
+ });
38
49
  return newItem;
39
50
  }
40
51
  catch (error) {
52
+ if (error instanceof Error)
53
+ entityManager.logger.error(error.message, {
54
+ item,
55
+ entityToken,
56
+ overwrite,
57
+ });
41
58
  throw error;
42
59
  }
43
60
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Entity, Exactify, TranscodeMap, PropertiesOfType, TranscodableProperties, Transcodes, DefaultTranscodeMap, PartialTranscodable, SortOrder } from '@karmaniverous/entity-tools';
1
+ import { Entity, Exactify, TranscodeMap, PropertiesOfType, TranscodableProperties, Transcodes, DefaultTranscodeMap, SortOrder } from '@karmaniverous/entity-tools';
2
2
  export { DefaultTranscodeMap, Entity, Exactify, PartialTranscodable, PropertiesNotOfType, PropertiesOfType, SortOrder, TranscodableProperties, TranscodeMap, Transcodes, defaultTranscodes } from '@karmaniverous/entity-tools';
3
3
  import { z } from 'zod';
4
4
 
@@ -632,23 +632,17 @@ type ParsedConfig = z.infer<typeof configSchema>;
632
632
  /**
633
633
  * A result returned by a {@link ShardQueryFunction | `ShardQueryFunction`} querying an individual shard.
634
634
  *
635
- * @typeParam Item - The {@link ItemMap | `ItemMap`} type being queried.
636
- * @typeParam T - The {@link TranscodeMap | `TranscodeMap`} identifying property types that can be indexed.
635
+ * @typeParam Item - The {@link Item | `Item`} type being queried.
637
636
 
638
637
  * @category Query
639
638
  */
640
- interface ShardQueryResult<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string, M extends EntityMap, HashKey extends string = 'hashKey', RangeKey extends string = 'rangeKey', T extends TranscodeMap = DefaultTranscodeMap> {
639
+ interface ShardQueryResult<Item extends Entity> {
641
640
  /** The number of records returned. */
642
641
  count: number;
643
642
  /** The returned records. */
644
643
  items: Item[];
645
644
  /** The page key for the next query on this shard. */
646
- pageKey?: PartialTranscodable<Item, T>;
647
- }
648
- interface ClientShardQueryResult {
649
- count: number;
650
- items: Entity[];
651
- pageKey?: Entity;
645
+ pageKey?: Partial<Item>;
652
646
  }
653
647
 
654
648
  /**
@@ -658,27 +652,24 @@ interface ClientShardQueryResult {
658
652
  * provided by the {@link EntityManager.query | `EntityManager.query`} method, which assembles many returned
659
653
  * pages queried across multiple shards into a single query result.
660
654
  *
661
- * @typeParam Item - The {@link ItemMap | `ItemMap`} type being queried.
662
- * @typeParam T - The {@link TranscodeMap | `TranscodeMap`} identifying property types that can be indexed. Defaults to {@link DefaultTranscodeMap | `DefaultTranscodeMap`}.
655
+ * @typeParam Item - The {@link Item | `Item`} type being queried.
663
656
 
664
- * @param hashKey - The {@link ConfigKeys.hashKey | `this.config.hashKey`} property value of the shard being queried.
657
+ * @param hashKey - The hash key value of the shard being queried.
665
658
  * @param pageKey - The page key returned by the previous query on this shard.
666
659
  * @param pageSize - The maximum number of items to return from this query.
667
660
  *
668
661
  * @category Query
669
662
  */
670
- type ShardQueryFunction<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string, M extends EntityMap, HashKey extends string = 'hashKey', RangeKey extends string = 'rangeKey', T extends TranscodeMap = DefaultTranscodeMap> = (hashKey: string, pageKey?: PartialTranscodable<Item, T>, pageSize?: number) => Promise<ShardQueryResult<Item, EntityToken, M, HashKey, RangeKey, T>>;
671
- type ClientShardQueryFunction = (hashKey: string, pageKey?: Entity, pageSize?: number) => Promise<ClientShardQueryResult>;
663
+ type ShardQueryFunction<Item extends Entity> = (hashKey: string, pageKey?: Partial<Item>, pageSize?: number) => Promise<ShardQueryResult<Item>>;
672
664
 
673
- type ShardQueryMap<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string, M extends EntityMap, HashKey extends string, RangeKey extends string, T extends TranscodeMap> = Record<string, ShardQueryFunction<Item, EntityToken, M, HashKey, RangeKey, T>>;
674
- type ClientShardQueryMap = Record<string, ClientShardQueryFunction>;
665
+ type ShardQueryMap<Item extends Entity> = Record<string, ShardQueryFunction<Item>>;
675
666
 
676
667
  /**
677
668
  * Options passed to the {@link EntityManager.query | `EntityManager.query`} method.
678
669
  *
679
670
  * @category Query
680
671
  */
681
- interface QueryOptions<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string, M extends EntityMap, HashKey extends string, RangeKey extends string, T extends TranscodeMap> {
672
+ interface QueryOptions<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string, M extends EntityMap, HashKey extends string, RangeKey extends string> {
682
673
  /** Identifies the entity to be queried. Key of {@link Config | `EntityManager.config.entities`}. */
683
674
  entityToken: EntityToken;
684
675
  /**
@@ -717,7 +708,7 @@ interface QueryOptions<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken],
717
708
  * page key, e.g. to match the same string against `firstName` and `lastName`
718
709
  * properties without performing a table scan for either.
719
710
  */
720
- shardQueryMap: ShardQueryMap<Item, EntityToken, M, HashKey, RangeKey, T>;
711
+ shardQueryMap: ShardQueryMap<Item>;
721
712
  /**
722
713
  * A {@link SortOrder | `SortOrder`} object specifying the sort order of the result set. Defaults to `[]`.
723
714
  */
@@ -776,12 +767,14 @@ interface QueryResult<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], E
776
767
  */
777
768
  declare class EntityManager<M extends EntityMap, HashKey extends string, RangeKey extends string, T extends TranscodeMap> {
778
769
  #private;
770
+ logger: Pick<Console, 'debug' | 'error'>;
779
771
  /**
780
772
  * Create an EntityManager instance.
781
773
  *
782
774
  * @param config - EntityManager {@link Config | `Config`} object.
775
+ * @param logger - Logger object (defaults to `console`, must support `debug` & `error` methods).
783
776
  */
784
- constructor(config: Config<M, HashKey, RangeKey, T>);
777
+ constructor(config: Config<M, HashKey, RangeKey, T>, logger?: Pick<Console, 'debug' | 'error'>);
785
778
  /**
786
779
  * Get the current EntityManager {@link Config | `Config`} object.
787
780
  *
@@ -835,21 +828,7 @@ declare class EntityManager<M extends EntityMap, HashKey extends string, RangeKe
835
828
  *
836
829
  * @throws Error if {@link QueryOptions.pageKeyMap | `pageKeyMap`} keys do not match {@link QueryOptions.shardQueryMap | `shardQueryMap`} keys.
837
830
  */
838
- query<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(options: QueryOptions<Item, EntityToken, M, HashKey, RangeKey, T>): Promise<QueryResult<Item, EntityToken, M, HashKey, RangeKey>>;
839
- }
840
-
841
- /**
842
- * Options for EntityManager client methods that support batch operations.
843
- */
844
- interface EntityManagerClientBatchOptions {
845
- /** Batch size. */
846
- batchSize?: number;
847
- /** Delay increment in ms for retry operations. Doubles on each retry. */
848
- delayIncrement?: number;
849
- /** Max retries for retry operations. */
850
- maxRetries?: number;
851
- /** Throttle for parallel operations. */
852
- throttle?: number;
831
+ query<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(options: QueryOptions<Item, EntityToken, M, HashKey, RangeKey>): Promise<QueryResult<Item, EntityToken, M, HashKey, RangeKey>>;
853
832
  }
854
833
 
855
834
  /**
@@ -879,58 +858,18 @@ interface LoggerOptions {
879
858
  logInternals?: boolean;
880
859
  }
881
860
 
882
- /**
883
- * EntityManagerClient base class options.
884
- *
885
- * @category Client
886
- */
887
- type EntityManagerClientOptions = EntityManagerClientBatchOptions & LoggerOptions;
888
- /**
889
- * EntityManagerClient base class.
890
- *
891
- * @typeParam Options - Options type extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
892
- *
893
- * @category Client
894
- */
895
- declare abstract class EntityManagerClient<Options extends EntityManagerClientOptions> {
896
- #private;
897
- /**
898
- * EntityManagerClient base constructor.
899
- * @param options - Options object extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
900
- */
901
- constructor({ batchSize, delayIncrement, maxRetries, throttle, logger, logInternals, ...childOptions }: Options);
902
- /**
903
- * Returns the options used to create the EntityManagerClient instance.
904
- */
905
- get options(): Required<Options>;
906
- /**
907
- * Executes a batch operation.
908
- *
909
- * @param items - Items to batch execute.
910
- * @param executeBatch - Function to execute the batch.
911
- * @param getUnprocessedItems - Function to get unprocessed items from the output.
912
- * @param options - Batch options.
913
- *
914
- * @typeParam Item - Input item type.
915
- * @typeParam Output - Output type.
916
- *
917
- * @returns Output array.
918
- */
919
- protected batchExecute<Item, Output>(items: Item[], executeBatch: (items: Item[]) => Promise<Output>, getUnprocessedItems?: (output: Output) => Item[] | undefined, { batchSize, delayIncrement, maxRetries, throttle, }?: EntityManagerClientBatchOptions): Promise<Output[]>;
920
- }
921
-
922
861
  /**
923
862
  * {@link ShardQueryMapBuilder | `ShardQueryMapBuilder`} options.
924
863
  *
925
864
  * @category Query
926
865
  */
927
- interface ShardQueryMapBuilderOptions {
866
+ interface ShardQueryMapBuilderOptions<Item extends Entity> {
928
867
  /** `entityManager.config.entities` key. */
929
868
  entityToken: string;
930
869
  /** Either the designated entity hash key or a generated property with `sharded === true`. */
931
870
  hashKeyToken: string;
932
871
  /** A partial `Item` sufficiently populated to generate the query hash key & index values. */
933
- item: Entity;
872
+ item: Item;
934
873
  /** Dehydrated page key from the previous query data page. */
935
874
  pageKey?: string;
936
875
  }
@@ -940,10 +879,10 @@ interface ShardQueryMapBuilderOptions {
940
879
  *
941
880
  * @category Query
942
881
  */
943
- declare abstract class ShardQueryMapBuilder<Options extends ShardQueryMapBuilderOptions> {
882
+ declare abstract class ShardQueryMapBuilder<Item extends Entity, Options extends ShardQueryMapBuilderOptions<Item>> {
944
883
  readonly options: Options;
945
884
  constructor(options: Options);
946
- abstract getShardQueryMap(): ClientShardQueryMap;
885
+ abstract getShardQueryMap(): ShardQueryMap<Item>;
947
886
  }
948
887
 
949
888
  /**
@@ -956,4 +895,4 @@ type WithRequiredAndNonNullable<T, K extends keyof T> = T & {
956
895
  [P in K]-?: NonNullable<T[P]>;
957
896
  };
958
897
 
959
- export { type Config, type ConfigEntities, type ConfigEntity, type ConfigEntityGenerated, type ConfigKeys, type ConfigTranscodes, EntityManager, EntityManagerClient, type EntityManagerClientBatchOptions, type EntityManagerClientOptions, type EntityMap, type ExclusiveKey, type ItemMap, type Logger, type LoggerEndpoint, type LoggerOptions, type ParsedConfig, type QueryOptions, type QueryResult, type ShardBump, type ShardQueryFunction, type ShardQueryMap, ShardQueryMapBuilder, type ShardQueryMapBuilderOptions, type ShardQueryResult, type Unwrap, type WithRequiredAndNonNullable, conditionalize };
898
+ export { type Config, type ConfigEntities, type ConfigEntity, type ConfigEntityGenerated, type ConfigKeys, type ConfigTranscodes, EntityManager, type EntityMap, type ExclusiveKey, type ItemMap, type Logger, type LoggerEndpoint, type LoggerOptions, type ParsedConfig, type QueryOptions, type QueryResult, type ShardBump, type ShardQueryFunction, type ShardQueryMap, ShardQueryMapBuilder, type ShardQueryMapBuilderOptions, type ShardQueryResult, type Unwrap, type WithRequiredAndNonNullable, conditionalize };
@@ -16,10 +16,12 @@ class EntityManager {
16
16
  * Create an EntityManager instance.
17
17
  *
18
18
  * @param config - EntityManager {@link Config | `Config`} object.
19
+ * @param logger - Logger object (defaults to `console`, must support `debug` & `error` methods).
19
20
  */
20
- constructor(config) {
21
+ constructor(config, logger = console) {
21
22
  _EntityManager_config.set(this, void 0);
22
23
  __classPrivateFieldSet(this, _EntityManager_config, configSchema.parse(config), "f");
24
+ this.logger = logger;
23
25
  }
24
26
  /**
25
27
  * Get the current EntityManager {@link Config | `Config`} object.
@@ -35,9 +35,21 @@ function addKeys(entityManager, item, entityToken, overwrite = false) {
35
35
  delete newItem[property];
36
36
  }
37
37
  }
38
+ entityManager.logger.debug('updated entity item generated properties', {
39
+ item,
40
+ entityToken,
41
+ overwrite,
42
+ newItem,
43
+ });
38
44
  return newItem;
39
45
  }
40
46
  catch (error) {
47
+ if (error instanceof Error)
48
+ entityManager.logger.error(error.message, {
49
+ item,
50
+ entityToken,
51
+ overwrite,
52
+ });
41
53
  throw error;
42
54
  }
43
55
  }
@@ -25,9 +25,21 @@ function decodeEntityElement(entityManager, value, entityToken, element) {
25
25
  if ([hashKey, rangeKey].includes(element))
26
26
  return value;
27
27
  const decoded = transcodes[entities[entityToken].elementTranscodes[element]].decode(value);
28
+ entityManager.logger.debug('decoded entity element', {
29
+ value,
30
+ entityToken,
31
+ element,
32
+ decoded,
33
+ });
28
34
  return decoded;
29
35
  }
30
36
  catch (error) {
37
+ if (error instanceof Error)
38
+ entityManager.logger.error(error.message, {
39
+ value,
40
+ entityToken,
41
+ element,
42
+ });
31
43
  throw error;
32
44
  }
33
45
  }
@@ -36,9 +36,16 @@ function decodeGeneratedProperty(entityManager, encoded, entityToken) {
36
36
  });
37
37
  // Assign decoded properties.
38
38
  Object.assign(decoded, objectify(values, ([key]) => key, ([key, value]) => decodeEntityElement(entityManager, value, entityToken, key)));
39
+ entityManager.logger.debug('decoded generated property', {
40
+ encoded,
41
+ entityToken,
42
+ decoded,
43
+ });
39
44
  return decoded;
40
45
  }
41
46
  catch (error) {
47
+ if (error instanceof Error)
48
+ entityManager.logger.error(error.message, { encoded, entityToken });
42
49
  throw error;
43
50
  }
44
51
  }
@@ -40,9 +40,22 @@ function dehydrateIndexItem(entityManager, item, entityToken, indexToken, omit =
40
40
  const dehydrated = elements
41
41
  .map((element) => encodeEntityElement(entityManager, item, entityToken, element))
42
42
  .join(generatedKeyDelimiter);
43
+ entityManager.logger.debug('dehydrated index', {
44
+ item,
45
+ entityToken,
46
+ indexToken,
47
+ elements,
48
+ dehydrated,
49
+ });
43
50
  return dehydrated;
44
51
  }
45
52
  catch (error) {
53
+ if (error instanceof Error)
54
+ entityManager.logger.error(error.message, {
55
+ item,
56
+ entityToken,
57
+ indexToken,
58
+ });
46
59
  throw error;
47
60
  }
48
61
  }
@@ -29,6 +29,11 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
29
29
  // Shortcut empty pageKeyMap.
30
30
  if (!Object.keys(pageKeyMap).length) {
31
31
  const dehydrated = [];
32
+ entityManager.logger.debug('dehydrated empty page key map', {
33
+ pageKeyMap,
34
+ entityToken,
35
+ dehydrated,
36
+ });
32
37
  return dehydrated;
33
38
  }
34
39
  // Extract, sort & validate indexs.
@@ -63,9 +68,18 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
63
68
  // Replace with empty array if all pageKeys are empty strings.
64
69
  if (dehydrated.every((pageKey) => pageKey === ''))
65
70
  dehydrated = [];
71
+ entityManager.logger.debug('dehydrated page key map', {
72
+ pageKeyMap,
73
+ entityToken,
74
+ indexes,
75
+ hashKeys,
76
+ dehydrated,
77
+ });
66
78
  return dehydrated;
67
79
  }
68
80
  catch (error) {
81
+ if (error instanceof Error)
82
+ entityManager.logger.error(error.message, { entityToken, pageKeyMap });
69
83
  throw error;
70
84
  }
71
85
  }
@@ -24,9 +24,17 @@ function encodeEntityElement(entityManager, item, entityToken, element) {
24
24
  if (value === undefined || [hashKey, rangeKey].includes(element))
25
25
  return value;
26
26
  const encoded = transcodes[entities[entityToken].elementTranscodes[element]].encode(item[element]) || undefined;
27
+ entityManager.logger.debug('encoded entity element', {
28
+ item,
29
+ entityToken,
30
+ element,
31
+ encoded,
32
+ });
27
33
  return encoded;
28
34
  }
29
35
  catch (error) {
36
+ if (error instanceof Error)
37
+ entityManager.logger.error(error.message, { item, entityToken, element });
30
38
  throw error;
31
39
  }
32
40
  }
@@ -32,9 +32,21 @@ function encodeGeneratedProperty(entityManager, item, entityToken, property) {
32
32
  ...(sharded ? [item[entityManager.config.hashKey]] : []),
33
33
  ...elementMap.map(([element, value]) => [element, (value ?? '').toString()].join(entityManager.config.generatedValueDelimiter)),
34
34
  ].join(entityManager.config.generatedKeyDelimiter);
35
+ entityManager.logger.debug('encoded generated property', {
36
+ item,
37
+ entityToken,
38
+ property,
39
+ encoded,
40
+ });
35
41
  return encoded;
36
42
  }
37
43
  catch (error) {
44
+ if (error instanceof Error)
45
+ entityManager.logger.error(error.message, {
46
+ item,
47
+ entityToken,
48
+ property,
49
+ });
38
50
  throw error;
39
51
  }
40
52
  }
@@ -29,9 +29,21 @@ function getHashKeySpace(entityManager, entityToken, timestampFrom = 0, timestam
29
29
  : '';
30
30
  })
31
31
  .map((shardKey) => `${entityToken}${entityManager.config.shardKeyDelimiter}${shardKey}`);
32
+ entityManager.logger.debug('generated hash key space', {
33
+ entityToken,
34
+ timestampFrom,
35
+ timestampTo,
36
+ hashKeySpace,
37
+ });
32
38
  return hashKeySpace;
33
39
  }
34
40
  catch (error) {
41
+ if (error instanceof Error)
42
+ entityManager.logger.error(error.message, {
43
+ entityToken,
44
+ timestampFrom,
45
+ timestampTo,
46
+ });
35
47
  throw error;
36
48
  }
37
49
  }
package/dist/mjs/index.js CHANGED
@@ -1,4 +1,3 @@
1
1
  export { conditionalize } from './conditionalize.js';
2
2
  export { EntityManager } from './EntityManager.js';
3
- export { EntityManagerClient } from './EntityManagerClient.js';
4
3
  export { ShardQueryMapBuilder } from './ShardQueryMapBuilder.js';
package/dist/mjs/query.js CHANGED
@@ -90,9 +90,35 @@ async function query(entityManager, { entityToken, hashKey, limit, pageKeyMap, p
90
90
  items: workingResult.items,
91
91
  pageKeyMap: compressToEncodedURIComponent(JSON.stringify(dehydratePageKeyMap(entityManager, workingResult.pageKeyMap, entityToken))),
92
92
  };
93
+ entityManager.logger.debug('queried entityToken across shards', {
94
+ entityToken,
95
+ hashKey,
96
+ limit,
97
+ pageKeyMap,
98
+ pageSize,
99
+ shardQueryMap,
100
+ timestampFrom,
101
+ timestampTo,
102
+ throttle,
103
+ rehydratedPageKeyMap,
104
+ workingResult,
105
+ result,
106
+ });
93
107
  return result;
94
108
  }
95
109
  catch (error) {
110
+ if (error instanceof Error)
111
+ entityManager.logger.error(error.message, {
112
+ entityToken,
113
+ hashKey,
114
+ limit,
115
+ pageKeyMap,
116
+ pageSize,
117
+ shardQueryMap,
118
+ timestampFrom,
119
+ timestampTo,
120
+ throttle,
121
+ });
96
122
  throw error;
97
123
  }
98
124
  }
@@ -35,9 +35,23 @@ function rehydrateIndexItem(entityManager, dehydrated, entityToken, indexToken,
35
35
  throw new Error('index rehydration key-value mismatch');
36
36
  // Assign values to elements.
37
37
  const rehydrated = shake(zipToObject(elements, values.map((value, i) => decodeEntityElement(entityManager, value, entityToken, elements[i]))));
38
+ entityManager.logger.debug('rehydrated index', {
39
+ dehydrated,
40
+ entityToken,
41
+ indexToken,
42
+ elements,
43
+ values,
44
+ rehydrated,
45
+ });
38
46
  return rehydrated;
39
47
  }
40
48
  catch (error) {
49
+ if (error instanceof Error)
50
+ entityManager.logger.error(error.message, {
51
+ dehydrated,
52
+ entityToken,
53
+ indexToken,
54
+ });
41
55
  throw error;
42
56
  }
43
57
  }
@@ -53,9 +53,21 @@ function rehydratePageKeyMap(entityManager, dehydrated, entityToken, indexTokens
53
53
  ? encodeGeneratedProperty(entityManager, item, entityToken, component)
54
54
  : item[component]);
55
55
  }));
56
+ entityManager.logger.debug('rehydrated page key map', {
57
+ dehydrated,
58
+ entityToken,
59
+ indexTokens,
60
+ rehydrated,
61
+ });
56
62
  return rehydrated;
57
63
  }
58
64
  catch (error) {
65
+ if (error instanceof Error)
66
+ entityManager.logger.error(error.message, {
67
+ dehydrated,
68
+ entityToken,
69
+ indexTokens,
70
+ });
59
71
  throw error;
60
72
  }
61
73
  }
@@ -22,9 +22,16 @@ function removeKeys(entityManager, item, entityToken) {
22
22
  // Delete generated properties.
23
23
  for (const property in entityManager.config.entities[entityToken].generated)
24
24
  delete newItem[property];
25
+ entityManager.logger.debug('stripped entity item generated properties', {
26
+ item,
27
+ entityToken,
28
+ newItem,
29
+ });
25
30
  return newItem;
26
31
  }
27
32
  catch (error) {
33
+ if (error instanceof Error)
34
+ entityManager.logger.error(error.message, { item, entityToken });
28
35
  throw error;
29
36
  }
30
37
  }
@@ -31,6 +31,8 @@ function unwrapIndex(entityManager, entityToken, indexToken) {
31
31
  .sort();
32
32
  }
33
33
  catch (error) {
34
+ if (error instanceof Error)
35
+ entityManager.logger.error(error.message, { indexToken, entityToken });
34
36
  throw error;
35
37
  }
36
38
  }
@@ -21,6 +21,11 @@ function updateItemHashKey(entityManager, item, entityToken, overwrite = false)
21
21
  validateEntityToken(entityManager, entityToken);
22
22
  // Return current item if hashKey exists and overwrite is false.
23
23
  if (item[entityManager.config.hashKey] && !overwrite) {
24
+ entityManager.logger.debug('did not overwrite existing entity item hash key', {
25
+ item,
26
+ entityToken,
27
+ overwrite,
28
+ });
24
29
  return { ...item };
25
30
  }
26
31
  // Get item timestamp property & validate.
@@ -43,9 +48,21 @@ function updateItemHashKey(entityManager, item, entityToken, overwrite = false)
43
48
  .padStart(chars, '0');
44
49
  }
45
50
  const newItem = Object.assign({ ...item }, { [entityManager.config.hashKey]: hashKey });
51
+ entityManager.logger.debug('updated entity item hash key', {
52
+ entityToken,
53
+ overwrite,
54
+ item,
55
+ newItem,
56
+ });
46
57
  return newItem;
47
58
  }
48
59
  catch (error) {
60
+ if (error instanceof Error)
61
+ entityManager.logger.error(error.message, {
62
+ item,
63
+ entityToken,
64
+ overwrite,
65
+ });
49
66
  throw error;
50
67
  }
51
68
  }
@@ -20,6 +20,11 @@ function updateItemRangeKey(entityManager, item, entityToken, overwrite = false)
20
20
  validateEntityToken(entityManager, entityToken);
21
21
  // Return current item if rangeKey exists and overwrite is false.
22
22
  if (item[entityManager.config.rangeKey] && !overwrite) {
23
+ entityManager.logger.debug('did not overwrite existing entity item range key', {
24
+ item,
25
+ entityToken,
26
+ overwrite,
27
+ });
23
28
  return { ...item };
24
29
  }
25
30
  // Get item unique property & validate.
@@ -33,9 +38,21 @@ function updateItemRangeKey(entityManager, item, entityToken, overwrite = false)
33
38
  uniqueProperty,
34
39
  ].join(entityManager.config.generatedValueDelimiter),
35
40
  });
41
+ entityManager.logger.debug('updated entity item range key', {
42
+ entityToken,
43
+ overwrite,
44
+ item,
45
+ newItem,
46
+ });
36
47
  return newItem;
37
48
  }
38
49
  catch (error) {
50
+ if (error instanceof Error)
51
+ entityManager.logger.error(error.message, {
52
+ item,
53
+ entityToken,
54
+ overwrite,
55
+ });
39
56
  throw error;
40
57
  }
41
58
  }
package/package.json CHANGED
@@ -14,50 +14,50 @@
14
14
  },
15
15
  "description": "Rational indexing & cross-shard querying at scale in your NoSQL database so you can focus on your application logic.",
16
16
  "devDependencies": {
17
- "@dotenvx/dotenvx": "^1.16.1",
18
- "@eslint/js": "^9.12.0",
17
+ "@dotenvx/dotenvx": "^1.20.0",
18
+ "@eslint/js": "^9.13.0",
19
19
  "@faker-js/faker": "^9.0.3",
20
20
  "@karmaniverous/mock-db": "^0.3.3",
21
21
  "@rollup/plugin-alias": "^5.1.1",
22
- "@rollup/plugin-commonjs": "^28.0.0",
22
+ "@rollup/plugin-commonjs": "^28.0.1",
23
23
  "@rollup/plugin-json": "^6.1.0",
24
24
  "@rollup/plugin-node-resolve": "^15.3.0",
25
25
  "@rollup/plugin-strip": "^3.0.4",
26
- "@rollup/plugin-typescript": "^12.1.0",
26
+ "@rollup/plugin-typescript": "^12.1.1",
27
27
  "@types/chai": "^5.0.0",
28
28
  "@types/eslint__js": "^8.42.3",
29
29
  "@types/eslint-config-prettier": "^6.11.3",
30
30
  "@types/eslint-plugin-mocha": "^10.4.0",
31
31
  "@types/mocha": "^10.0.9",
32
- "@types/node": "^22.7.5",
32
+ "@types/node": "^22.7.8",
33
33
  "@types/string-hash": "^1.1.3",
34
34
  "auto-changelog": "^2.5.0",
35
35
  "chai": "^5.1.1",
36
36
  "cross-env": "^7.0.3",
37
- "eslint": "^9.12.0",
37
+ "eslint": "^9.13.0",
38
38
  "eslint-config-prettier": "^9.1.0",
39
39
  "eslint-plugin-mocha": "^10.5.0",
40
40
  "eslint-plugin-simple-import-sort": "^12.1.1",
41
41
  "eslint-plugin-tsdoc": "^0.3.0",
42
42
  "jsdom-global": "^3.0.2",
43
- "knip": "^5.33.2",
44
- "lefthook": "^1.7.18",
43
+ "knip": "^5.33.3",
44
+ "lefthook": "^1.7.22",
45
45
  "mocha": "^10.7.3",
46
46
  "nyc": "^17.1.0",
47
47
  "prettier": "^3.3.3",
48
- "release-it": "^17.7.0",
48
+ "release-it": "^17.10.0",
49
49
  "rimraf": "^6.0.1",
50
50
  "rollup": "^4.24.0",
51
51
  "rollup-plugin-dts": "^6.1.1",
52
52
  "source-map-support": "^0.5.21",
53
53
  "ts-node": "^10.9.2",
54
- "tslib": "^2.7.0",
55
- "typedoc": "^0.26.8",
56
- "typedoc-plugin-mdn-links": "^3.3.2",
54
+ "tslib": "^2.8.0",
55
+ "typedoc": "^0.26.10",
56
+ "typedoc-plugin-mdn-links": "^3.3.4",
57
57
  "typedoc-plugin-replace-text": "^4.0.0",
58
58
  "typedoc-plugin-zod": "^1.2.1",
59
59
  "typescript": "^5.6.3",
60
- "typescript-eslint": "^8.8.1"
60
+ "typescript-eslint": "^8.11.0"
61
61
  },
62
62
  "exports": {
63
63
  ".": {
@@ -132,5 +132,5 @@
132
132
  },
133
133
  "type": "module",
134
134
  "types": "dist/index.d.ts",
135
- "version": "6.4.2"
135
+ "version": "6.4.4"
136
136
  }
@@ -1,90 +0,0 @@
1
- 'use strict';
2
-
3
- var tslib = require('tslib');
4
- var radash = require('radash');
5
- var promises = require('timers/promises');
6
- var conditionalize = require('./conditionalize.js');
7
-
8
- var _EntityManagerClient_options;
9
- /**
10
- * EntityManagerClient base class.
11
- *
12
- * @typeParam Options - Options type extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
13
- *
14
- * @category Client
15
- */
16
- class EntityManagerClient {
17
- /**
18
- * EntityManagerClient base constructor.
19
- * @param options - Options object extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
20
- */
21
- constructor({ batchSize = 25, delayIncrement = 100, maxRetries = 5, throttle = 10, logger = console, logInternals = false, ...childOptions }) {
22
- _EntityManagerClient_options.set(this, void 0);
23
- if (!radash.isFunction(logger.debug))
24
- throw new Error('logger must support debug method');
25
- if (!radash.isFunction(logger.error))
26
- throw new Error('logger must support error method');
27
- tslib.__classPrivateFieldSet(this, _EntityManagerClient_options, {
28
- batchSize,
29
- delayIncrement,
30
- maxRetries,
31
- throttle,
32
- logInternals,
33
- logger: {
34
- ...logger,
35
- debug: conditionalize.conditionalize(logger.debug, logInternals),
36
- },
37
- ...childOptions,
38
- }, "f");
39
- }
40
- /**
41
- * Returns the options used to create the EntityManagerClient instance.
42
- */
43
- get options() {
44
- return tslib.__classPrivateFieldGet(this, _EntityManagerClient_options, "f");
45
- }
46
- /**
47
- * Executes a batch operation.
48
- *
49
- * @param items - Items to batch execute.
50
- * @param executeBatch - Function to execute the batch.
51
- * @param getUnprocessedItems - Function to get unprocessed items from the output.
52
- * @param options - Batch options.
53
- *
54
- * @typeParam Item - Input item type.
55
- * @typeParam Output - Output type.
56
- *
57
- * @returns Output array.
58
- */
59
- async batchExecute(items, executeBatch, getUnprocessedItems, { batchSize = this.options.batchSize, delayIncrement = this.options.delayIncrement, maxRetries = this.options.maxRetries, throttle = this.options.throttle, } = {}) {
60
- const batches = radash.cluster(items, batchSize);
61
- const outputs = [];
62
- await radash.parallel(throttle, batches, async (batch) => {
63
- let delay = 0;
64
- let retry = 0;
65
- while (batch.length) {
66
- if (delay)
67
- await promises.setTimeout(delay);
68
- const output = await executeBatch(batch);
69
- this.options.logger.debug('executed batch', {
70
- batch,
71
- delay,
72
- retry,
73
- output,
74
- });
75
- outputs.push(output);
76
- batch = getUnprocessedItems?.(output) ?? [];
77
- if (batch.length) {
78
- if (retry === maxRetries)
79
- throw new Error('max retries exceeded');
80
- delay = delay ? delay * 2 : delayIncrement;
81
- retry++;
82
- }
83
- }
84
- });
85
- return outputs;
86
- }
87
- }
88
- _EntityManagerClient_options = new WeakMap();
89
-
90
- exports.EntityManagerClient = EntityManagerClient;
@@ -1,88 +0,0 @@
1
- import { __classPrivateFieldSet, __classPrivateFieldGet } from 'tslib';
2
- import { isFunction, cluster, parallel } from 'radash';
3
- import { setTimeout } from 'timers/promises';
4
- import { conditionalize } from './conditionalize.js';
5
-
6
- var _EntityManagerClient_options;
7
- /**
8
- * EntityManagerClient base class.
9
- *
10
- * @typeParam Options - Options type extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
11
- *
12
- * @category Client
13
- */
14
- class EntityManagerClient {
15
- /**
16
- * EntityManagerClient base constructor.
17
- * @param options - Options object extended from {@link EntityManagerClientOptions | `EntityManagerClientOptions`}.
18
- */
19
- constructor({ batchSize = 25, delayIncrement = 100, maxRetries = 5, throttle = 10, logger = console, logInternals = false, ...childOptions }) {
20
- _EntityManagerClient_options.set(this, void 0);
21
- if (!isFunction(logger.debug))
22
- throw new Error('logger must support debug method');
23
- if (!isFunction(logger.error))
24
- throw new Error('logger must support error method');
25
- __classPrivateFieldSet(this, _EntityManagerClient_options, {
26
- batchSize,
27
- delayIncrement,
28
- maxRetries,
29
- throttle,
30
- logInternals,
31
- logger: {
32
- ...logger,
33
- debug: conditionalize(logger.debug, logInternals),
34
- },
35
- ...childOptions,
36
- }, "f");
37
- }
38
- /**
39
- * Returns the options used to create the EntityManagerClient instance.
40
- */
41
- get options() {
42
- return __classPrivateFieldGet(this, _EntityManagerClient_options, "f");
43
- }
44
- /**
45
- * Executes a batch operation.
46
- *
47
- * @param items - Items to batch execute.
48
- * @param executeBatch - Function to execute the batch.
49
- * @param getUnprocessedItems - Function to get unprocessed items from the output.
50
- * @param options - Batch options.
51
- *
52
- * @typeParam Item - Input item type.
53
- * @typeParam Output - Output type.
54
- *
55
- * @returns Output array.
56
- */
57
- async batchExecute(items, executeBatch, getUnprocessedItems, { batchSize = this.options.batchSize, delayIncrement = this.options.delayIncrement, maxRetries = this.options.maxRetries, throttle = this.options.throttle, } = {}) {
58
- const batches = cluster(items, batchSize);
59
- const outputs = [];
60
- await parallel(throttle, batches, async (batch) => {
61
- let delay = 0;
62
- let retry = 0;
63
- while (batch.length) {
64
- if (delay)
65
- await setTimeout(delay);
66
- const output = await executeBatch(batch);
67
- this.options.logger.debug('executed batch', {
68
- batch,
69
- delay,
70
- retry,
71
- output,
72
- });
73
- outputs.push(output);
74
- batch = getUnprocessedItems?.(output) ?? [];
75
- if (batch.length) {
76
- if (retry === maxRetries)
77
- throw new Error('max retries exceeded');
78
- delay = delay ? delay * 2 : delayIncrement;
79
- retry++;
80
- }
81
- }
82
- });
83
- return outputs;
84
- }
85
- }
86
- _EntityManagerClient_options = new WeakMap();
87
-
88
- export { EntityManagerClient };