@karmaniverous/entity-manager 6.13.3 → 6.14.1

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 (59) hide show
  1. package/README.md +330 -16
  2. package/dist/cjs/{EntityManager.js → EntityManager/EntityManager.js} +18 -44
  3. package/dist/cjs/{ParsedConfig.js → EntityManager/ParsedConfig.js} +46 -55
  4. package/dist/cjs/{addKeys.js → EntityManager/addKeys.js} +1 -0
  5. package/dist/cjs/{decodeElement.js → EntityManager/decodeElement.js} +2 -1
  6. package/dist/cjs/{dehydratePageKeyMap.js → EntityManager/dehydratePageKeyMap.js} +3 -1
  7. package/dist/cjs/{encodeElement.js → EntityManager/encodeElement.js} +2 -2
  8. package/dist/cjs/{encodeGeneratedProperty.js → EntityManager/encodeGeneratedProperty.js} +1 -1
  9. package/dist/cjs/EntityManager/getPrimaryKey.js +25 -0
  10. package/dist/cjs/{rehydratePageKeyMap.js → EntityManager/rehydratePageKeyMap.js} +3 -1
  11. package/dist/cjs/{removeKeys.js → EntityManager/removeKeys.js} +10 -8
  12. package/dist/cjs/{updateItemHashKey.js → EntityManager/updateItemHashKey.js} +4 -1
  13. package/dist/cjs/index.js +5 -3
  14. package/dist/index.d.ts +109 -252
  15. package/dist/mjs/{EntityManager.js → EntityManager/EntityManager.js} +18 -44
  16. package/dist/mjs/{ParsedConfig.js → EntityManager/ParsedConfig.js} +46 -55
  17. package/dist/mjs/{addKeys.js → EntityManager/addKeys.js} +1 -0
  18. package/dist/mjs/{decodeElement.js → EntityManager/decodeElement.js} +2 -1
  19. package/dist/mjs/{dehydratePageKeyMap.js → EntityManager/dehydratePageKeyMap.js} +3 -1
  20. package/dist/mjs/{encodeElement.js → EntityManager/encodeElement.js} +2 -2
  21. package/dist/mjs/{encodeGeneratedProperty.js → EntityManager/encodeGeneratedProperty.js} +1 -1
  22. package/dist/mjs/EntityManager/getPrimaryKey.js +23 -0
  23. package/dist/mjs/{rehydratePageKeyMap.js → EntityManager/rehydratePageKeyMap.js} +3 -1
  24. package/dist/mjs/{removeKeys.js → EntityManager/removeKeys.js} +10 -8
  25. package/dist/mjs/{updateItemHashKey.js → EntityManager/updateItemHashKey.js} +4 -1
  26. package/dist/mjs/index.js +4 -3
  27. package/package.json +44 -45
  28. /package/dist/cjs/{BaseEntityClient.js → BaseEntityClient/BaseEntityClient.js} +0 -0
  29. /package/dist/cjs/{BaseQueryBuilder.js → BaseQueryBuilder/BaseQueryBuilder.js} +0 -0
  30. /package/dist/cjs/{decodeGeneratedProperty.js → EntityManager/decodeGeneratedProperty.js} +0 -0
  31. /package/dist/cjs/{dehydrateIndexItem.js → EntityManager/dehydrateIndexItem.js} +0 -0
  32. /package/dist/cjs/{findIndexToken.js → EntityManager/findIndexToken.js} +0 -0
  33. /package/dist/cjs/{getHashKeySpace.js → EntityManager/getHashKeySpace.js} +0 -0
  34. /package/dist/cjs/{getIndexComponents.js → EntityManager/getIndexComponents.js} +0 -0
  35. /package/dist/cjs/{getShardBump.js → EntityManager/getShardBump.js} +0 -0
  36. /package/dist/cjs/{query.js → EntityManager/query.js} +0 -0
  37. /package/dist/cjs/{rehydrateIndexItem.js → EntityManager/rehydrateIndexItem.js} +0 -0
  38. /package/dist/cjs/{unwrapIndex.js → EntityManager/unwrapIndex.js} +0 -0
  39. /package/dist/cjs/{updateItemRangeKey.js → EntityManager/updateItemRangeKey.js} +0 -0
  40. /package/dist/cjs/{validateEntityToken.js → EntityManager/validateEntityToken.js} +0 -0
  41. /package/dist/cjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js} +0 -0
  42. /package/dist/cjs/{validateIndexToken.js → EntityManager/validateIndexToken.js} +0 -0
  43. /package/dist/cjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js} +0 -0
  44. /package/dist/mjs/{BaseEntityClient.js → BaseEntityClient/BaseEntityClient.js} +0 -0
  45. /package/dist/mjs/{BaseQueryBuilder.js → BaseQueryBuilder/BaseQueryBuilder.js} +0 -0
  46. /package/dist/mjs/{decodeGeneratedProperty.js → EntityManager/decodeGeneratedProperty.js} +0 -0
  47. /package/dist/mjs/{dehydrateIndexItem.js → EntityManager/dehydrateIndexItem.js} +0 -0
  48. /package/dist/mjs/{findIndexToken.js → EntityManager/findIndexToken.js} +0 -0
  49. /package/dist/mjs/{getHashKeySpace.js → EntityManager/getHashKeySpace.js} +0 -0
  50. /package/dist/mjs/{getIndexComponents.js → EntityManager/getIndexComponents.js} +0 -0
  51. /package/dist/mjs/{getShardBump.js → EntityManager/getShardBump.js} +0 -0
  52. /package/dist/mjs/{query.js → EntityManager/query.js} +0 -0
  53. /package/dist/mjs/{rehydrateIndexItem.js → EntityManager/rehydrateIndexItem.js} +0 -0
  54. /package/dist/mjs/{unwrapIndex.js → EntityManager/unwrapIndex.js} +0 -0
  55. /package/dist/mjs/{updateItemRangeKey.js → EntityManager/updateItemRangeKey.js} +0 -0
  56. /package/dist/mjs/{validateEntityToken.js → EntityManager/validateEntityToken.js} +0 -0
  57. /package/dist/mjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js} +0 -0
  58. /package/dist/mjs/{validateIndexToken.js → EntityManager/validateIndexToken.js} +0 -0
  59. /package/dist/mjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js} +0 -0
@@ -10,7 +10,7 @@ const validateArrayUnique = (arr, ctx, identity = (item) => item, path = []) =>
10
10
  for (const [element, count] of Object.entries(counts)) {
11
11
  if (count > 1)
12
12
  ctx.addIssue({
13
- code: zod.z.ZodIssueCode.custom,
13
+ code: 'custom',
14
14
  message: `duplicate array element`,
15
15
  params: { element },
16
16
  path,
@@ -21,7 +21,7 @@ const validateKeysExclusive = (keys, label, ref, ctx) => {
21
21
  const intersection = keys.filter((key) => ref.includes(key));
22
22
  if (intersection.length)
23
23
  ctx.addIssue({
24
- code: zod.z.ZodIssueCode.custom,
24
+ code: 'custom',
25
25
  message: `${label} key collision: ${intersection.toString()}`,
26
26
  });
27
27
  };
@@ -32,26 +32,14 @@ const componentArray = zod.z
32
32
  const configSchema = zod.z
33
33
  .object({
34
34
  entities: zod.z
35
- .record(zod.z
35
+ .record(zod.z.string(), zod.z
36
36
  .object({
37
- defaultLimit: zod.z
38
- .number()
39
- .int()
40
- .positive()
41
- .safe()
42
- .optional()
43
- .default(10),
44
- defaultPageSize: zod.z
45
- .number()
46
- .int()
47
- .positive()
48
- .safe()
49
- .optional()
50
- .default(10),
37
+ defaultLimit: zod.z.number().int().positive().optional().default(10),
38
+ defaultPageSize: zod.z.number().int().positive().optional().default(10),
51
39
  shardBumps: zod.z
52
40
  .array(zod.z
53
41
  .object({
54
- timestamp: zod.z.number().nonnegative().safe(),
42
+ timestamp: zod.z.number().int().nonnegative(),
55
43
  charBits: zod.z.number().int().min(1).max(5),
56
44
  chars: zod.z.number().int().min(0).max(40),
57
45
  })
@@ -79,7 +67,7 @@ const configSchema = zod.z
79
67
  for (let i = 1; i < val.length; i++)
80
68
  if (val[i].chars <= val[i - 1].chars)
81
69
  ctx.addIssue({
82
- code: zod.z.ZodIssueCode.custom,
70
+ code: 'custom',
83
71
  message: `shardBump chars do not monotonically increase at timestamp ${val[i].timestamp.toString()}`,
84
72
  path: [i],
85
73
  });
@@ -93,14 +81,14 @@ const configSchema = zod.z
93
81
  .default({}),
94
82
  generatedProperties: zod.z
95
83
  .object({
96
- sharded: zod.z.record(componentArray).optional().default({}),
97
- unsharded: zod.z.record(componentArray).optional().default({}),
84
+ sharded: zod.z.record(zod.z.string(), componentArray).optional().default({}),
85
+ unsharded: zod.z.record(zod.z.string(), componentArray).optional().default({}),
98
86
  })
99
87
  .optional()
100
88
  .default({ sharded: {}, unsharded: {} }),
101
89
  hashKey: zod.z.string(),
102
90
  indexes: zod.z
103
- .record(zod.z.object({
91
+ .record(zod.z.string(), zod.z.object({
104
92
  hashKey: zod.z.string().min(1),
105
93
  rangeKey: zod.z.string().min(1),
106
94
  projections: zod.z
@@ -112,15 +100,18 @@ const configSchema = zod.z
112
100
  .default({}),
113
101
  generatedKeyDelimiter: zod.z.string().regex(/\W+/).optional().default('|'),
114
102
  generatedValueDelimiter: zod.z.string().regex(/\W+/).optional().default('#'),
115
- propertyTranscodes: zod.z.record(zod.z.string()).optional().default({}),
103
+ propertyTranscodes: zod.z.record(zod.z.string(), zod.z.string()).optional().default({}),
116
104
  rangeKey: zod.z.string(),
117
105
  shardKeyDelimiter: zod.z.string().regex(/\W+/).optional().default('!'),
118
- throttle: zod.z.number().int().positive().safe().optional().default(10),
106
+ throttle: zod.z.number().int().positive().optional().default(10),
119
107
  transcodes: zod.z
120
- .record(zod.z
108
+ .record(zod.z.string(), zod.z
121
109
  .object({
122
- encode: zod.z.function().args(zod.z.any()).returns(zod.z.string()),
123
- decode: zod.z.function().args(zod.z.string()).returns(zod.z.any()),
110
+ // Accept function shapes without relying on z.function()
111
+ // to avoid TS inference conflicts across Zod versions and
112
+ // to remain compatible with narrower parameter types.
113
+ encode: zod.z.custom((fn) => typeof fn === 'function'),
114
+ decode: zod.z.custom((fn) => typeof fn === 'function'),
124
115
  })
125
116
  .strict())
126
117
  .optional()
@@ -131,7 +122,7 @@ const configSchema = zod.z
131
122
  // validate no generated key delimiter collision
132
123
  if (data.generatedKeyDelimiter.includes(data.generatedValueDelimiter))
133
124
  ctx.addIssue({
134
- code: zod.z.ZodIssueCode.custom,
125
+ code: 'custom',
135
126
  message: 'generatedKeyDelimiter contains generatedValueDelimiter',
136
127
  params: {
137
128
  generatedKeyDelimiter: data.generatedKeyDelimiter,
@@ -141,7 +132,7 @@ const configSchema = zod.z
141
132
  });
142
133
  if (data.generatedKeyDelimiter.includes(data.shardKeyDelimiter))
143
134
  ctx.addIssue({
144
- code: zod.z.ZodIssueCode.custom,
135
+ code: 'custom',
145
136
  message: 'generatedKeyDelimiter contains shardKeyDelimiter',
146
137
  params: {
147
138
  generatedKeyDelimiter: data.generatedKeyDelimiter,
@@ -152,7 +143,7 @@ const configSchema = zod.z
152
143
  // validate no generated value delimiter collision
153
144
  if (data.generatedValueDelimiter.includes(data.generatedKeyDelimiter))
154
145
  ctx.addIssue({
155
- code: zod.z.ZodIssueCode.custom,
146
+ code: 'custom',
156
147
  message: 'generatedValueDelimiter contains generatedKeyDelimiter',
157
148
  params: {
158
149
  generatedValueDelimiter: data.generatedValueDelimiter,
@@ -162,7 +153,7 @@ const configSchema = zod.z
162
153
  });
163
154
  if (data.generatedValueDelimiter.includes(data.shardKeyDelimiter))
164
155
  ctx.addIssue({
165
- code: zod.z.ZodIssueCode.custom,
156
+ code: 'custom',
166
157
  message: 'generatedValueDelimiter contains shardKeyDelimiter',
167
158
  params: {
168
159
  generatedValueDelimiter: data.generatedValueDelimiter,
@@ -173,7 +164,7 @@ const configSchema = zod.z
173
164
  // validate no shard key delimiter collision
174
165
  if (data.shardKeyDelimiter.includes(data.generatedKeyDelimiter))
175
166
  ctx.addIssue({
176
- code: zod.z.ZodIssueCode.custom,
167
+ code: 'custom',
177
168
  message: 'shardKeyDelimiter contains generatedKeyDelimiter',
178
169
  params: {
179
170
  generatedKeyDelimiter: data.generatedKeyDelimiter,
@@ -183,7 +174,7 @@ const configSchema = zod.z
183
174
  });
184
175
  if (data.shardKeyDelimiter.includes(data.generatedValueDelimiter))
185
176
  ctx.addIssue({
186
- code: zod.z.ZodIssueCode.custom,
177
+ code: 'custom',
187
178
  message: 'shardKeyDelimiter contains generatedValueDelimiter',
188
179
  params: {
189
180
  generatedValueDelimiter: data.generatedValueDelimiter,
@@ -213,19 +204,17 @@ const configSchema = zod.z
213
204
  for (const [property, transcode] of Object.entries(data.propertyTranscodes))
214
205
  if (!transcodes.includes(transcode))
215
206
  ctx.addIssue({
216
- code: zod.z.ZodIssueCode.invalid_enum_value,
217
- options: transcodes,
207
+ code: 'custom',
208
+ message: `propertyTranscodes['${property}'] references unknown transcode '${transcode}'`,
218
209
  path: ['propertyTranscodes', property],
219
- received: transcode,
220
210
  });
221
211
  // Validate all sharded property elements are transcoded properties.
222
212
  for (const [property, elements] of Object.entries(data.generatedProperties.sharded))
223
213
  for (const element of elements)
224
214
  if (!transcodedProperties.includes(element))
225
215
  ctx.addIssue({
226
- code: zod.z.ZodIssueCode.invalid_enum_value,
227
- options: transcodedProperties,
228
- received: element,
216
+ code: 'custom',
217
+ message: `generatedProperties.sharded['${property}'] contains non-transcoded element '${element}'`,
229
218
  path: ['generatedProperties', 'sharded', property],
230
219
  });
231
220
  // Validate all unsharded property elements are transcoded properties.
@@ -233,9 +222,8 @@ const configSchema = zod.z
233
222
  for (const element of elements)
234
223
  if (!transcodedProperties.includes(element))
235
224
  ctx.addIssue({
236
- code: zod.z.ZodIssueCode.invalid_enum_value,
237
- options: transcodedProperties,
238
- received: element,
225
+ code: 'custom',
226
+ message: `generatedProperties.unsharded['${property}'] contains non-transcoded element '${element}'`,
239
227
  path: ['generatedProperties', 'unsharded', property],
240
228
  });
241
229
  // Validate indexes.
@@ -244,19 +232,24 @@ const configSchema = zod.z
244
232
  // Validate hash key is sharded.
245
233
  if (![data.hashKey, ...shardedKeys].includes(hashKey)) {
246
234
  ctx.addIssue({
247
- code: zod.z.ZodIssueCode.invalid_enum_value,
248
- options: [data.hashKey, ...shardedKeys],
235
+ code: 'custom',
236
+ message: `index '${indexKey}' hashKey '${hashKey}' must be one of [${[
237
+ data.hashKey,
238
+ ...shardedKeys,
239
+ ].join(', ')}]`,
249
240
  path: ['indexes', indexKey, 'hashKey'],
250
- received: hashKey,
251
241
  });
252
242
  }
253
243
  // Validate range key is unsharded or transcodable.
254
244
  if (![data.rangeKey, ...unshardedKeys, ...transcodedProperties].includes(rangeKey)) {
255
245
  ctx.addIssue({
256
- code: zod.z.ZodIssueCode.invalid_enum_value,
257
- options: [data.rangeKey, ...unshardedKeys],
246
+ code: 'custom',
247
+ message: `index '${indexKey}' rangeKey '${rangeKey}' must be one of [${[
248
+ data.rangeKey,
249
+ ...unshardedKeys,
250
+ ...transcodedProperties,
251
+ ].join(', ')}]`,
258
252
  path: ['indexes', indexKey, 'rangeKey'],
259
- received: rangeKey,
260
253
  });
261
254
  }
262
255
  // Validate no index projections are keys.
@@ -271,7 +264,7 @@ const configSchema = zod.z
271
264
  ...unshardedKeys,
272
265
  ].includes(projection))
273
266
  ctx.addIssue({
274
- code: zod.z.ZodIssueCode.custom,
267
+ code: 'custom',
275
268
  message: 'index projection is a key',
276
269
  params: { projection },
277
270
  path: ['indexes', indexKey, 'projections'],
@@ -282,18 +275,16 @@ const configSchema = zod.z
282
275
  // validate timestampProperty is a transcoded property.
283
276
  if (!transcodedProperties.includes(timestampProperty))
284
277
  ctx.addIssue({
285
- code: zod.z.ZodIssueCode.invalid_enum_value,
286
- options: transcodedProperties,
278
+ code: 'custom',
279
+ message: `entities['${entityToken}'].timestampProperty '${timestampProperty}' must be one of [${transcodedProperties.join(', ')}]`,
287
280
  path: ['entities', entityToken, 'timestampProperty'],
288
- received: timestampProperty,
289
281
  });
290
282
  // validate uniqueProperty is a transcoded property.
291
283
  if (!transcodedProperties.includes(uniqueProperty))
292
284
  ctx.addIssue({
293
- code: zod.z.ZodIssueCode.invalid_enum_value,
294
- options: transcodedProperties,
285
+ code: 'custom',
286
+ message: `entities['${entityToken}'].uniqueProperty '${uniqueProperty}' must be one of [${transcodedProperties.join(', ')}]`,
295
287
  path: ['entities', entityToken, 'uniqueProperty'],
296
- received: uniqueProperty,
297
288
  });
298
289
  }
299
290
  });
@@ -34,6 +34,7 @@ function addKeys(entityManager, entityToken, item, overwrite = false) {
34
34
  if (encoded)
35
35
  Object.assign(newItem, { [property]: encoded });
36
36
  else
37
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
37
38
  delete newItem[property];
38
39
  }
39
40
  }
@@ -24,7 +24,8 @@ function decodeElement(entityManager, element, value) {
24
24
  if (!value)
25
25
  return;
26
26
  const { propertyTranscodes, transcodes } = entityManager.config;
27
- const decoded = transcodes[propertyTranscodes[element]].decode(value);
27
+ const decodeFn = transcodes[propertyTranscodes[element]].decode;
28
+ const decoded = decodeFn(value);
28
29
  entityManager.logger.debug('decoded entity element', {
29
30
  element,
30
31
  value,
@@ -40,7 +40,9 @@ function dehydratePageKeyMap(entityManager, entityToken, pageKeyMap) {
40
40
  }
41
41
  // Extract, sort & validate indexs.
42
42
  const indexes = Object.keys(pageKeyMap).sort();
43
- indexes.map((index) => validateIndexToken.validateIndexToken(entityManager, index));
43
+ indexes.map((index) => {
44
+ validateIndexToken.validateIndexToken(entityManager, index);
45
+ });
44
46
  // Extract & sort hash keys.
45
47
  const hashKeys = Object.keys(pageKeyMap[indexes[0]]);
46
48
  // Dehydrate page keys.
@@ -21,8 +21,8 @@ function encodeElement(entityManager, element, item) {
21
21
  const value = item[element];
22
22
  if (value === undefined || [hashKey, rangeKey].includes(element))
23
23
  return value;
24
- const encoded = transcodes[propertyTranscodes[element]].encode(item[element]) ||
25
- undefined;
24
+ const encodeFn = transcodes[propertyTranscodes[element]].encode;
25
+ const encoded = encodeFn(item[element]) || undefined;
26
26
  entityManager.logger.debug('encoded entity element', {
27
27
  element,
28
28
  item,
@@ -30,7 +30,7 @@ function encodeGeneratedProperty(entityManager, property, item) {
30
30
  ...(sharded
31
31
  ? [item[entityManager.config.hashKey]]
32
32
  : []),
33
- ...elementMap.map(([element, value]) => [element, (value ?? '').toString()].join(entityManager.config.generatedValueDelimiter)),
33
+ ...elementMap.map(([element, value]) => [element, `${value ?? ''}`].join(entityManager.config.generatedValueDelimiter)),
34
34
  ].join(entityManager.config.generatedKeyDelimiter);
35
35
  entityManager.logger.debug('encoded generated property', {
36
36
  property,
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var radash = require('radash');
4
+ var addKeys = require('./addKeys.js');
5
+
6
+ /**
7
+ * Convert an {@link EntityItem | `EntityItem`} into an {@link EntityKey | `EntityKey`}.
8
+ *
9
+ * @param entityManager - {@link EntityManager | `EntityManager`} instance.
10
+ * @param entityToken - {@link Config | `Config`} `entities` key.
11
+ * @param item - {@link EntityItem | `EntityItem`} object.
12
+ * @param overwrite - Overwrite existing properties (default `false`).
13
+ *
14
+ * @returns {@link EntityKey | `EntityKey`} extracted from shallow clone of `item` with updated properties.
15
+ *
16
+ * @throws `Error` if `entityToken` is invalid.
17
+ */
18
+ function getPrimaryKey(entityManager, entityToken, item, overwrite = false) {
19
+ const { hashKey, rangeKey } = entityManager.config;
20
+ return radash.pick(!overwrite && item[hashKey] && item[rangeKey]
21
+ ? item
22
+ : addKeys.addKeys(entityManager, entityToken, item, overwrite), [entityManager.config.hashKey, entityManager.config.rangeKey]);
23
+ }
24
+
25
+ exports.getPrimaryKey = getPrimaryKey;
@@ -47,7 +47,9 @@ function rehydratePageKeyMap(entityManager, entityToken, indexTokens, item, dehy
47
47
  if (hashKeys.length > 1)
48
48
  throw new Error('inconsistent hashKeys');
49
49
  const [hashKeyToken] = hashKeys;
50
- indexTokens.map((index) => validateIndexToken.validateIndexToken(entityManager, index));
50
+ indexTokens.map((index) => {
51
+ validateIndexToken.validateIndexToken(entityManager, index);
52
+ });
51
53
  // Shortcut empty dehydrated.
52
54
  if (dehydrated && !dehydrated.length)
53
55
  return [hashKeyToken, {}];
@@ -17,14 +17,16 @@ function removeKeys(entityManager, entityToken, item) {
17
17
  try {
18
18
  // Validate params.
19
19
  validateEntityToken.validateEntityToken(entityManager, entityToken);
20
- // Delete hash & range keys.
21
- const newItem = { ...item };
22
- delete newItem[entityManager.config.hashKey];
23
- delete newItem[entityManager.config.rangeKey];
24
- // Delete generated properties.
25
- const { sharded, unsharded } = entityManager.config.generatedProperties;
26
- for (const property in { ...sharded, ...unsharded })
27
- delete newItem[property];
20
+ // Build a set of keys to strip (hash, range, and all generated properties).
21
+ const { hashKey, rangeKey, generatedProperties: { sharded, unsharded }, } = entityManager.config;
22
+ const keysToStrip = new Set([
23
+ hashKey,
24
+ rangeKey,
25
+ ...Object.keys(sharded),
26
+ ...Object.keys(unsharded),
27
+ ]);
28
+ // Create a shallow copy of item omitting the keys above (no delete operator).
29
+ const newItem = Object.fromEntries(Object.entries(item).filter(([key]) => !keysToStrip.has(key)));
28
30
  entityManager.logger.debug('stripped entity item generated properties', {
29
31
  entityToken,
30
32
  item,
@@ -42,12 +42,15 @@ function updateItemHashKey(entityManager, entityToken, item, overwrite = false)
42
42
  if (chars) {
43
43
  // Radix is the numerical base of the shardKey.
44
44
  const radix = 2 ** charBits;
45
+ // Compute the full shard space for this bump. Use radix ** chars to ensure
46
+ // all placeholders are utilized (e.g., chars=2, charBits=2 => 16 combos).
47
+ const space = radix ** chars;
45
48
  // Get item unique property & validate.
46
49
  const uniqueId = item[entityManager.config.entities[entityToken]
47
50
  .uniqueProperty];
48
51
  if (entityTools.isNil(uniqueId))
49
52
  throw new Error(`missing item unique property`);
50
- hashKey += (stringHash(uniqueId.toString()) % (chars * radix))
53
+ hashKey += (stringHash(uniqueId) % space)
51
54
  .toString(radix)
52
55
  .padStart(chars, '0');
53
56
  }
package/dist/cjs/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var BaseEntityClient = require('./BaseEntityClient.js');
4
- var BaseQueryBuilder = require('./BaseQueryBuilder.js');
5
- var EntityManager = require('./EntityManager.js');
3
+ var BaseEntityClient = require('./BaseEntityClient/BaseEntityClient.js');
4
+ var BaseQueryBuilder = require('./BaseQueryBuilder/BaseQueryBuilder.js');
5
+ var EntityManager = require('./EntityManager/EntityManager.js');
6
+ var ParsedConfig = require('./EntityManager/ParsedConfig.js');
6
7
 
7
8
 
8
9
 
9
10
  exports.BaseEntityClient = BaseEntityClient.BaseEntityClient;
10
11
  exports.BaseQueryBuilder = BaseQueryBuilder.BaseQueryBuilder;
11
12
  exports.EntityManager = EntityManager.EntityManager;
13
+ exports.configSchema = ParsedConfig.configSchema;