@karmaniverous/entity-manager 7.2.0 → 7.3.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.
- package/dist/cjs/EntityManager/EntityManager.js +8 -12
- package/dist/cjs/EntityManager/ParsedConfig.js +12 -1
- package/dist/cjs/EntityManager/createEntityManager.js +4 -0
- package/dist/cjs/EntityManager/findIndexToken.js +2 -13
- package/dist/index.d.ts +66 -57
- package/dist/mjs/EntityManager/EntityManager.js +8 -12
- package/dist/mjs/EntityManager/ParsedConfig.js +12 -1
- package/dist/mjs/EntityManager/createEntityManager.js +4 -0
- package/dist/mjs/EntityManager/findIndexToken.js +2 -13
- package/package.json +8 -2
|
@@ -15,6 +15,10 @@ var _EntityManager_config;
|
|
|
15
15
|
* query strategy to NoSql data.
|
|
16
16
|
*
|
|
17
17
|
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines the configuration's {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}. If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
18
|
+
* @typeParam CF - Values-first config literal type captured at construction
|
|
19
|
+
* time (phantom generic; type-only). This is used by downstream
|
|
20
|
+
* adapters to infer index-token unions (ITS) and per-index page
|
|
21
|
+
* key shapes.
|
|
18
22
|
*
|
|
19
23
|
* @remarks
|
|
20
24
|
* While the {@link EntityManager.query | `query`} method is `public`, normally it should not be called directly. The `query` method is used by a platform-specific {@link BaseQueryBuilder.query | `QueryBuilder.query`} method to provide a fluent query API.
|
|
@@ -87,19 +91,11 @@ class EntityManager {
|
|
|
87
91
|
}
|
|
88
92
|
return removeKeys.removeKeys(this, entityToken, i);
|
|
89
93
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Find an index token in a {@link Config | `Config`} object based on the index `hashKey` and `rangeKey`.
|
|
92
|
-
*
|
|
93
|
-
* @param hashKeyToken - Index hash key.
|
|
94
|
-
* @param rangeKeyToken - Index range key.
|
|
95
|
-
* @param suppressError - Suppress error if no match found.
|
|
96
|
-
*
|
|
97
|
-
* @returns Index token if found.
|
|
98
|
-
*
|
|
99
|
-
* @throws `Error` if no match found and `suppressError` is not `true`.
|
|
100
|
-
*/
|
|
101
94
|
findIndexToken(hashKeyToken, rangeKeyToken, suppressError) {
|
|
102
|
-
|
|
95
|
+
// Dispatch with a literal to satisfy overload selection.
|
|
96
|
+
return suppressError === true
|
|
97
|
+
? findIndexToken.findIndexToken(this, hashKeyToken, rangeKeyToken, true)
|
|
98
|
+
: findIndexToken.findIndexToken(this, hashKeyToken, rangeKeyToken, false);
|
|
103
99
|
}
|
|
104
100
|
/**
|
|
105
101
|
* Query a database entity across shards in a provider-generic fashion.
|
|
@@ -227,8 +227,19 @@ const configSchema = zod.z
|
|
|
227
227
|
path: ['generatedProperties', 'unsharded', property],
|
|
228
228
|
});
|
|
229
229
|
// Validate indexes.
|
|
230
|
-
//
|
|
230
|
+
// Validate no two indexes have the same hashKey & rangeKey.
|
|
231
|
+
const seenIndexPairs = new Set();
|
|
231
232
|
for (const [indexKey, { hashKey, rangeKey, projections }] of Object.entries(data.indexes)) {
|
|
233
|
+
const pairSig = `${hashKey}|${rangeKey}`;
|
|
234
|
+
if (seenIndexPairs.has(pairSig)) {
|
|
235
|
+
ctx.addIssue({
|
|
236
|
+
code: 'custom',
|
|
237
|
+
message: `duplicate index hashKey/rangeKey pair`,
|
|
238
|
+
path: ['indexes', indexKey],
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else
|
|
242
|
+
seenIndexPairs.add(pairSig);
|
|
232
243
|
// Validate hash key is sharded.
|
|
233
244
|
if (![data.hashKey, ...shardedKeys].includes(hashKey)) {
|
|
234
245
|
ctx.addIssue({
|
|
@@ -11,6 +11,10 @@ var EntityManager = require('./EntityManager.js');
|
|
|
11
11
|
* `satisfies` at call sites to preserve literal keys.
|
|
12
12
|
* @typeParam EM - EntityMap for the manager. Defaults to a minimal derived map
|
|
13
13
|
* from `CC.entitiesSchema` when present; otherwise falls back to EntityMap.
|
|
14
|
+
*
|
|
15
|
+
* @returns An {@link EntityManager | `EntityManager`} instance whose type
|
|
16
|
+
* captures CF from the single values-first config literal ({@link ConfigInput | `ConfigInput`})
|
|
17
|
+
* as the second generic parameter (phantom; type-only).
|
|
14
18
|
*/
|
|
15
19
|
function createEntityManager(config, logger = console) {
|
|
16
20
|
// Cast to the existing Config<C> shape for runtime parsing; Zod validation
|
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Find an index token in a {@link Config | `Config`} object based on the index `hashKey` and `rangeKey`.
|
|
5
|
-
*
|
|
6
|
-
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
7
|
-
* @param hashKeyToken - Index hash key.
|
|
8
|
-
* @param rangeKeyToken - Index range key.
|
|
9
|
-
* @param suppressError - Suppress error if no match found.
|
|
10
|
-
*
|
|
11
|
-
* @returns Index token if found.
|
|
12
|
-
*
|
|
13
|
-
* @throws `Error` if no match found and `suppressError` is not `true`.
|
|
14
|
-
*/
|
|
15
3
|
function findIndexToken(entityManager, hashKeyToken, rangeKeyToken, suppressError) {
|
|
16
|
-
const indexToken = Object.entries(entityManager.config.indexes).find(([, index]) => index.hashKey === hashKeyToken &&
|
|
4
|
+
const indexToken = (Object.entries(entityManager.config.indexes).find(([, index]) => index.hashKey === hashKeyToken &&
|
|
5
|
+
index.rangeKey === rangeKeyToken)?.[0] ?? undefined);
|
|
17
6
|
if (!indexToken && !suppressError)
|
|
18
7
|
throw new Error(`No index token found for hashKey '${hashKeyToken}' & rangeKey '${rangeKeyToken}'.`);
|
|
19
8
|
return indexToken;
|
package/dist/index.d.ts
CHANGED
|
@@ -148,54 +148,6 @@ type EntityKey<CC extends BaseConfigMap> = Record<CC['HashKey'] | CC['RangeKey']
|
|
|
148
148
|
*/
|
|
149
149
|
type EntityToken<CC extends BaseConfigMap> = keyof Exactify<CC['EntityMap']> & string;
|
|
150
150
|
|
|
151
|
-
declare const configSchema: z$1.ZodObject<{
|
|
152
|
-
entities: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
153
|
-
defaultLimit: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
154
|
-
defaultPageSize: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
155
|
-
shardBumps: z$1.ZodPipe<z$1.ZodDefault<z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
156
|
-
timestamp: z$1.ZodNumber;
|
|
157
|
-
charBits: z$1.ZodNumber;
|
|
158
|
-
chars: z$1.ZodNumber;
|
|
159
|
-
}, z$1.core.$strict>>>>, z$1.ZodTransform<{
|
|
160
|
-
timestamp: number;
|
|
161
|
-
charBits: number;
|
|
162
|
-
chars: number;
|
|
163
|
-
}[], {
|
|
164
|
-
timestamp: number;
|
|
165
|
-
charBits: number;
|
|
166
|
-
chars: number;
|
|
167
|
-
}[]>>;
|
|
168
|
-
timestampProperty: z$1.ZodString;
|
|
169
|
-
uniqueProperty: z$1.ZodString;
|
|
170
|
-
}, z$1.core.$strict>>>>;
|
|
171
|
-
generatedProperties: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodObject<{
|
|
172
|
-
sharded: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodArray<z$1.ZodString>>>>;
|
|
173
|
-
unsharded: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodArray<z$1.ZodString>>>>;
|
|
174
|
-
}, z$1.core.$strip>>>;
|
|
175
|
-
hashKey: z$1.ZodString;
|
|
176
|
-
indexes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
177
|
-
hashKey: z$1.ZodString;
|
|
178
|
-
rangeKey: z$1.ZodString;
|
|
179
|
-
projections: z$1.ZodOptional<z$1.ZodArray<z$1.ZodString>>;
|
|
180
|
-
}, z$1.core.$strip>>>>;
|
|
181
|
-
generatedKeyDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
182
|
-
generatedValueDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
183
|
-
propertyTranscodes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodString>>>;
|
|
184
|
-
rangeKey: z$1.ZodString;
|
|
185
|
-
shardKeyDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
186
|
-
throttle: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
187
|
-
transcodes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
188
|
-
encode: z$1.ZodCustom<unknown, unknown>;
|
|
189
|
-
decode: z$1.ZodCustom<unknown, unknown>;
|
|
190
|
-
}, z$1.core.$strict>>>>;
|
|
191
|
-
}, z$1.core.$strict>;
|
|
192
|
-
/**
|
|
193
|
-
* Simplified type taken on by a {@link Config | `Config`} object after parsing in the {@link EntityManager | `EntityManager`} constructor.
|
|
194
|
-
*
|
|
195
|
-
* @category EntityManager
|
|
196
|
-
*/
|
|
197
|
-
type ParsedConfig = z$1.infer<typeof configSchema>;
|
|
198
|
-
|
|
199
151
|
/**
|
|
200
152
|
* A partial {@link EntityItem | `EntityItem`} restricted to keys defined in `C`.
|
|
201
153
|
*
|
|
@@ -244,6 +196,54 @@ type IndexComponentTokens<CC extends BaseConfigMap, CF, IT extends string> = Has
|
|
|
244
196
|
*/
|
|
245
197
|
type PageKeyByIndex<CC extends BaseConfigMap, ET extends EntityToken<CC>, IT extends string = string, CF = unknown> = Pick<EntityItem<CC>, IndexComponentTokens<CC, CF, IT>>;
|
|
246
198
|
|
|
199
|
+
declare const configSchema: z$1.ZodObject<{
|
|
200
|
+
entities: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
201
|
+
defaultLimit: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
202
|
+
defaultPageSize: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
203
|
+
shardBumps: z$1.ZodPipe<z$1.ZodDefault<z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
204
|
+
timestamp: z$1.ZodNumber;
|
|
205
|
+
charBits: z$1.ZodNumber;
|
|
206
|
+
chars: z$1.ZodNumber;
|
|
207
|
+
}, z$1.core.$strict>>>>, z$1.ZodTransform<{
|
|
208
|
+
timestamp: number;
|
|
209
|
+
charBits: number;
|
|
210
|
+
chars: number;
|
|
211
|
+
}[], {
|
|
212
|
+
timestamp: number;
|
|
213
|
+
charBits: number;
|
|
214
|
+
chars: number;
|
|
215
|
+
}[]>>;
|
|
216
|
+
timestampProperty: z$1.ZodString;
|
|
217
|
+
uniqueProperty: z$1.ZodString;
|
|
218
|
+
}, z$1.core.$strict>>>>;
|
|
219
|
+
generatedProperties: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodObject<{
|
|
220
|
+
sharded: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodArray<z$1.ZodString>>>>;
|
|
221
|
+
unsharded: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodArray<z$1.ZodString>>>>;
|
|
222
|
+
}, z$1.core.$strip>>>;
|
|
223
|
+
hashKey: z$1.ZodString;
|
|
224
|
+
indexes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
225
|
+
hashKey: z$1.ZodString;
|
|
226
|
+
rangeKey: z$1.ZodString;
|
|
227
|
+
projections: z$1.ZodOptional<z$1.ZodArray<z$1.ZodString>>;
|
|
228
|
+
}, z$1.core.$strip>>>>;
|
|
229
|
+
generatedKeyDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
230
|
+
generatedValueDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
231
|
+
propertyTranscodes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodString>>>;
|
|
232
|
+
rangeKey: z$1.ZodString;
|
|
233
|
+
shardKeyDelimiter: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
234
|
+
throttle: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodNumber>>;
|
|
235
|
+
transcodes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
236
|
+
encode: z$1.ZodCustom<unknown, unknown>;
|
|
237
|
+
decode: z$1.ZodCustom<unknown, unknown>;
|
|
238
|
+
}, z$1.core.$strict>>>>;
|
|
239
|
+
}, z$1.core.$strict>;
|
|
240
|
+
/**
|
|
241
|
+
* Simplified type taken on by a {@link Config | `Config`} object after parsing in the {@link EntityManager | `EntityManager`} constructor.
|
|
242
|
+
*
|
|
243
|
+
* @category EntityManager
|
|
244
|
+
*/
|
|
245
|
+
type ParsedConfig = z$1.infer<typeof configSchema>;
|
|
246
|
+
|
|
247
247
|
/** EntityOfToken — resolves the concrete entity shape for a specific entity token. */
|
|
248
248
|
type EntityOfToken<CC extends BaseConfigMap, ET extends EntityToken<CC>> = Exactify<CC['EntityMap']>[ET];
|
|
249
249
|
/**
|
|
@@ -489,13 +489,17 @@ interface QueryResult<CC extends BaseConfigMap, ET extends EntityToken<CC>, ITS
|
|
|
489
489
|
* query strategy to NoSql data.
|
|
490
490
|
*
|
|
491
491
|
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines the configuration's {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}. If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
492
|
+
* @typeParam CF - Values-first config literal type captured at construction
|
|
493
|
+
* time (phantom generic; type-only). This is used by downstream
|
|
494
|
+
* adapters to infer index-token unions (ITS) and per-index page
|
|
495
|
+
* key shapes.
|
|
492
496
|
*
|
|
493
497
|
* @remarks
|
|
494
498
|
* While the {@link EntityManager.query | `query`} method is `public`, normally it should not be called directly. The `query` method is used by a platform-specific {@link BaseQueryBuilder.query | `QueryBuilder.query`} method to provide a fluent query API.
|
|
495
499
|
*
|
|
496
500
|
* @category EntityManager
|
|
497
501
|
*/
|
|
498
|
-
declare class EntityManager<CC extends BaseConfigMap> {
|
|
502
|
+
declare class EntityManager<CC extends BaseConfigMap, CF = unknown> {
|
|
499
503
|
#private;
|
|
500
504
|
/** Logger object (defaults to `console`, must support `debug` & `error` methods). */
|
|
501
505
|
readonly logger: Pick<Console, 'debug' | 'error'>;
|
|
@@ -582,17 +586,18 @@ declare class EntityManager<CC extends BaseConfigMap> {
|
|
|
582
586
|
*/
|
|
583
587
|
removeKeys<ET extends EntityToken<CC>>(entityToken: ET, items: EntityRecordByToken<CC, ET>[]): EntityItemByToken<CC, ET>[];
|
|
584
588
|
/**
|
|
585
|
-
* Find an index token
|
|
589
|
+
* Find an index token based on the configured hash and range key tokens.
|
|
586
590
|
*
|
|
587
|
-
* @param hashKeyToken - Index hash key.
|
|
588
|
-
* @param rangeKeyToken - Index range key.
|
|
589
|
-
* @param suppressError -
|
|
591
|
+
* @param hashKeyToken - Index hash key token (global hashKey or a sharded generated key).
|
|
592
|
+
* @param rangeKeyToken - Index range key token (global rangeKey, unsharded generated key, or a transcodable scalar).
|
|
593
|
+
* @param suppressError - When false (default), throws if no match; when true, returns undefined instead.
|
|
590
594
|
*
|
|
591
|
-
* @returns
|
|
595
|
+
* @returns A configured index token (narrowed to the CF.indexes key union) or undefined when allowed.
|
|
592
596
|
*
|
|
593
|
-
* @throws `Error` if no match found and `suppressError` is not `true`.
|
|
597
|
+
* @throws `Error` if no match is found and `suppressError` is not `true`.
|
|
594
598
|
*/
|
|
595
|
-
findIndexToken(hashKeyToken:
|
|
599
|
+
findIndexToken(hashKeyToken: CC['HashKey'] | CC['ShardedKeys'], rangeKeyToken: CC['RangeKey'] | CC['UnshardedKeys'] | CC['TranscodedProperties'], suppressError?: false): IndexTokensOf<CF>;
|
|
600
|
+
findIndexToken(hashKeyToken: CC['HashKey'] | CC['ShardedKeys'], rangeKeyToken: CC['RangeKey'] | CC['UnshardedKeys'] | CC['TranscodedProperties'], suppressError: true): IndexTokensOf<CF> | undefined;
|
|
596
601
|
/**
|
|
597
602
|
* Query a database entity across shards in a provider-generic fashion.
|
|
598
603
|
*
|
|
@@ -712,8 +717,12 @@ type CapturedConfigMapFrom<CC, EM extends EntityMap> = {
|
|
|
712
717
|
* `satisfies` at call sites to preserve literal keys.
|
|
713
718
|
* @typeParam EM - EntityMap for the manager. Defaults to a minimal derived map
|
|
714
719
|
* from `CC.entitiesSchema` when present; otherwise falls back to EntityMap.
|
|
720
|
+
*
|
|
721
|
+
* @returns An {@link EntityManager | `EntityManager`} instance whose type
|
|
722
|
+
* captures CF from the single values-first config literal ({@link ConfigInput | `ConfigInput`})
|
|
723
|
+
* as the second generic parameter (phantom; type-only).
|
|
715
724
|
*/
|
|
716
|
-
declare function createEntityManager<const CC extends ConfigInput, EM extends EntityMap = EntitiesFromSchema<CC>>(config: CC, logger?: Pick<Console, 'debug' | 'error'>): EntityManager<CapturedConfigMapFrom<CC, EM
|
|
725
|
+
declare function createEntityManager<const CC extends ConfigInput, EM extends EntityMap = EntitiesFromSchema<CC>>(config: CC, logger?: Pick<Console, 'debug' | 'error'>): EntityManager<CapturedConfigMapFrom<CC, EM>, CC>;
|
|
717
726
|
|
|
718
727
|
/**
|
|
719
728
|
* Database-facing record type from a {@link BaseConfigMap | `ConfigMap`} with required hash & range keys.
|
|
@@ -13,6 +13,10 @@ var _EntityManager_config;
|
|
|
13
13
|
* query strategy to NoSql data.
|
|
14
14
|
*
|
|
15
15
|
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines the configuration's {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}. If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
16
|
+
* @typeParam CF - Values-first config literal type captured at construction
|
|
17
|
+
* time (phantom generic; type-only). This is used by downstream
|
|
18
|
+
* adapters to infer index-token unions (ITS) and per-index page
|
|
19
|
+
* key shapes.
|
|
16
20
|
*
|
|
17
21
|
* @remarks
|
|
18
22
|
* While the {@link EntityManager.query | `query`} method is `public`, normally it should not be called directly. The `query` method is used by a platform-specific {@link BaseQueryBuilder.query | `QueryBuilder.query`} method to provide a fluent query API.
|
|
@@ -85,19 +89,11 @@ class EntityManager {
|
|
|
85
89
|
}
|
|
86
90
|
return removeKeys(this, entityToken, i);
|
|
87
91
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Find an index token in a {@link Config | `Config`} object based on the index `hashKey` and `rangeKey`.
|
|
90
|
-
*
|
|
91
|
-
* @param hashKeyToken - Index hash key.
|
|
92
|
-
* @param rangeKeyToken - Index range key.
|
|
93
|
-
* @param suppressError - Suppress error if no match found.
|
|
94
|
-
*
|
|
95
|
-
* @returns Index token if found.
|
|
96
|
-
*
|
|
97
|
-
* @throws `Error` if no match found and `suppressError` is not `true`.
|
|
98
|
-
*/
|
|
99
92
|
findIndexToken(hashKeyToken, rangeKeyToken, suppressError) {
|
|
100
|
-
|
|
93
|
+
// Dispatch with a literal to satisfy overload selection.
|
|
94
|
+
return suppressError === true
|
|
95
|
+
? findIndexToken(this, hashKeyToken, rangeKeyToken, true)
|
|
96
|
+
: findIndexToken(this, hashKeyToken, rangeKeyToken, false);
|
|
101
97
|
}
|
|
102
98
|
/**
|
|
103
99
|
* Query a database entity across shards in a provider-generic fashion.
|
|
@@ -225,8 +225,19 @@ const configSchema = z
|
|
|
225
225
|
path: ['generatedProperties', 'unsharded', property],
|
|
226
226
|
});
|
|
227
227
|
// Validate indexes.
|
|
228
|
-
//
|
|
228
|
+
// Validate no two indexes have the same hashKey & rangeKey.
|
|
229
|
+
const seenIndexPairs = new Set();
|
|
229
230
|
for (const [indexKey, { hashKey, rangeKey, projections }] of Object.entries(data.indexes)) {
|
|
231
|
+
const pairSig = `${hashKey}|${rangeKey}`;
|
|
232
|
+
if (seenIndexPairs.has(pairSig)) {
|
|
233
|
+
ctx.addIssue({
|
|
234
|
+
code: 'custom',
|
|
235
|
+
message: `duplicate index hashKey/rangeKey pair`,
|
|
236
|
+
path: ['indexes', indexKey],
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
else
|
|
240
|
+
seenIndexPairs.add(pairSig);
|
|
230
241
|
// Validate hash key is sharded.
|
|
231
242
|
if (![data.hashKey, ...shardedKeys].includes(hashKey)) {
|
|
232
243
|
ctx.addIssue({
|
|
@@ -9,6 +9,10 @@ import { EntityManager } from './EntityManager.js';
|
|
|
9
9
|
* `satisfies` at call sites to preserve literal keys.
|
|
10
10
|
* @typeParam EM - EntityMap for the manager. Defaults to a minimal derived map
|
|
11
11
|
* from `CC.entitiesSchema` when present; otherwise falls back to EntityMap.
|
|
12
|
+
*
|
|
13
|
+
* @returns An {@link EntityManager | `EntityManager`} instance whose type
|
|
14
|
+
* captures CF from the single values-first config literal ({@link ConfigInput | `ConfigInput`})
|
|
15
|
+
* as the second generic parameter (phantom; type-only).
|
|
12
16
|
*/
|
|
13
17
|
function createEntityManager(config, logger = console) {
|
|
14
18
|
// Cast to the existing Config<C> shape for runtime parsing; Zod validation
|
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Find an index token in a {@link Config | `Config`} object based on the index `hashKey` and `rangeKey`.
|
|
3
|
-
*
|
|
4
|
-
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
5
|
-
* @param hashKeyToken - Index hash key.
|
|
6
|
-
* @param rangeKeyToken - Index range key.
|
|
7
|
-
* @param suppressError - Suppress error if no match found.
|
|
8
|
-
*
|
|
9
|
-
* @returns Index token if found.
|
|
10
|
-
*
|
|
11
|
-
* @throws `Error` if no match found and `suppressError` is not `true`.
|
|
12
|
-
*/
|
|
13
1
|
function findIndexToken(entityManager, hashKeyToken, rangeKeyToken, suppressError) {
|
|
14
|
-
const indexToken = Object.entries(entityManager.config.indexes).find(([, index]) => index.hashKey === hashKeyToken &&
|
|
2
|
+
const indexToken = (Object.entries(entityManager.config.indexes).find(([, index]) => index.hashKey === hashKeyToken &&
|
|
3
|
+
index.rangeKey === rangeKeyToken)?.[0] ?? undefined);
|
|
15
4
|
if (!indexToken && !suppressError)
|
|
16
5
|
throw new Error(`No index token found for hashKey '${hashKeyToken}' & rangeKey '${rangeKeyToken}'.`);
|
|
17
6
|
return indexToken;
|
package/package.json
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Jason Williscroft",
|
|
3
|
+
"auto-changelog": {
|
|
4
|
+
"commitLimit": false,
|
|
5
|
+
"hideCredit": true,
|
|
6
|
+
"output": "CHANGELOG.md",
|
|
7
|
+
"unreleased": true
|
|
8
|
+
},
|
|
3
9
|
"bugs": {
|
|
4
10
|
"url": "https://github.com/karmaniverous/entity-manager/issues"
|
|
5
11
|
},
|
|
@@ -81,7 +87,7 @@
|
|
|
81
87
|
},
|
|
82
88
|
"release-it": {
|
|
83
89
|
"git": {
|
|
84
|
-
"changelog": "npx auto-changelog --stdout --
|
|
90
|
+
"changelog": "npx auto-changelog --stdout --unreleased --template https://raw.githubusercontent.com/release-it/release-it/main/templates/changelog-compact.hbs",
|
|
85
91
|
"commitMessage": "chore: release v${version}",
|
|
86
92
|
"requireBranch": "main"
|
|
87
93
|
},
|
|
@@ -128,5 +134,5 @@
|
|
|
128
134
|
},
|
|
129
135
|
"type": "module",
|
|
130
136
|
"types": "dist/index.d.ts",
|
|
131
|
-
"version": "7.
|
|
137
|
+
"version": "7.3.1"
|
|
132
138
|
}
|