@karmaniverous/entity-manager 6.7.5 → 6.8.0

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 (54) hide show
  1. package/dist/cjs/BaseEntityClient.js +1 -1
  2. package/dist/cjs/BaseQueryBuilder.js +1 -1
  3. package/dist/cjs/EntityManager.js +8 -8
  4. package/dist/cjs/ParsedConfig.js +143 -113
  5. package/dist/cjs/addKeys.js +6 -6
  6. package/dist/{mjs/decodeEntityElement.js → cjs/decodeElement.js} +10 -12
  7. package/dist/cjs/decodeGeneratedProperty.js +6 -10
  8. package/dist/cjs/dehydrateIndexItem.js +12 -11
  9. package/dist/cjs/dehydratePageKeyMap.js +10 -7
  10. package/dist/{mjs/encodeEntityElement.js → cjs/encodeElement.js} +8 -10
  11. package/dist/cjs/encodeGeneratedProperty.js +13 -14
  12. package/dist/cjs/getHashKeySpace.js +6 -6
  13. package/dist/cjs/getIndexComponents.js +6 -8
  14. package/dist/cjs/getShardBump.js +1 -1
  15. package/dist/cjs/query.js +1 -1
  16. package/dist/cjs/rehydrateIndexItem.js +12 -10
  17. package/dist/cjs/rehydratePageKeyMap.js +18 -11
  18. package/dist/cjs/removeKeys.js +3 -2
  19. package/dist/cjs/unwrapIndex.js +25 -11
  20. package/dist/cjs/updateItemHashKey.js +5 -3
  21. package/dist/cjs/updateItemRangeKey.js +6 -4
  22. package/dist/cjs/validateGeneratedProperty.js +23 -0
  23. package/dist/cjs/validateIndexToken.js +16 -0
  24. package/dist/cjs/validateTranscodedProperty.js +16 -0
  25. package/dist/index.d.ts +176 -529
  26. package/dist/mjs/BaseEntityClient.js +1 -1
  27. package/dist/mjs/BaseQueryBuilder.js +1 -1
  28. package/dist/mjs/EntityManager.js +8 -8
  29. package/dist/mjs/ParsedConfig.js +143 -113
  30. package/dist/mjs/addKeys.js +6 -6
  31. package/dist/{cjs/decodeEntityElement.js → mjs/decodeElement.js} +8 -14
  32. package/dist/mjs/decodeGeneratedProperty.js +6 -10
  33. package/dist/mjs/dehydrateIndexItem.js +12 -11
  34. package/dist/mjs/dehydratePageKeyMap.js +10 -7
  35. package/dist/{cjs/encodeEntityElement.js → mjs/encodeElement.js} +7 -13
  36. package/dist/mjs/encodeGeneratedProperty.js +13 -14
  37. package/dist/mjs/getHashKeySpace.js +6 -6
  38. package/dist/mjs/getIndexComponents.js +6 -8
  39. package/dist/mjs/getShardBump.js +1 -1
  40. package/dist/mjs/query.js +1 -1
  41. package/dist/mjs/rehydrateIndexItem.js +12 -10
  42. package/dist/mjs/rehydratePageKeyMap.js +18 -11
  43. package/dist/mjs/removeKeys.js +3 -2
  44. package/dist/mjs/unwrapIndex.js +26 -12
  45. package/dist/mjs/updateItemHashKey.js +5 -3
  46. package/dist/mjs/updateItemRangeKey.js +6 -4
  47. package/dist/mjs/validateGeneratedProperty.js +21 -0
  48. package/dist/mjs/validateIndexToken.js +14 -0
  49. package/dist/mjs/validateTranscodedProperty.js +14 -0
  50. package/package.json +5 -5
  51. package/dist/cjs/validateEntityGeneratedProperty.js +0 -29
  52. package/dist/cjs/validateEntityIndexToken.js +0 -22
  53. package/dist/mjs/validateEntityGeneratedProperty.js +0 -27
  54. package/dist/mjs/validateEntityIndexToken.js +0 -20
@@ -1,16 +1,11 @@
1
- 'use strict';
2
-
3
- var validateEntityToken = require('./validateEntityToken.js');
4
-
5
1
  /**
6
- * Encode an {@link Entity | `Entity`} generated property element or ungenerated index component using the associated {@link Transcodes | Transcodes} `encode` function.
2
+ * Encode an {@link EntityItem | `EntityItem`} generated property element or ungenerated index component using the associated {@link Transcodes | Transcodes} `encode` function.
7
3
  *
8
4
  * Returns all `undefined` values.
9
5
  *
10
6
  * If `element` is the {@link Config.hashKey | `hashKey`} or {@link Config.rangeKey | `rangeKey`}, returns the value as-is.
11
7
  *
12
8
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
13
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
14
9
  * @param element - The {@link Entity | `Entity`} generated property element or ungenerated index component to encode.
15
10
  * @param item - Partial {@link ItemMap | `ItemMap`} object.
16
11
  *
@@ -18,16 +13,15 @@ var validateEntityToken = require('./validateEntityToken.js');
18
13
  *
19
14
  * @throws `Error` if `entityToken` is invalid.
20
15
  */
21
- function encodeEntityElement(entityManager, entityToken, element, item) {
16
+ function encodeElement(entityManager, element, item) {
22
17
  try {
23
- validateEntityToken.validateEntityToken(entityManager, entityToken);
24
- const { entities, hashKey, rangeKey, transcodes } = entityManager.config;
18
+ const { hashKey, rangeKey, propertyTranscodes, transcodes } = entityManager.config;
25
19
  const value = item[element];
26
20
  if (value === undefined || [hashKey, rangeKey].includes(element))
27
21
  return value;
28
- const encoded = transcodes[entities[entityToken].elementTranscodes[element]].encode(item[element]) || undefined;
22
+ const encoded = transcodes[propertyTranscodes[element]].encode(item[element]) ||
23
+ undefined;
29
24
  entityManager.logger.debug('encoded entity element', {
30
- entityToken,
31
25
  element,
32
26
  item,
33
27
  encoded,
@@ -36,9 +30,9 @@ function encodeEntityElement(entityManager, entityToken, element, item) {
36
30
  }
37
31
  catch (error) {
38
32
  if (error instanceof Error)
39
- entityManager.logger.error(error.message, { entityToken, element, item });
33
+ entityManager.logger.error(error.message, { element, item });
40
34
  throw error;
41
35
  }
42
36
  }
43
37
 
44
- exports.encodeEntityElement = encodeEntityElement;
38
+ export { encodeElement };
@@ -1,39 +1,39 @@
1
1
  import { isNil } from '@karmaniverous/entity-tools';
2
- import { validateEntityGeneratedProperty } from './validateEntityGeneratedProperty.js';
2
+ import { validateGeneratedProperty } from './validateGeneratedProperty.js';
3
3
 
4
4
  /**
5
- * Encode a generated property value. Returns a string or undefined if atomicity requirement not met.
5
+ * Encode a generated property value. Returns a string or undefined if atomicity requirement of sharded properties not met.
6
6
  *
7
7
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
8
- * @param entityToken - `entityManager.config.entities` key.
9
- * @param property - {@link ConfigEntityGenerated | `entityManager.config.entities.<entityToken>.generated`} key.
8
+ * @param property - {@link Config.generatedProperties | Generated property} key.
10
9
  * @param item - Partial {@link ItemMap | `ItemMap`} object.
11
10
  *
12
11
  * @returns Encoded generated property value.
13
12
  *
14
- * @throws `Error` if `entityToken` is invalid.
15
- * @throws `Error` if `property` is invalid.
13
+ * @throws `Error` if `property` is not a {@link Config.generatedProperties | generated property}.
16
14
  */
17
- function encodeGeneratedProperty(entityManager, entityToken, property, item) {
15
+ function encodeGeneratedProperty(entityManager, property, item) {
18
16
  try {
19
17
  // Validate params.
20
- validateEntityGeneratedProperty(entityManager, entityToken, property);
21
- const { atomic, elements, sharded } = entityManager.config.entities[entityToken].generated[property];
18
+ validateGeneratedProperty(entityManager, property);
19
+ const sharded = property in entityManager.config.generatedProperties.sharded;
20
+ const elements = entityManager.config.generatedProperties[sharded ? 'sharded' : 'unsharded'][property];
22
21
  // Map elements to [element, value] pairs.
23
22
  const elementMap = elements.map((element) => [
24
23
  element,
25
24
  item[element],
26
25
  ]);
27
- // Validate atomicity requirement.
28
- if (atomic && elementMap.some(([, value]) => isNil(value)))
26
+ // Return undefined if sharded & atomicity requirement fails.
27
+ if (sharded && elementMap.some(([, value]) => isNil(value)))
29
28
  return;
30
29
  // Encode property value.
31
30
  const encoded = [
32
- ...(sharded ? [item[entityManager.config.hashKey]] : []),
31
+ ...(sharded
32
+ ? [item[entityManager.config.hashKey]]
33
+ : []),
33
34
  ...elementMap.map(([element, value]) => [element, (value ?? '').toString()].join(entityManager.config.generatedValueDelimiter)),
34
35
  ].join(entityManager.config.generatedKeyDelimiter);
35
36
  entityManager.logger.debug('encoded generated property', {
36
- entityToken,
37
37
  property,
38
38
  item,
39
39
  encoded,
@@ -43,7 +43,6 @@ function encodeGeneratedProperty(entityManager, entityToken, property, item) {
43
43
  catch (error) {
44
44
  if (error instanceof Error)
45
45
  entityManager.logger.error(error.message, {
46
- entityToken,
47
46
  property,
48
47
  item,
49
48
  });
@@ -1,14 +1,14 @@
1
1
  import { range } from 'radash';
2
2
  import { encodeGeneratedProperty } from './encodeGeneratedProperty.js';
3
- import { validateEntityGeneratedProperty } from './validateEntityGeneratedProperty.js';
3
+ import { validateGeneratedProperty } from './validateGeneratedProperty.js';
4
4
 
5
5
  /**
6
6
  * Return an array of {@link ConfigKeys.hashKey | `entityManager.config.hashKey`} property values covering the shard space bounded by `timestampFrom` & `timestampTo`.
7
7
  *
8
8
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
9
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
10
- * @param hashKeyToken - {@link ParsedConfig | `entityManager.config.hashKey`} or {@link ParsedConfig | `entityManager.config.entities.<entityToken>.generated`} key. If a generated property, must be shardable.
11
- * @param item - Partial {@link ItemMap | `ItemMap[EntityToken]`} object. Must include all properties required to generate the hash key space.
9
+ * @param entityToken - {@link Config.entities | `entityManager.config.entities`} key.
10
+ * @param hashKeyToken - {@link ParsedConfig | `entityManager.config.hashKey`} or {@link ParsedConfig | `entityManager.config.generatedProperties.sharded`} key.
11
+ * @param item - {@link EntityItem | `EntityItem`} object. Must include all properties required to generate the hash key space.
12
12
  * @param timestampFrom - Lower timestanp limit. Defaults to `0`.
13
13
  * @param timestampTo - Upper timestamp limit. Defaults to `Date.now()`.
14
14
  *
@@ -20,7 +20,7 @@ function getHashKeySpace(entityManager, entityToken, hashKeyToken, item, timesta
20
20
  try {
21
21
  // Validate hashKeyToken is either the global hash key or a sharded generated property.
22
22
  if (hashKeyToken !== entityManager.config.hashKey)
23
- validateEntityGeneratedProperty(entityManager, entityToken, hashKeyToken, true);
23
+ validateGeneratedProperty(entityManager, hashKeyToken, true);
24
24
  const { shardBumps } = entityManager.config.entities[entityToken];
25
25
  const hashKeySpace = shardBumps
26
26
  // Filter shard bumps by timestamp range.
@@ -40,7 +40,7 @@ function getHashKeySpace(entityManager, entityToken, hashKeyToken, item, timesta
40
40
  let hashKey = `${entityToken}${entityManager.config.shardKeyDelimiter}${shardKey}`;
41
41
  // If hash key space basis is a different property, encode it.
42
42
  if (hashKeyToken !== entityManager.config.hashKey)
43
- hashKey = encodeGeneratedProperty(entityManager, entityToken, hashKeyToken, {
43
+ hashKey = encodeGeneratedProperty(entityManager, hashKeyToken, {
44
44
  ...item,
45
45
  [entityManager.config.hashKey]: hashKey,
46
46
  });
@@ -1,22 +1,20 @@
1
1
  import { unique } from 'radash';
2
- import { validateEntityIndexToken } from './validateEntityIndexToken.js';
2
+ import { validateIndexToken } from './validateIndexToken.js';
3
3
 
4
4
  /**
5
5
  * Get the index components of an entity index. Adds the hash and range keys to the index components.
6
6
  *
7
7
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
8
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
9
- * @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
8
+ * @param indexToken - {@link Config.indexes | `entityManager.config.indexes`} key.
10
9
  *
11
10
  * @returns Array of index components.
12
11
  *
13
- * @throws `Error` if `entityToken` is invalid.
14
12
  * @throws `Error` if `indexToken` is invalid.
15
13
  */
16
- function getIndexComponents(entityManager, entityToken, indexToken) {
17
- validateEntityIndexToken(entityManager, entityToken, indexToken);
18
- const { hashKey, rangeKey, entities } = entityManager.config;
19
- const { hashKey: indexHashKey, rangeKey: indexRangeKey } = entities[entityToken].indexes[indexToken];
14
+ function getIndexComponents(entityManager, indexToken) {
15
+ validateIndexToken(entityManager, indexToken);
16
+ const { hashKey, rangeKey, indexes } = entityManager.config;
17
+ const { hashKey: indexHashKey, rangeKey: indexRangeKey } = indexes[indexToken];
20
18
  return unique([hashKey, rangeKey, indexHashKey, indexRangeKey]);
21
19
  }
22
20
 
@@ -4,7 +4,7 @@ import { validateEntityToken } from './validateEntityToken.js';
4
4
  * Get first entity shard bump before timestamp.
5
5
  *
6
6
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
7
- * @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
7
+ * @param entityToken - {@link Config.entities | `this.config.entities`} key.
8
8
  * @param timestamp - Timestamp in milliseconds.
9
9
  *
10
10
  * @returns {@link ShardBump | `ShardBump`} object.
package/dist/mjs/query.js CHANGED
@@ -11,7 +11,7 @@ const { compressToEncodedURIComponent, decompressFromEncodedURIComponent } = lzS
11
11
  * @remarks
12
12
  * The provided {@link ShardQueryFunction | `ShardQueryFunction`} performs the actual query of individual data pages on individual shards. This function is presumed to express provider-specific query logic, including any necessary indexing or search constraints.
13
13
  *
14
- * Individual shard query results will be combined, deduped by {@link ConfigEntity.uniqueProperty} property value, and sorted by {@link QueryOptions.sortOrder | `sortOrder`}.
14
+ * Individual shard query results will be combined, deduped by {@link Config.uniqueProperty} property value, and sorted by {@link QueryOptions.sortOrder | `sortOrder`}.
15
15
  *
16
16
  * In queries on sharded data, expect the leading and trailing edges of returned data pages to interleave somewhat with preceding & following pages.
17
17
  *
@@ -1,10 +1,11 @@
1
1
  import { shake, zipToObject } from 'radash';
2
- import { decodeEntityElement } from './decodeEntityElement.js';
2
+ import { decodeElement } from './decodeElement.js';
3
3
  import { unwrapIndex } from './unwrapIndex.js';
4
- import { validateEntityIndexToken } from './validateEntityIndexToken.js';
4
+ import { validateEntityToken } from './validateEntityToken.js';
5
+ import { validateIndexToken } from './validateIndexToken.js';
5
6
 
6
7
  /**
7
- * Convert a delimited string into a partial {@link ItemMap | `ItemMap`} object representing the ungenerated component elements of a Config entity index.
8
+ * Convert a delimited string into an {@link EntityItem | `EntityItem`} object representing the ungenerated component elements of a Config entity index, minus its hash key.
8
9
  *
9
10
  * @remarks
10
11
  * Reverses {@link EntityManager.dehydrateIndexItem | `dehydrateIndexItem`}.
@@ -12,31 +13,32 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
12
13
  * {@link EntityManager.dehydrateIndexItem | `dehydrateIndexItem`} alphebetically sorts unwrapped index elements during the dehydration process. This method assumes delimited element values are presented in the same order.
13
14
  *
14
15
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
15
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
16
- * @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
16
+ * @param entityToken - {@link Config.entities | `entityManager.config.entities`} key.
17
+ * @param indexToken - {@link Config.indexes | `entityManager.config.indexes`} key.
17
18
  * @param dehydrated - Dehydrated index value.
18
19
  *
19
- * @returns Partial {@link ItemMap | `ItemMap`} object containing rehydrated index component elements.
20
+ * @returns {@link EntityItem | `EntityItem`} object containing rehydrated index component elements.
20
21
  *
21
22
  * @throws `Error` if `entityToken` is invalid.
22
23
  * @throws `Error` if `indexToken` is invalid.
23
24
  */
24
25
  function rehydrateIndexItem(entityManager, entityToken, indexToken, dehydrated) {
25
26
  try {
26
- const { generatedKeyDelimiter } = entityManager.config;
27
27
  // Validate params.
28
- validateEntityIndexToken(entityManager, entityToken, indexToken);
28
+ validateEntityToken(entityManager, entityToken);
29
+ validateIndexToken(entityManager, indexToken);
29
30
  // Unwrap index elements.
30
- const { hashKey } = entityManager.config.entities[entityToken].indexes[indexToken];
31
+ const { hashKey } = entityManager.config.indexes[indexToken];
31
32
  const elements = unwrapIndex(entityManager, entityToken, indexToken, [
32
33
  hashKey,
33
34
  ]);
34
35
  // Split dehydrated value & validate.
36
+ const { generatedKeyDelimiter } = entityManager.config;
35
37
  const values = dehydrated.split(generatedKeyDelimiter);
36
38
  if (elements.length !== values.length)
37
39
  throw new Error('index rehydration key-value mismatch');
38
40
  // Assign values to elements.
39
- const rehydrated = shake(zipToObject(elements, values.map((value, i) => decodeEntityElement(entityManager, entityToken, elements[i], value))));
41
+ const rehydrated = shake(zipToObject(elements, values.map((value, i) => decodeElement(entityManager, elements[i], value))));
40
42
  entityManager.logger.debug('rehydrated index', {
41
43
  entityToken,
42
44
  indexToken,
@@ -5,7 +5,8 @@ import { getHashKeySpace } from './getHashKeySpace.js';
5
5
  import { getIndexComponents } from './getIndexComponents.js';
6
6
  import { rehydrateIndexItem } from './rehydrateIndexItem.js';
7
7
  import { updateItemRangeKey } from './updateItemRangeKey.js';
8
- import { validateEntityIndexToken } from './validateEntityIndexToken.js';
8
+ import { validateEntityToken } from './validateEntityToken.js';
9
+ import { validateIndexToken } from './validateIndexToken.js';
9
10
 
10
11
  /**
11
12
  * Rehydrate an array of dehydrated page keys into a {@link PageKeyMap | `PageKeyMap`} object.
@@ -13,8 +14,8 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
13
14
  * Reverses the {@link EntityManager.dehydratePageKeyMap | `dehydratePageKeyMap`} method.
14
15
  *
15
16
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
16
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
17
- * @param indexTokens - Array of {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} keys used as keys of the original {@link PageKeyMap | `PageKeyMap`}.
17
+ * @param entityToken - {@link Config.entities | `entityManager.config.entities`} key.
18
+ * @param indexTokens - Array of {@link Config.indexes | `entityManager.config.indexes`} keys used as keys of the original {@link PageKeyMap | `PageKeyMap`}.
18
19
  * @param item - Partial item object sufficiently populated to generate index hash keys.
19
20
  * @param dehydrated - Array of dehydrated page keys or undefined if new query.
20
21
  * @param timestampFrom - Lower timestanp limit used to generate the original {@link PageKeyMap | `PageKeyMap`}. Defaults to `0`.
@@ -30,20 +31,21 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
30
31
  */
31
32
  function rehydratePageKeyMap(entityManager, entityToken, indexTokens, item, dehydrated, timestampFrom = 0, timestampTo = Date.now()) {
32
33
  try {
34
+ // Validate params.
35
+ validateEntityToken(entityManager, entityToken);
33
36
  // Validate indexTokens populated.
34
37
  if (!indexTokens.length)
35
38
  throw new Error('indexTokens empty');
36
39
  // Validate indexTokens exist.
37
40
  const hashKeys = unique(indexTokens.map((indexToken) => {
38
- validateEntityIndexToken(entityManager, entityToken, indexToken);
39
- return entityManager.config.entities[entityToken].indexes[indexToken]
40
- .hashKey;
41
+ validateIndexToken(entityManager, indexToken);
42
+ return entityManager.config.indexes[indexToken].hashKey;
41
43
  }));
42
44
  // Validate hashKeys consistent.
43
45
  if (hashKeys.length > 1)
44
46
  throw new Error('inconsistent hashKeys');
45
47
  const [hashKeyToken] = hashKeys;
46
- indexTokens.map((index) => validateEntityIndexToken(entityManager, entityToken, index));
48
+ indexTokens.map((index) => validateIndexToken(entityManager, index));
47
49
  // Shortcut empty dehydrated.
48
50
  if (dehydrated && !dehydrated.length)
49
51
  return [hashKeyToken, {}];
@@ -55,17 +57,22 @@ function rehydratePageKeyMap(entityManager, entityToken, indexTokens, item, dehy
55
57
  if (dehydrated.length !== hashKeySpace.length * indexTokens.length)
56
58
  throw new Error('dehydrated length mismatch');
57
59
  // Rehydrate pageKeys.
60
+ const uniqueProperty = entityManager.config.entities[entityToken]
61
+ .uniqueProperty;
62
+ const { sharded, unsharded } = entityManager.config.generatedProperties;
58
63
  const rehydrated = mapValues(zipToObject(indexTokens, cluster(dehydrated, hashKeySpace.length)), (dehydratedIndexPageKeyMaps, index) => zipToObject(hashKeySpace, (hashKey, i) => {
59
64
  if (!dehydratedIndexPageKeyMaps[i])
60
65
  return;
61
66
  let pageKeyItem = {
62
- ...decodeGeneratedProperty(entityManager, entityToken, hashKey),
67
+ ...decodeGeneratedProperty(entityManager, hashKey),
63
68
  ...rehydrateIndexItem(entityManager, entityToken, index, dehydratedIndexPageKeyMaps[i]),
64
69
  };
65
70
  pageKeyItem = updateItemRangeKey(entityManager, entityToken, pageKeyItem);
66
- return zipToObject(getIndexComponents(entityManager, entityToken, index), (component) => entityManager.config.entities[entityToken].generated[component]
67
- ? encodeGeneratedProperty(entityManager, entityToken, component, pageKeyItem)
68
- : pageKeyItem[component]);
71
+ return zipToObject(getIndexComponents(entityManager, index), (component) => component === entityManager.config.rangeKey
72
+ ? [uniqueProperty, pageKeyItem[uniqueProperty]].join(entityManager.config.generatedValueDelimiter)
73
+ : component in sharded || component in unsharded
74
+ ? encodeGeneratedProperty(entityManager, component, pageKeyItem)
75
+ : pageKeyItem[component]);
69
76
  }));
70
77
  entityManager.logger.debug('rehydrated page key map', {
71
78
  entityToken,
@@ -4,7 +4,7 @@ import { validateEntityToken } from './validateEntityToken.js';
4
4
  * Strips generated properties, hash key, and range key from an {@link ItemMap | `ItemMap`} object.
5
5
  *
6
6
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
7
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
7
+ * @param entityToken - {@link Config.entities | `entityManager.config.entities`} key.
8
8
  * @param item - {@link ItemMap | `ItemMap`} object.
9
9
  *
10
10
  * @returns Shallow clone of `item` without generated properties, hash key or range key.
@@ -20,7 +20,8 @@ function removeKeys(entityManager, entityToken, item) {
20
20
  delete newItem[entityManager.config.hashKey];
21
21
  delete newItem[entityManager.config.rangeKey];
22
22
  // Delete generated properties.
23
- for (const property in entityManager.config.entities[entityToken].generated)
23
+ const { sharded, unsharded } = entityManager.config.generatedProperties;
24
+ for (const property in { ...sharded, ...unsharded })
24
25
  delete newItem[property];
25
26
  entityManager.logger.debug('stripped entity item generated properties', {
26
27
  entityToken,
@@ -1,12 +1,13 @@
1
- import { shake, unique } from 'radash';
1
+ import { unique } from 'radash';
2
2
  import { getIndexComponents } from './getIndexComponents.js';
3
- import { validateEntityIndexToken } from './validateEntityIndexToken.js';
3
+ import { validateEntityToken } from './validateEntityToken.js';
4
+ import { validateIndexToken } from './validateIndexToken.js';
4
5
 
5
6
  /**
6
- * Unwraps an {@link ConfigEntity.indexes | Entity index} into deduped, sorted, ungenerated index component elements.
7
+ * Unwraps an {@link Config.indexes | index} into deduped, sorted, ungenerated index component elements.
7
8
  *
8
9
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
9
- * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
10
+ * @param entityToken - {@link Config.entities | `entityManager.config.entities`} key.
10
11
  * @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
11
12
  * @param omit - Array of index components or elements to omit from the output value.
12
13
  *
@@ -18,24 +19,37 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
18
19
  function unwrapIndex(entityManager, entityToken, indexToken, omit = []) {
19
20
  try {
20
21
  // Validate params.
21
- validateEntityIndexToken(entityManager, entityToken, indexToken);
22
- const generated = entityManager.config.entities[entityToken].generated;
23
- const generatedKeys = Object.keys(shake(generated));
24
- return unique(getIndexComponents(entityManager, entityToken, indexToken)
22
+ validateEntityToken(entityManager, entityToken);
23
+ validateIndexToken(entityManager, indexToken);
24
+ const { sharded, unsharded } = entityManager.config.generatedProperties;
25
+ const unwrapped = unique(getIndexComponents(entityManager, indexToken)
25
26
  .filter((component) => !omit.includes(component))
26
27
  .map((component) => component === entityManager.config.hashKey
27
28
  ? entityManager.config.entities[entityToken].timestampProperty
28
29
  : component === entityManager.config.rangeKey
29
30
  ? entityManager.config.entities[entityToken].uniqueProperty
30
- : generatedKeys.includes(component)
31
- ? generated[component].elements
32
- : component)
31
+ : component in sharded
32
+ ? sharded[component]
33
+ : component in unsharded
34
+ ? unsharded[component]
35
+ : component)
33
36
  .flat()
34
37
  .filter((element) => !omit.includes(element))).sort();
38
+ entityManager.logger.debug('unwrapped index', {
39
+ entityToken,
40
+ indexToken,
41
+ omit,
42
+ unwrapped,
43
+ });
44
+ return unwrapped;
35
45
  }
36
46
  catch (error) {
37
47
  if (error instanceof Error)
38
- entityManager.logger.error(error.message, { indexToken, entityToken });
48
+ entityManager.logger.error(error.message, {
49
+ entityToken,
50
+ indexToken,
51
+ omit,
52
+ });
39
53
  throw error;
40
54
  }
41
55
  }
@@ -7,7 +7,7 @@ import { validateEntityToken } from './validateEntityToken.js';
7
7
  * Update the hash key on a partial {@link ItemMap | `ItemMap`} object.
8
8
  *
9
9
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
10
- * @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
10
+ * @param entityToken - {@link Config.entities | `this.config.entities`} key.
11
11
  * @param item - Partial {@link ItemMap | `ItemMap`} object.
12
12
  * @param overwrite - Overwrite existing {@link ConfigKeys.hashKey | `this.config.hashKey`} property value (default `false`).
13
13
  *
@@ -20,7 +20,8 @@ function updateItemHashKey(entityManager, entityToken, item, overwrite = false)
20
20
  // Validate params.
21
21
  validateEntityToken(entityManager, entityToken);
22
22
  // Return current item if hashKey exists and overwrite is false.
23
- if (item[entityManager.config.hashKey] && !overwrite) {
23
+ if (item[entityManager.config.hashKey] &&
24
+ !overwrite) {
24
25
  entityManager.logger.debug('did not overwrite existing entity item hash key', {
25
26
  item,
26
27
  entityToken,
@@ -29,7 +30,8 @@ function updateItemHashKey(entityManager, entityToken, item, overwrite = false)
29
30
  return { ...item };
30
31
  }
31
32
  // Get item timestamp property & validate.
32
- const timestamp = item[entityManager.config.entities[entityToken].timestampProperty];
33
+ const timestamp = item[entityManager.config.entities[entityToken]
34
+ .timestampProperty];
33
35
  if (isNil(timestamp))
34
36
  throw new Error(`missing item timestamp property`);
35
37
  // Find first entity sharding bump before timestamp.
@@ -5,21 +5,22 @@ import { validateEntityToken } from './validateEntityToken.js';
5
5
  * Update the range key on a partial {@link ItemMap | `ItemMap`} object.
6
6
  *
7
7
  * @param entityManager - {@link EntityManager | `EntityManager`} instance.
8
- * @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
8
+ * @param entityToken - {@link Config.entities | `this.config.entities`} key.
9
9
  * @param item - Partial {@link ItemMap | `ItemMap`} object.
10
10
  * @param overwrite - Overwrite existing {@link ConfigKeys.rangeKey | `this.config.rangeKey`} property value (default `false`).
11
11
  *
12
12
  * @returns Shallow clone of `item` with updated range key.
13
13
  *
14
14
  * @throws `Error` if `entityToken` is invalid.
15
- * @throws `Error` if `item` {@link ConfigEntity.uniqueProperty | `this.config.entities<entityToken>.uniqueProperty`} property value is missing.
15
+ * @throws `Error` if `item` {@link Config.uniqueProperty | `this.config.entities<entityToken>.uniqueProperty`} property value is missing.
16
16
  */
17
17
  function updateItemRangeKey(entityManager, entityToken, item, overwrite = false) {
18
18
  try {
19
19
  // Validate params.
20
20
  validateEntityToken(entityManager, entityToken);
21
21
  // Return current item if rangeKey exists and overwrite is false.
22
- if (item[entityManager.config.rangeKey] && !overwrite) {
22
+ if (item[entityManager.config.rangeKey] &&
23
+ !overwrite) {
23
24
  entityManager.logger.debug('did not overwrite existing entity item range key', {
24
25
  entityToken,
25
26
  item,
@@ -28,7 +29,8 @@ function updateItemRangeKey(entityManager, entityToken, item, overwrite = false)
28
29
  return { ...item };
29
30
  }
30
31
  // Get item unique property & validate.
31
- const uniqueProperty = item[entityManager.config.entities[entityToken].uniqueProperty];
32
+ const uniqueProperty = item[entityManager.config.entities[entityToken]
33
+ .uniqueProperty];
32
34
  if (isNil(uniqueProperty))
33
35
  throw new Error(`missing item unique property`);
34
36
  // Update range key.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Validate that a property is defined as an {@link EntityManager | `EntityManager`} {@link Config.generatedProperties | generated property}.
3
+ *
4
+ * @param entityManager - {@link EntityManager | `EntityManager`} instance.
5
+ * @param property - {@link Config.generatedProperties | Generated property} key.
6
+ * @param isSharded - Whether the generated property is sharded. `undefined` indicates no constraint.
7
+ *
8
+ * @throws `Error` if `property` is not a {@link Config.generatedProperties | generated property}.
9
+ * @throws `Error` if `sharded` is specified & does not match {@link Config.generatedProperties | generated property} type.
10
+ */
11
+ function validateGeneratedProperty(entityManager, property, isSharded) {
12
+ const { sharded, unsharded } = entityManager.config.generatedProperties;
13
+ if (!(property in sharded) && !(property in unsharded))
14
+ throw new Error('invalid generated property');
15
+ if (isSharded !== undefined &&
16
+ ((isSharded && !(property in sharded)) ||
17
+ (!isSharded && !(property in unsharded))))
18
+ throw new Error(`generated property ${isSharded ? 'not ' : ''}sharded`);
19
+ }
20
+
21
+ export { validateGeneratedProperty };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Validate that an entity index is defined in EntityManager config.
3
+ *
4
+ * @param entityManager - {@link EntityManager | `EntityManager`} instance.
5
+ * @param indexToken - {@link Config.indexes | `entityManager.config.indexes`} key.
6
+ *
7
+ * @throws `Error` if `indexToken` is invalid.
8
+ */
9
+ function validateIndexToken(entityManager, indexToken) {
10
+ if (!(indexToken in entityManager.config.indexes))
11
+ throw new Error('invalid index token');
12
+ }
13
+
14
+ export { validateIndexToken };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Validate that a property is defined as an {@link EntityManager | `EntityManager`} {@link Config.propertyTranscodes | transcoded property}.
3
+ *
4
+ * @param entityManager - {@link EntityManager | `EntityManager`} instance.
5
+ * @param property - {@link Config.propertyTranscodes | Transcoded property} key.
6
+ *
7
+ * @throws `Error` if `property` is not a {@link Config.propertyTranscodes | transcoded property}.
8
+ */
9
+ function validateTranscodedProperty(entityManager, property) {
10
+ if (!(property in entityManager.config.propertyTranscodes))
11
+ throw new Error('invalid transcoded property');
12
+ }
13
+
14
+ export { validateTranscodedProperty };
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "dependencies": {
7
7
  "@karmaniverous/batch-process": "^0.1.0",
8
- "@karmaniverous/entity-tools": "^0.4.4",
8
+ "@karmaniverous/entity-tools": "^0.5.0",
9
9
  "@karmaniverous/string-utilities": "^0.2.1",
10
10
  "lz-string": "^1.5.0",
11
11
  "radash": "^12.1.0",
@@ -17,7 +17,7 @@
17
17
  "@dotenvx/dotenvx": "^1.22.0",
18
18
  "@eslint/js": "^9.14.0",
19
19
  "@faker-js/faker": "^9.2.0",
20
- "@karmaniverous/mock-db": "^0.3.3",
20
+ "@karmaniverous/mock-db": "^0.3.4",
21
21
  "@rollup/plugin-alias": "^5.1.1",
22
22
  "@rollup/plugin-commonjs": "^28.0.1",
23
23
  "@rollup/plugin-json": "^6.1.0",
@@ -46,13 +46,13 @@
46
46
  "prettier": "^3.3.3",
47
47
  "release-it": "^17.10.0",
48
48
  "rimraf": "^6.0.1",
49
- "rollup": "^4.24.4",
49
+ "rollup": "^4.25.0",
50
50
  "rollup-plugin-dts": "^6.1.1",
51
51
  "source-map-support": "^0.5.21",
52
52
  "ts-node": "^10.9.2",
53
53
  "tslib": "^2.8.1",
54
54
  "typedoc": "^0.26.11",
55
- "typedoc-plugin-mdn-links": "^3.3.6",
55
+ "typedoc-plugin-mdn-links": "^3.3.7",
56
56
  "typedoc-plugin-replace-text": "^4.0.0",
57
57
  "typedoc-plugin-zod": "^1.2.1",
58
58
  "typescript": "^5.6.3",
@@ -132,5 +132,5 @@
132
132
  },
133
133
  "type": "module",
134
134
  "types": "dist/index.d.ts",
135
- "version": "6.7.5"
135
+ "version": "6.8.0"
136
136
  }
@@ -1,29 +0,0 @@
1
- 'use strict';
2
-
3
- var validateEntityToken = require('./validateEntityToken.js');
4
-
5
- /**
6
- * Validate that an entity generated property is defined in EntityManager
7
- * config.
8
- *
9
- * @param entityManager - {@link EntityManager | `EntityManager`} instance.
10
- * @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
11
- * @param property - {@link ConfigEntityGenerated | `this.config.entities.<entityToken>.generated`} key.
12
- * @param sharded - Whether the generated property is sharded. `undefined` indicates no constraint.
13
- *
14
- * @throws `Error` if `entityToken` is invalid.
15
- * @throws `Error` if `property` is invalid.
16
- * @throws `Error` if `sharded` is specified & does not match `this.config.entities.<entityToken>.generated.<property>.sharded`.
17
- */
18
- function validateEntityGeneratedProperty(entityManager, entityToken, property, sharded) {
19
- validateEntityToken.validateEntityToken(entityManager, entityToken);
20
- const generated = entityManager.config.entities[entityToken].generated[property];
21
- if (!generated && property !== entityManager.config.hashKey)
22
- throw new Error('invalid entity generated property');
23
- if (sharded !== undefined &&
24
- ((generated && sharded !== generated.sharded) ||
25
- (!sharded && property === entityManager.config.hashKey)))
26
- throw new Error(`entity generated property ${sharded ? 'not ' : ''}sharded`);
27
- }
28
-
29
- exports.validateEntityGeneratedProperty = validateEntityGeneratedProperty;
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- var validateEntityToken = require('./validateEntityToken.js');
4
-
5
- /**
6
- * Validate that an entity index is defined in EntityManager config.
7
- *
8
- * @param entityManager - {@link EntityManager | `EntityManager`} instance.
9
- * @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
10
- * @param indexToken - {@link ConfigEntity.indexes | `this.config.entities.<entityToken>.indexes`} key.
11
- *
12
- * @throws `Error` if `entityToken` is invalid.
13
- * @throws `Error` if `indexToken` is invalid.
14
- */
15
- function validateEntityIndexToken(entityManager, entityToken, indexToken) {
16
- validateEntityToken.validateEntityToken(entityManager, entityToken);
17
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18
- if (!entityManager.config.entities[entityToken].indexes[indexToken])
19
- throw new Error('invalid entity index token');
20
- }
21
-
22
- exports.validateEntityIndexToken = validateEntityIndexToken;