@karmaniverous/entity-manager 6.5.0 → 6.6.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.
- package/dist/cjs/EntityManager.js +6 -6
- package/dist/cjs/ParsedConfig.js +21 -6
- package/dist/cjs/addKeys.js +5 -5
- package/dist/cjs/decodeEntityElement.js +4 -4
- package/dist/cjs/decodeGeneratedProperty.js +5 -5
- package/dist/cjs/dehydrateIndexItem.js +3 -3
- package/dist/cjs/dehydratePageKeyMap.js +6 -6
- package/dist/cjs/encodeEntityElement.js +4 -4
- package/dist/cjs/encodeGeneratedProperty.js +4 -4
- package/dist/cjs/getIndexComponents.js +25 -0
- package/dist/cjs/query.js +3 -3
- package/dist/cjs/rehydrateIndexItem.js +5 -5
- package/dist/cjs/rehydratePageKeyMap.js +9 -9
- package/dist/cjs/removeKeys.js +4 -4
- package/dist/cjs/unwrapIndex.js +2 -1
- package/dist/cjs/updateItemHashKey.js +3 -3
- package/dist/cjs/updateItemRangeKey.js +4 -4
- package/dist/index.d.ts +33 -21
- package/dist/mjs/EntityManager.js +6 -6
- package/dist/mjs/ParsedConfig.js +21 -6
- package/dist/mjs/addKeys.js +5 -5
- package/dist/mjs/decodeEntityElement.js +4 -4
- package/dist/mjs/decodeGeneratedProperty.js +5 -5
- package/dist/mjs/dehydrateIndexItem.js +3 -3
- package/dist/mjs/dehydratePageKeyMap.js +6 -6
- package/dist/mjs/encodeEntityElement.js +4 -4
- package/dist/mjs/encodeGeneratedProperty.js +4 -4
- package/dist/mjs/getIndexComponents.js +23 -0
- package/dist/mjs/query.js +3 -3
- package/dist/mjs/rehydrateIndexItem.js +5 -5
- package/dist/mjs/rehydratePageKeyMap.js +9 -9
- package/dist/mjs/removeKeys.js +4 -4
- package/dist/mjs/unwrapIndex.js +2 -1
- package/dist/mjs/updateItemHashKey.js +3 -3
- package/dist/mjs/updateItemRangeKey.js +4 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -81,7 +81,7 @@ interface ShardBump {
|
|
|
81
81
|
chars: number;
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
|
-
* Returns a Config entity index
|
|
84
|
+
* Returns a Config entity index component type.
|
|
85
85
|
*
|
|
86
86
|
* @typeParam EntityToken - The {@link Entity | `Entity`} token.
|
|
87
87
|
* @typeParam M - The {@link EntityMap | `EntityMap`}.
|
|
@@ -92,7 +92,7 @@ interface ShardBump {
|
|
|
92
92
|
* @category Config
|
|
93
93
|
* @protected
|
|
94
94
|
*/
|
|
95
|
-
type
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
402
|
+
hashKey: string;
|
|
403
|
+
rangeKey: string;
|
|
401
404
|
projections?: [string, ...string[]] | undefined;
|
|
402
405
|
}, {
|
|
403
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
659
|
+
hashKey: string;
|
|
660
|
+
rangeKey: string;
|
|
649
661
|
projections?: [string, ...string[]] | undefined;
|
|
650
662
|
}> | undefined;
|
|
651
663
|
shardBumps?: {
|
|
@@ -836,26 +848,26 @@ declare class EntityManager<M extends EntityMap, HashKey extends string, RangeKe
|
|
|
836
848
|
/**
|
|
837
849
|
* Update generated properties, hash key, and range key on an {@link ItemMap | `ItemMap`} object.
|
|
838
850
|
*
|
|
839
|
-
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
840
851
|
* @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
|
|
852
|
+
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
841
853
|
* @param overwrite - Overwrite existing properties (default `false`).
|
|
842
854
|
*
|
|
843
855
|
* @returns Shallow clone of `item` with updated properties.
|
|
844
856
|
*
|
|
845
857
|
* @throws `Error` if `entityToken` is invalid.
|
|
846
858
|
*/
|
|
847
|
-
addKeys<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(item: Partial<Item>,
|
|
859
|
+
addKeys<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(entityToken: EntityToken, item: Partial<Item>, overwrite?: boolean): Partial<Item>;
|
|
848
860
|
/**
|
|
849
861
|
* Strips generated properties, hash key, and range key from an {@link ItemMap | `ItemMap`} object.
|
|
850
862
|
*
|
|
851
|
-
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
852
863
|
* @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
|
|
864
|
+
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
853
865
|
*
|
|
854
866
|
* @returns Shallow clone of `item` without generated properties, hash key or range key.
|
|
855
867
|
*
|
|
856
868
|
* @throws `Error` if `entityToken` is invalid.
|
|
857
869
|
*/
|
|
858
|
-
removeKeys<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(item: Partial<Item
|
|
870
|
+
removeKeys<Item extends ItemMap<M, HashKey, RangeKey>[EntityToken], EntityToken extends keyof Exactify<M> & string>(entityToken: EntityToken, item: Partial<Item>): Partial<Item>;
|
|
859
871
|
/**
|
|
860
872
|
* Query a database entity across shards in a provider-generic fashion.
|
|
861
873
|
*
|
|
@@ -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
|
|
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 };
|
|
@@ -42,29 +42,29 @@ class EntityManager {
|
|
|
42
42
|
/**
|
|
43
43
|
* Update generated properties, hash key, and range key on an {@link ItemMap | `ItemMap`} object.
|
|
44
44
|
*
|
|
45
|
-
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
46
45
|
* @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
|
|
46
|
+
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
47
47
|
* @param overwrite - Overwrite existing properties (default `false`).
|
|
48
48
|
*
|
|
49
49
|
* @returns Shallow clone of `item` with updated properties.
|
|
50
50
|
*
|
|
51
51
|
* @throws `Error` if `entityToken` is invalid.
|
|
52
52
|
*/
|
|
53
|
-
addKeys(
|
|
54
|
-
return addKeys(this,
|
|
53
|
+
addKeys(entityToken, item, overwrite = false) {
|
|
54
|
+
return addKeys(this, entityToken, item, overwrite);
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Strips generated properties, hash key, and range key from an {@link ItemMap | `ItemMap`} object.
|
|
58
58
|
*
|
|
59
|
-
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
60
59
|
* @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
|
|
60
|
+
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
61
61
|
*
|
|
62
62
|
* @returns Shallow clone of `item` without generated properties, hash key or range key.
|
|
63
63
|
*
|
|
64
64
|
* @throws `Error` if `entityToken` is invalid.
|
|
65
65
|
*/
|
|
66
|
-
removeKeys(
|
|
67
|
-
return removeKeys(this,
|
|
66
|
+
removeKeys(entityToken, item) {
|
|
67
|
+
return removeKeys(this, entityToken, item);
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Query a database entity across shards in a provider-generic fashion.
|
package/dist/mjs/ParsedConfig.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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
|
|
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 (
|
|
232
|
-
for (const projection of
|
|
233
|
-
if ([data.hashKey, data.rangeKey,
|
|
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',
|
package/dist/mjs/addKeys.js
CHANGED
|
@@ -8,27 +8,27 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
8
8
|
* Update generated properties, hash key, and range key on an {@link ItemMap | `ItemMap`} object.
|
|
9
9
|
*
|
|
10
10
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
11
|
-
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
12
11
|
* @param entityToken - {@link ConfigKeys.entities | `this.config.entities`} key.
|
|
12
|
+
* @param item - {@link ItemMap | `ItemMap`} object.
|
|
13
13
|
* @param overwrite - Overwrite existing properties (default `false`).
|
|
14
14
|
*
|
|
15
15
|
* @returns Shallow clone of `item` with updated properties.
|
|
16
16
|
*
|
|
17
17
|
* @throws `Error` if `entityToken` is invalid.
|
|
18
18
|
*/
|
|
19
|
-
function addKeys(entityManager,
|
|
19
|
+
function addKeys(entityManager, entityToken, item, overwrite = false) {
|
|
20
20
|
try {
|
|
21
21
|
// Validate params.
|
|
22
22
|
validateEntityToken(entityManager, entityToken);
|
|
23
23
|
// Update hash key.
|
|
24
|
-
let newItem = updateItemHashKey(entityManager,
|
|
24
|
+
let newItem = updateItemHashKey(entityManager, entityToken, item, overwrite);
|
|
25
25
|
// Update range key.
|
|
26
|
-
newItem = updateItemRangeKey(entityManager,
|
|
26
|
+
newItem = updateItemRangeKey(entityManager, entityToken, newItem, overwrite);
|
|
27
27
|
// Update generated properties.
|
|
28
28
|
for (const property in entityManager.config.entities[entityToken]
|
|
29
29
|
.generated) {
|
|
30
30
|
if (overwrite || isNil(item[property])) {
|
|
31
|
-
const encoded = encodeGeneratedProperty(entityManager,
|
|
31
|
+
const encoded = encodeGeneratedProperty(entityManager, entityToken, property, newItem);
|
|
32
32
|
if (encoded)
|
|
33
33
|
Object.assign(newItem, { [property]: encoded });
|
|
34
34
|
else
|
|
@@ -8,15 +8,15 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
8
8
|
* If `element` is the {@link Config.hashKey | `hashKey`} or {@link Config.rangeKey | `rangeKey`}, returns the value as-is.
|
|
9
9
|
*
|
|
10
10
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
11
|
-
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
12
11
|
* @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
|
|
13
12
|
* @param element - The {@link Entity | `Entity`} generated property element or ungenerated index component to encode.
|
|
13
|
+
* @param value - Encoded entity element.
|
|
14
14
|
*
|
|
15
15
|
* @returns Decoded value.
|
|
16
16
|
*
|
|
17
17
|
* @throws `Error` if `entityToken` is invalid.
|
|
18
18
|
*/
|
|
19
|
-
function decodeEntityElement(entityManager,
|
|
19
|
+
function decodeEntityElement(entityManager, entityToken, element, value) {
|
|
20
20
|
try {
|
|
21
21
|
validateEntityToken(entityManager, entityToken);
|
|
22
22
|
const { entities, hashKey, rangeKey, transcodes } = entityManager.config;
|
|
@@ -26,9 +26,9 @@ function decodeEntityElement(entityManager, value, entityToken, element) {
|
|
|
26
26
|
return value;
|
|
27
27
|
const decoded = transcodes[entities[entityToken].elementTranscodes[element]].decode(value);
|
|
28
28
|
entityManager.logger.debug('decoded entity element', {
|
|
29
|
-
value,
|
|
30
29
|
entityToken,
|
|
31
30
|
element,
|
|
31
|
+
value,
|
|
32
32
|
decoded,
|
|
33
33
|
});
|
|
34
34
|
return decoded;
|
|
@@ -36,9 +36,9 @@ function decodeEntityElement(entityManager, value, entityToken, element) {
|
|
|
36
36
|
catch (error) {
|
|
37
37
|
if (error instanceof Error)
|
|
38
38
|
entityManager.logger.error(error.message, {
|
|
39
|
-
value,
|
|
40
39
|
entityToken,
|
|
41
40
|
element,
|
|
41
|
+
value,
|
|
42
42
|
});
|
|
43
43
|
throw error;
|
|
44
44
|
}
|
|
@@ -6,14 +6,14 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
6
6
|
* Decode a generated property value. Returns a partial ItemMap.
|
|
7
7
|
*
|
|
8
8
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
9
|
-
* @param encoded - Encoded generated property value.
|
|
10
9
|
* @param entityToken - `entityManager.config.entities` key.
|
|
10
|
+
* @param encoded - Encoded generated property value.
|
|
11
11
|
*
|
|
12
12
|
* @returns Partial {@link ItemMap | `ItemMap`} object with updated properties decoded from `encoded`.
|
|
13
13
|
*
|
|
14
14
|
* @throws `Error` if `entityToken` is invalid.
|
|
15
15
|
*/
|
|
16
|
-
function decodeGeneratedProperty(entityManager,
|
|
16
|
+
function decodeGeneratedProperty(entityManager, entityToken, encoded) {
|
|
17
17
|
try {
|
|
18
18
|
const { generatedKeyDelimiter, generatedValueDelimiter, hashKey, shardKeyDelimiter, } = entityManager.config;
|
|
19
19
|
// Validate params.
|
|
@@ -35,17 +35,17 @@ function decodeGeneratedProperty(entityManager, encoded, entityToken) {
|
|
|
35
35
|
return pair;
|
|
36
36
|
});
|
|
37
37
|
// Assign decoded properties.
|
|
38
|
-
Object.assign(decoded, objectify(values, ([key]) => key, ([key, value]) => decodeEntityElement(entityManager,
|
|
38
|
+
Object.assign(decoded, objectify(values, ([key]) => key, ([key, value]) => decodeEntityElement(entityManager, entityToken, key, value)));
|
|
39
39
|
entityManager.logger.debug('decoded generated property', {
|
|
40
|
-
encoded,
|
|
41
40
|
entityToken,
|
|
41
|
+
encoded,
|
|
42
42
|
decoded,
|
|
43
43
|
});
|
|
44
44
|
return decoded;
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
47
|
if (error instanceof Error)
|
|
48
|
-
entityManager.logger.error(error.message, {
|
|
48
|
+
entityManager.logger.error(error.message, { entityToken, encoded });
|
|
49
49
|
throw error;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -16,9 +16,9 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
|
|
|
16
16
|
* `item` must be populated with all required index component elements!
|
|
17
17
|
*
|
|
18
18
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
19
|
-
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
20
19
|
* @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
|
|
21
20
|
* @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
|
|
21
|
+
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
22
22
|
* @param omit - Array of index components to omit from the output value.
|
|
23
23
|
*
|
|
24
24
|
* @returns Dehydrated index value.
|
|
@@ -26,7 +26,7 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
|
|
|
26
26
|
* @throws `Error` if `entityToken` is invalid.
|
|
27
27
|
* @throws `Error` if `indexToken` is invalid.
|
|
28
28
|
*/
|
|
29
|
-
function dehydrateIndexItem(entityManager,
|
|
29
|
+
function dehydrateIndexItem(entityManager, entityToken, indexToken, item, omit = []) {
|
|
30
30
|
try {
|
|
31
31
|
const { generatedKeyDelimiter } = entityManager.config;
|
|
32
32
|
// Validate params.
|
|
@@ -38,7 +38,7 @@ function dehydrateIndexItem(entityManager, item, entityToken, indexToken, omit =
|
|
|
38
38
|
const elements = unwrapIndex(entityManager, entityToken, indexToken).filter((element) => !omit.includes(element));
|
|
39
39
|
// Join index element values.
|
|
40
40
|
const dehydrated = elements
|
|
41
|
-
.map((element) => encodeEntityElement(entityManager,
|
|
41
|
+
.map((element) => encodeEntityElement(entityManager, entityToken, element, item))
|
|
42
42
|
.join(generatedKeyDelimiter);
|
|
43
43
|
entityManager.logger.debug('dehydrated index', {
|
|
44
44
|
item,
|
|
@@ -9,8 +9,8 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
9
9
|
* Reverses {@link EntityManager.rehydratePageKeyMap | `rehydratePageKeyMap`}.
|
|
10
10
|
*
|
|
11
11
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
12
|
-
* @param pageKeyMap - {@link PageKeyMap | `PageKeyMap`} object to dehydrate.
|
|
13
12
|
* @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
|
|
13
|
+
* @param pageKeyMap - {@link PageKeyMap | `PageKeyMap`} object to dehydrate.
|
|
14
14
|
*
|
|
15
15
|
* @returns Array of dehydrated page keys.
|
|
16
16
|
*
|
|
@@ -22,7 +22,7 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
22
22
|
*
|
|
23
23
|
* An empty returned array indicates all page keys are `undefined`.
|
|
24
24
|
*/
|
|
25
|
-
function dehydratePageKeyMap(entityManager,
|
|
25
|
+
function dehydratePageKeyMap(entityManager, entityToken, pageKeyMap) {
|
|
26
26
|
try {
|
|
27
27
|
// Validate params.
|
|
28
28
|
validateEntityToken(entityManager, entityToken);
|
|
@@ -30,8 +30,8 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
|
|
|
30
30
|
if (!Object.keys(pageKeyMap).length) {
|
|
31
31
|
const dehydrated = [];
|
|
32
32
|
entityManager.logger.debug('dehydrated empty page key map', {
|
|
33
|
-
pageKeyMap,
|
|
34
33
|
entityToken,
|
|
34
|
+
pageKeyMap,
|
|
35
35
|
dehydrated,
|
|
36
36
|
});
|
|
37
37
|
return dehydrated;
|
|
@@ -54,13 +54,13 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
|
|
|
54
54
|
const item = Object.entries(pageKeyMap[index][hashKey]).reduce((item, [property, value]) => {
|
|
55
55
|
if (property in entityManager.config.entities[entityToken].generated ||
|
|
56
56
|
property === entityManager.config.rangeKey)
|
|
57
|
-
Object.assign(item, decodeGeneratedProperty(entityManager,
|
|
57
|
+
Object.assign(item, decodeGeneratedProperty(entityManager, entityToken, value));
|
|
58
58
|
else
|
|
59
59
|
Object.assign(item, { [property]: value });
|
|
60
60
|
return item;
|
|
61
61
|
}, {});
|
|
62
62
|
// Dehydrate index from item.
|
|
63
|
-
dehydrated.push(dehydrateIndexItem(entityManager,
|
|
63
|
+
dehydrated.push(dehydrateIndexItem(entityManager, entityToken, index, item, [
|
|
64
64
|
entityManager.config.hashKey,
|
|
65
65
|
]));
|
|
66
66
|
}
|
|
@@ -69,8 +69,8 @@ function dehydratePageKeyMap(entityManager, pageKeyMap, entityToken) {
|
|
|
69
69
|
if (dehydrated.every((pageKey) => pageKey === ''))
|
|
70
70
|
dehydrated = [];
|
|
71
71
|
entityManager.logger.debug('dehydrated page key map', {
|
|
72
|
-
pageKeyMap,
|
|
73
72
|
entityToken,
|
|
73
|
+
pageKeyMap,
|
|
74
74
|
indexes,
|
|
75
75
|
hashKeys,
|
|
76
76
|
dehydrated,
|
|
@@ -8,15 +8,15 @@ import { validateEntityToken } from './validateEntityToken.js';
|
|
|
8
8
|
* If `element` is the {@link Config.hashKey | `hashKey`} or {@link Config.rangeKey | `rangeKey`}, returns the value as-is.
|
|
9
9
|
*
|
|
10
10
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
11
|
-
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
12
11
|
* @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
|
|
13
12
|
* @param element - The {@link Entity | `Entity`} generated property element or ungenerated index component to encode.
|
|
13
|
+
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
14
14
|
*
|
|
15
15
|
* @returns Encoded value.
|
|
16
16
|
*
|
|
17
17
|
* @throws `Error` if `entityToken` is invalid.
|
|
18
18
|
*/
|
|
19
|
-
function encodeEntityElement(entityManager,
|
|
19
|
+
function encodeEntityElement(entityManager, entityToken, element, item) {
|
|
20
20
|
try {
|
|
21
21
|
validateEntityToken(entityManager, entityToken);
|
|
22
22
|
const { entities, hashKey, rangeKey, transcodes } = entityManager.config;
|
|
@@ -25,16 +25,16 @@ function encodeEntityElement(entityManager, item, entityToken, element) {
|
|
|
25
25
|
return value;
|
|
26
26
|
const encoded = transcodes[entities[entityToken].elementTranscodes[element]].encode(item[element]) || undefined;
|
|
27
27
|
entityManager.logger.debug('encoded entity element', {
|
|
28
|
-
item,
|
|
29
28
|
entityToken,
|
|
30
29
|
element,
|
|
30
|
+
item,
|
|
31
31
|
encoded,
|
|
32
32
|
});
|
|
33
33
|
return encoded;
|
|
34
34
|
}
|
|
35
35
|
catch (error) {
|
|
36
36
|
if (error instanceof Error)
|
|
37
|
-
entityManager.logger.error(error.message, {
|
|
37
|
+
entityManager.logger.error(error.message, { entityToken, element, item });
|
|
38
38
|
throw error;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -5,16 +5,16 @@ import { validateEntityGeneratedProperty } from './validateEntityGeneratedProper
|
|
|
5
5
|
* Encode a generated property value. Returns a string or undefined if atomicity requirement not met.
|
|
6
6
|
*
|
|
7
7
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
8
|
-
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
9
8
|
* @param entityToken - `entityManager.config.entities` key.
|
|
10
9
|
* @param property - {@link ConfigEntityGenerated | `entityManager.config.entities.<entityToken>.generated`} key.
|
|
10
|
+
* @param item - Partial {@link ItemMap | `ItemMap`} object.
|
|
11
11
|
*
|
|
12
12
|
* @returns Encoded generated property value.
|
|
13
13
|
*
|
|
14
14
|
* @throws `Error` if `entityToken` is invalid.
|
|
15
15
|
* @throws `Error` if `property` is invalid.
|
|
16
16
|
*/
|
|
17
|
-
function encodeGeneratedProperty(entityManager,
|
|
17
|
+
function encodeGeneratedProperty(entityManager, entityToken, property, item) {
|
|
18
18
|
try {
|
|
19
19
|
// Validate params.
|
|
20
20
|
validateEntityGeneratedProperty(entityManager, entityToken, property);
|
|
@@ -33,9 +33,9 @@ function encodeGeneratedProperty(entityManager, item, entityToken, property) {
|
|
|
33
33
|
...elementMap.map(([element, value]) => [element, (value ?? '').toString()].join(entityManager.config.generatedValueDelimiter)),
|
|
34
34
|
].join(entityManager.config.generatedKeyDelimiter);
|
|
35
35
|
entityManager.logger.debug('encoded generated property', {
|
|
36
|
-
item,
|
|
37
36
|
entityToken,
|
|
38
37
|
property,
|
|
38
|
+
item,
|
|
39
39
|
encoded,
|
|
40
40
|
});
|
|
41
41
|
return encoded;
|
|
@@ -43,9 +43,9 @@ function encodeGeneratedProperty(entityManager, item, entityToken, property) {
|
|
|
43
43
|
catch (error) {
|
|
44
44
|
if (error instanceof Error)
|
|
45
45
|
entityManager.logger.error(error.message, {
|
|
46
|
-
item,
|
|
47
46
|
entityToken,
|
|
48
47
|
property,
|
|
48
|
+
item,
|
|
49
49
|
});
|
|
50
50
|
throw error;
|
|
51
51
|
}
|
|
@@ -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 };
|
package/dist/mjs/query.js
CHANGED
|
@@ -38,9 +38,9 @@ async function query(entityManager, { entityToken, hashKey, limit, pageKeyMap, p
|
|
|
38
38
|
if (!(isInt(pageSize) && pageSize >= 1))
|
|
39
39
|
throw new Error('pageSize must be a positive integer');
|
|
40
40
|
// Rehydrate pageKeyMap.
|
|
41
|
-
const rehydratedPageKeyMap = rehydratePageKeyMap(entityManager, pageKeyMap
|
|
41
|
+
const rehydratedPageKeyMap = rehydratePageKeyMap(entityManager, entityToken, Object.keys(shardQueryMap), pageKeyMap
|
|
42
42
|
? JSON.parse(decompressFromEncodedURIComponent(pageKeyMap))
|
|
43
|
-
: undefined,
|
|
43
|
+
: undefined, timestampFrom, timestampTo);
|
|
44
44
|
// Shortcut if pageKeyMap is empty.
|
|
45
45
|
if (!Object.keys(rehydratedPageKeyMap).length)
|
|
46
46
|
return {
|
|
@@ -88,7 +88,7 @@ async function query(entityManager, { entityToken, hashKey, limit, pageKeyMap, p
|
|
|
88
88
|
const result = {
|
|
89
89
|
count: workingResult.items.length,
|
|
90
90
|
items: workingResult.items,
|
|
91
|
-
pageKeyMap: compressToEncodedURIComponent(JSON.stringify(dehydratePageKeyMap(entityManager, workingResult.pageKeyMap
|
|
91
|
+
pageKeyMap: compressToEncodedURIComponent(JSON.stringify(dehydratePageKeyMap(entityManager, entityToken, workingResult.pageKeyMap))),
|
|
92
92
|
};
|
|
93
93
|
entityManager.logger.debug('queried entityToken across shards', {
|
|
94
94
|
entityToken,
|
|
@@ -12,9 +12,9 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
|
|
|
12
12
|
* {@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
13
|
*
|
|
14
14
|
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
15
|
-
* @param dehydrated - Dehydrated index value.
|
|
16
15
|
* @param entityToken - {@link ConfigKeys.entities | `entityManager.config.entities`} key.
|
|
17
16
|
* @param indexToken - {@link ConfigEntity.indexes | `entityManager.config.entities.<entityToken>.indexes`} key.
|
|
17
|
+
* @param dehydrated - Dehydrated index value.
|
|
18
18
|
* @param omit - Array of index components omitted from `dehydrated`.
|
|
19
19
|
*
|
|
20
20
|
* @returns Partial {@link ItemMap | `ItemMap`} object containing rehydrated index component elements.
|
|
@@ -22,7 +22,7 @@ import { validateEntityIndexToken } from './validateEntityIndexToken.js';
|
|
|
22
22
|
* @throws `Error` if `entityToken` is invalid.
|
|
23
23
|
* @throws `Error` if `indexToken` is invalid.
|
|
24
24
|
*/
|
|
25
|
-
function rehydrateIndexItem(entityManager,
|
|
25
|
+
function rehydrateIndexItem(entityManager, entityToken, indexToken, dehydrated, omit = []) {
|
|
26
26
|
try {
|
|
27
27
|
const { generatedKeyDelimiter } = entityManager.config;
|
|
28
28
|
// Validate params.
|
|
@@ -34,11 +34,11 @@ function rehydrateIndexItem(entityManager, dehydrated, entityToken, indexToken,
|
|
|
34
34
|
if (elements.length !== values.length)
|
|
35
35
|
throw new Error('index rehydration key-value mismatch');
|
|
36
36
|
// Assign values to elements.
|
|
37
|
-
const rehydrated = shake(zipToObject(elements, values.map((value, i) => decodeEntityElement(entityManager,
|
|
37
|
+
const rehydrated = shake(zipToObject(elements, values.map((value, i) => decodeEntityElement(entityManager, entityToken, elements[i], value))));
|
|
38
38
|
entityManager.logger.debug('rehydrated index', {
|
|
39
|
-
dehydrated,
|
|
40
39
|
entityToken,
|
|
41
40
|
indexToken,
|
|
41
|
+
dehydrated,
|
|
42
42
|
elements,
|
|
43
43
|
values,
|
|
44
44
|
rehydrated,
|
|
@@ -48,9 +48,9 @@ function rehydrateIndexItem(entityManager, dehydrated, entityToken, indexToken,
|
|
|
48
48
|
catch (error) {
|
|
49
49
|
if (error instanceof Error)
|
|
50
50
|
entityManager.logger.error(error.message, {
|
|
51
|
-
dehydrated,
|
|
52
51
|
entityToken,
|
|
53
52
|
indexToken,
|
|
53
|
+
dehydrated,
|
|
54
54
|
});
|
|
55
55
|
throw error;
|
|
56
56
|
}
|