@karmaniverous/entity-manager 6.5.0 → 6.5.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.
@@ -59,7 +59,8 @@ const configSchema = zod.z
59
59
  elementTranscodes: zod.z.record(zod.z.string()).optional().default({}),
60
60
  indexes: zod.z
61
61
  .record(zod.z.object({
62
- components: componentArray,
62
+ hashKey: zod.z.string().min(1),
63
+ rangeKey: zod.z.string().min(1),
63
64
  projections: componentArray.optional(),
64
65
  }))
65
66
  .optional()
@@ -212,9 +213,23 @@ const configSchema = zod.z
212
213
  });
213
214
  // validate indexes.
214
215
  const generatedProperties = Object.keys(entity.generated);
215
- for (const [indexKey, index] of Object.entries(entity.indexes)) {
216
+ for (const [indexKey, { hashKey, rangeKey, projections },] of Object.entries(entity.indexes)) {
217
+ // validate index hash key is sharded
218
+ if (hashKey !== data.hashKey && !entity.generated[hashKey]?.sharded)
219
+ ctx.addIssue({
220
+ code: zod.z.ZodIssueCode.custom,
221
+ message: 'index hash key is not sharded',
222
+ path: ['entities', entityToken, 'indexes', indexKey, 'hashKey'],
223
+ });
224
+ // validate index range key is unsharded
225
+ if (rangeKey !== data.rangeKey && entity.generated[rangeKey]?.sharded)
226
+ ctx.addIssue({
227
+ code: zod.z.ZodIssueCode.custom,
228
+ message: 'index range key is sharded',
229
+ path: ['entities', entityToken, 'indexes', indexKey, 'rangeKey'],
230
+ });
216
231
  // validate all ungenerated entity index components have a corresponding entity element type
217
- for (const component of index.components)
232
+ for (const component of [hashKey, rangeKey])
218
233
  if (![data.hashKey, data.rangeKey, ...generatedProperties].includes(component) &&
219
234
  !typedElements.includes(component))
220
235
  ctx.addIssue({
@@ -230,9 +245,9 @@ const configSchema = zod.z
230
245
  received: component,
231
246
  });
232
247
  // validate no index projections are index components, hashKey, or rangeKey
233
- if (index.projections)
234
- for (const projection of index.projections) {
235
- if ([data.hashKey, data.rangeKey, ...index.components].includes(projection))
248
+ if (projections)
249
+ for (const projection of projections) {
250
+ if ([data.hashKey, data.rangeKey, hashKey, rangeKey].includes(projection))
236
251
  ctx.addIssue({
237
252
  code: zod.z.ZodIssueCode.custom,
238
253
  message: 'index projection is an index component, hash key, or range key',
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var radash = require('radash');
4
+ var validateEntityIndexToken = require('./validateEntityIndexToken.js');
5
+
6
+ /**
7
+ * Get the index components of an entity index. Adds the hash and range keys to the index components.
8
+ *
9
+ * @param entityManager - {@link EntityManager | `EntityManager`} instance.
10
+ * @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
11
+ * @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
12
+ *
13
+ * @returns Array of index components.
14
+ *
15
+ * @throws `Error` if `entityToken` is invalid.
16
+ * @throws `Error` if `indexToken` is invalid.
17
+ */
18
+ function getIndexComponents(entityManager, entityToken, indexToken) {
19
+ validateEntityIndexToken.validateEntityIndexToken(entityManager, entityToken, indexToken);
20
+ const { hashKey, rangeKey, entities } = entityManager.config;
21
+ const { hashKey: indexHashKey, rangeKey: indexRangeKey } = entities[entityToken].indexes[indexToken];
22
+ return radash.unique([hashKey, rangeKey, indexHashKey, indexRangeKey]);
23
+ }
24
+
25
+ exports.getIndexComponents = getIndexComponents;
@@ -3,6 +3,7 @@
3
3
  var radash = require('radash');
4
4
  var encodeGeneratedProperty = require('./encodeGeneratedProperty.js');
5
5
  var getHashKeySpace = require('./getHashKeySpace.js');
6
+ var getIndexComponents = require('./getIndexComponents.js');
6
7
  var rehydrateIndexItem = require('./rehydrateIndexItem.js');
7
8
  var updateItemRangeKey = require('./updateItemRangeKey.js');
8
9
  var validateEntityIndexToken = require('./validateEntityIndexToken.js');
@@ -51,8 +52,7 @@ function rehydratePageKeyMap(entityManager, dehydrated, entityToken, indexTokens
51
52
  ...rehydrateIndexItem.rehydrateIndexItem(entityManager, dehydratedIndexPageKeyMaps[i], entityToken, index, [entityManager.config.hashKey]),
52
53
  };
53
54
  item = updateItemRangeKey.updateItemRangeKey(entityManager, item, entityToken);
54
- return radash.zipToObject(entityManager.config.entities[entityToken].indexes[index]
55
- .components, (component) => entityManager.config.entities[entityToken].generated[component]
55
+ return radash.zipToObject(getIndexComponents.getIndexComponents(entityManager, entityToken, index), (component) => entityManager.config.entities[entityToken].generated[component]
56
56
  ? encodeGeneratedProperty.encodeGeneratedProperty(entityManager, item, entityToken, component)
57
57
  : item[component]);
58
58
  }));
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var radash = require('radash');
4
+ var getIndexComponents = require('./getIndexComponents.js');
4
5
  var validateEntityIndexToken = require('./validateEntityIndexToken.js');
5
6
 
6
7
  /**
@@ -21,7 +22,7 @@ function unwrapIndex(entityManager, entityToken, indexToken) {
21
22
  validateEntityIndexToken.validateEntityIndexToken(entityManager, entityToken, indexToken);
22
23
  const generated = entityManager.config.entities[entityToken].generated;
23
24
  const generatedKeys = Object.keys(radash.shake(generated));
24
- return entityManager.config.entities[entityToken].indexes[indexToken].components
25
+ return getIndexComponents.getIndexComponents(entityManager, entityToken, indexToken)
25
26
  .map((component) => component === entityManager.config.hashKey
26
27
  ? entityManager.config.hashKey
27
28
  : component === entityManager.config.rangeKey
package/dist/index.d.ts CHANGED
@@ -92,7 +92,7 @@ interface ShardBump {
92
92
  * @category Config
93
93
  * @protected
94
94
  */
95
- type ConfigEntityIndexComponents<EntityToken extends keyof Exactify<M>, M extends EntityMap, HashKey extends string, RangeKey extends string, T extends TranscodeMap> = (TranscodableProperties<M[EntityToken], T> | PropertiesOfType<M[EntityToken], never> | HashKey | RangeKey)[];
95
+ type ConfigEntityIndexComponent<EntityToken extends keyof Exactify<M>, M extends EntityMap, HashKey extends string, RangeKey extends string, T extends TranscodeMap> = TranscodableProperties<M[EntityToken], T> | PropertiesOfType<M[EntityToken], never> | HashKey | RangeKey;
96
96
  /**
97
97
  * Returns a Config entity type.
98
98
  *
@@ -184,12 +184,13 @@ type ConfigEntity<EntityToken extends keyof Exactify<M>, M extends EntityMap, Ha
184
184
  /**
185
185
  * Indexes defined for the {@link Entity | `Entity`}. Should reflect the underlying database table indexes.
186
186
  *
187
- * Each key is the name of an index, and each value is a non-empty array of {@link Entity | `Entity`} property names that define the index.
187
+ * Each key is the name of an index, and each value defines the hash key, range key, and projected properties of the index.
188
188
  *
189
- * Related property types must be align with the {@link Config | `Config`} `T` type parameter. Note tha all {@link ConfigEntityGenerated | generated property} types are transcodable by definition.
189
+ * hashKey and rangeKey types must align with the {@link Config | `Config`} `T` type parameter. Note that all {@link ConfigEntityGenerated | generated property} types are transcodable by definition.
190
190
  */
191
191
  indexes?: Record<string, {
192
- components: ConfigEntityIndexComponents<EntityToken, M, HashKey, RangeKey, T>;
192
+ hashKey: ConfigEntityIndexComponent<EntityToken, M, HashKey, RangeKey, T>;
193
+ rangeKey: ConfigEntityIndexComponent<EntityToken, M, HashKey, RangeKey, T>;
193
194
  projections?: (keyof M[EntityToken])[];
194
195
  }>;
195
196
  /**
@@ -394,13 +395,16 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
394
395
  }>>>>>;
395
396
  elementTranscodes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
396
397
  indexes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
397
- components: z.ZodEffects<z.ZodArray<z.ZodString, "atleastone">, [string, ...string[]], [string, ...string[]]>;
398
+ hashKey: z.ZodString;
399
+ rangeKey: z.ZodString;
398
400
  projections: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodString, "atleastone">, [string, ...string[]], [string, ...string[]]>>;
399
401
  }, "strip", z.ZodTypeAny, {
400
- components: [string, ...string[]];
402
+ hashKey: string;
403
+ rangeKey: string;
401
404
  projections?: [string, ...string[]] | undefined;
402
405
  }, {
403
- components: [string, ...string[]];
406
+ hashKey: string;
407
+ rangeKey: string;
404
408
  projections?: [string, ...string[]] | undefined;
405
409
  }>>>>;
406
410
  shardBumps: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -447,7 +451,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
447
451
  defaultPageSize: number;
448
452
  elementTranscodes: Record<string, string>;
449
453
  indexes: Record<string, {
450
- components: [string, ...string[]];
454
+ hashKey: string;
455
+ rangeKey: string;
451
456
  projections?: [string, ...string[]] | undefined;
452
457
  }>;
453
458
  shardBumps: {
@@ -469,7 +474,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
469
474
  defaultPageSize?: number | undefined;
470
475
  elementTranscodes?: Record<string, string> | undefined;
471
476
  indexes?: Record<string, {
472
- components: [string, ...string[]];
477
+ hashKey: string;
478
+ rangeKey: string;
473
479
  projections?: [string, ...string[]] | undefined;
474
480
  }> | undefined;
475
481
  shardBumps?: {
@@ -487,7 +493,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
487
493
  defaultPageSize: number;
488
494
  elementTranscodes: Record<string, string>;
489
495
  indexes: Record<string, {
490
- components: [string, ...string[]];
496
+ hashKey: string;
497
+ rangeKey: string;
491
498
  projections?: [string, ...string[]] | undefined;
492
499
  }>;
493
500
  shardBumps: {
@@ -509,7 +516,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
509
516
  defaultPageSize?: number | undefined;
510
517
  elementTranscodes?: Record<string, string> | undefined;
511
518
  indexes?: Record<string, {
512
- components: [string, ...string[]];
519
+ hashKey: string;
520
+ rangeKey: string;
513
521
  projections?: [string, ...string[]] | undefined;
514
522
  }> | undefined;
515
523
  shardBumps?: {
@@ -547,7 +555,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
547
555
  defaultPageSize: number;
548
556
  elementTranscodes: Record<string, string>;
549
557
  indexes: Record<string, {
550
- components: [string, ...string[]];
558
+ hashKey: string;
559
+ rangeKey: string;
551
560
  projections?: [string, ...string[]] | undefined;
552
561
  }>;
553
562
  shardBumps: {
@@ -581,7 +590,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
581
590
  defaultPageSize?: number | undefined;
582
591
  elementTranscodes?: Record<string, string> | undefined;
583
592
  indexes?: Record<string, {
584
- components: [string, ...string[]];
593
+ hashKey: string;
594
+ rangeKey: string;
585
595
  projections?: [string, ...string[]] | undefined;
586
596
  }> | undefined;
587
597
  shardBumps?: {
@@ -611,7 +621,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
611
621
  defaultPageSize: number;
612
622
  elementTranscodes: Record<string, string>;
613
623
  indexes: Record<string, {
614
- components: [string, ...string[]];
624
+ hashKey: string;
625
+ rangeKey: string;
615
626
  projections?: [string, ...string[]] | undefined;
616
627
  }>;
617
628
  shardBumps: {
@@ -645,7 +656,8 @@ declare const configSchema: z.ZodEffects<z.ZodObject<{
645
656
  defaultPageSize?: number | undefined;
646
657
  elementTranscodes?: Record<string, string> | undefined;
647
658
  indexes?: Record<string, {
648
- components: [string, ...string[]];
659
+ hashKey: string;
660
+ rangeKey: string;
649
661
  projections?: [string, ...string[]] | undefined;
650
662
  }> | undefined;
651
663
  shardBumps?: {
@@ -877,4 +889,4 @@ declare class EntityManager<M extends EntityMap, HashKey extends string, RangeKe
877
889
  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>>;
878
890
  }
879
891
 
880
- export { type Config, type ConfigEntities, type ConfigEntity, type ConfigEntityGenerated, type ConfigEntityIndexComponents, type ConfigKeys, type ConfigTranscodes, EntityManager, type EntityMap, type ExclusiveKey, type ItemMap, type ParsedConfig, type QueryOptions, type QueryResult, type ShardBump, type ShardQueryFunction, type ShardQueryMap, type ShardQueryResult, type Unwrap, conditionalize };
892
+ export { type Config, type ConfigEntities, type ConfigEntity, type ConfigEntityGenerated, type ConfigEntityIndexComponent, type ConfigKeys, type ConfigTranscodes, EntityManager, type EntityMap, type ExclusiveKey, type ItemMap, type ParsedConfig, type QueryOptions, type QueryResult, type ShardBump, type ShardQueryFunction, type ShardQueryMap, type ShardQueryResult, type Unwrap, conditionalize };
@@ -57,7 +57,8 @@ const configSchema = z
57
57
  elementTranscodes: z.record(z.string()).optional().default({}),
58
58
  indexes: z
59
59
  .record(z.object({
60
- components: componentArray,
60
+ hashKey: z.string().min(1),
61
+ rangeKey: z.string().min(1),
61
62
  projections: componentArray.optional(),
62
63
  }))
63
64
  .optional()
@@ -210,9 +211,23 @@ const configSchema = z
210
211
  });
211
212
  // validate indexes.
212
213
  const generatedProperties = Object.keys(entity.generated);
213
- for (const [indexKey, index] of Object.entries(entity.indexes)) {
214
+ for (const [indexKey, { hashKey, rangeKey, projections },] of Object.entries(entity.indexes)) {
215
+ // validate index hash key is sharded
216
+ if (hashKey !== data.hashKey && !entity.generated[hashKey]?.sharded)
217
+ ctx.addIssue({
218
+ code: z.ZodIssueCode.custom,
219
+ message: 'index hash key is not sharded',
220
+ path: ['entities', entityToken, 'indexes', indexKey, 'hashKey'],
221
+ });
222
+ // validate index range key is unsharded
223
+ if (rangeKey !== data.rangeKey && entity.generated[rangeKey]?.sharded)
224
+ ctx.addIssue({
225
+ code: z.ZodIssueCode.custom,
226
+ message: 'index range key is sharded',
227
+ path: ['entities', entityToken, 'indexes', indexKey, 'rangeKey'],
228
+ });
214
229
  // validate all ungenerated entity index components have a corresponding entity element type
215
- for (const component of index.components)
230
+ for (const component of [hashKey, rangeKey])
216
231
  if (![data.hashKey, data.rangeKey, ...generatedProperties].includes(component) &&
217
232
  !typedElements.includes(component))
218
233
  ctx.addIssue({
@@ -228,9 +243,9 @@ const configSchema = z
228
243
  received: component,
229
244
  });
230
245
  // validate no index projections are index components, hashKey, or rangeKey
231
- if (index.projections)
232
- for (const projection of index.projections) {
233
- if ([data.hashKey, data.rangeKey, ...index.components].includes(projection))
246
+ if (projections)
247
+ for (const projection of projections) {
248
+ if ([data.hashKey, data.rangeKey, hashKey, rangeKey].includes(projection))
234
249
  ctx.addIssue({
235
250
  code: z.ZodIssueCode.custom,
236
251
  message: 'index projection is an index component, hash key, or range key',
@@ -0,0 +1,23 @@
1
+ import { unique } from 'radash';
2
+ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
3
+
4
+ /**
5
+ * Get the index components of an entity index. Adds the hash and range keys to the index components.
6
+ *
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.
10
+ *
11
+ * @returns Array of index components.
12
+ *
13
+ * @throws `Error` if `entityToken` is invalid.
14
+ * @throws `Error` if `indexToken` is invalid.
15
+ */
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];
20
+ return unique([hashKey, rangeKey, indexHashKey, indexRangeKey]);
21
+ }
22
+
23
+ export { getIndexComponents };
@@ -1,6 +1,7 @@
1
1
  import { range, mapValues, zipToObject, cluster } from 'radash';
2
2
  import { encodeGeneratedProperty } from './encodeGeneratedProperty.js';
3
3
  import { getHashKeySpace } from './getHashKeySpace.js';
4
+ import { getIndexComponents } from './getIndexComponents.js';
4
5
  import { rehydrateIndexItem } from './rehydrateIndexItem.js';
5
6
  import { updateItemRangeKey } from './updateItemRangeKey.js';
6
7
  import { validateEntityIndexToken } from './validateEntityIndexToken.js';
@@ -49,8 +50,7 @@ function rehydratePageKeyMap(entityManager, dehydrated, entityToken, indexTokens
49
50
  ...rehydrateIndexItem(entityManager, dehydratedIndexPageKeyMaps[i], entityToken, index, [entityManager.config.hashKey]),
50
51
  };
51
52
  item = updateItemRangeKey(entityManager, item, entityToken);
52
- return zipToObject(entityManager.config.entities[entityToken].indexes[index]
53
- .components, (component) => entityManager.config.entities[entityToken].generated[component]
53
+ return zipToObject(getIndexComponents(entityManager, entityToken, index), (component) => entityManager.config.entities[entityToken].generated[component]
54
54
  ? encodeGeneratedProperty(entityManager, item, entityToken, component)
55
55
  : item[component]);
56
56
  }));
@@ -1,4 +1,5 @@
1
1
  import { shake } from 'radash';
2
+ import { getIndexComponents } from './getIndexComponents.js';
2
3
  import { validateEntityIndexToken } from './validateEntityIndexToken.js';
3
4
 
4
5
  /**
@@ -19,7 +20,7 @@ function unwrapIndex(entityManager, entityToken, indexToken) {
19
20
  validateEntityIndexToken(entityManager, entityToken, indexToken);
20
21
  const generated = entityManager.config.entities[entityToken].generated;
21
22
  const generatedKeys = Object.keys(shake(generated));
22
- return entityManager.config.entities[entityToken].indexes[indexToken].components
23
+ return getIndexComponents(entityManager, entityToken, indexToken)
23
24
  .map((component) => component === entityManager.config.hashKey
24
25
  ? entityManager.config.hashKey
25
26
  : component === entityManager.config.rangeKey
package/package.json CHANGED
@@ -132,5 +132,5 @@
132
132
  },
133
133
  "type": "module",
134
134
  "types": "dist/index.d.ts",
135
- "version": "6.5.0"
135
+ "version": "6.5.1"
136
136
  }