@karmaniverous/entity-manager 7.3.0 → 7.3.2
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/BaseEntityClient/BaseEntityClient.js +6 -2
- 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 +77 -64
- package/dist/mjs/BaseEntityClient/BaseEntityClient.js +6 -2
- 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 +1 -1
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Base EntityClient class. Integrates {@link EntityManager | `EntityManager`} with injected logging & enhanced batch processing.
|
|
5
5
|
*
|
|
6
|
-
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
6
|
+
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
7
|
+
* {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}.
|
|
8
|
+
* If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
9
|
+
* @typeParam CF - Values-first config literal type captured by the manager (phantom; type-only). Propagated so
|
|
10
|
+
* client-facing calls that return `IndexTokensOf<CF>` retain the narrowed union.
|
|
7
11
|
*
|
|
8
12
|
* @category EntityClient
|
|
9
13
|
*/
|
|
10
14
|
class BaseEntityClient {
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
* Base EntityClient constructor.
|
|
13
17
|
*
|
|
14
18
|
* @param options - {@link BaseEntityClientOptions | `BaseEntityClientOptions`} object.
|
|
15
19
|
*/
|
|
@@ -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,6 +489,10 @@ 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.
|
|
@@ -582,17 +586,18 @@ declare class EntityManager<CC extends BaseConfigMap, CF = unknown> {
|
|
|
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,6 +717,10 @@ 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
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
|
|
|
@@ -732,11 +741,11 @@ type EntityRecord<CC extends BaseConfigMap> = EntityItem<CC> & EntityKey<CC>;
|
|
|
732
741
|
*
|
|
733
742
|
* @category EntityClient
|
|
734
743
|
*/
|
|
735
|
-
interface BaseEntityClientOptions<CC extends BaseConfigMap> {
|
|
744
|
+
interface BaseEntityClientOptions<CC extends BaseConfigMap, CF = unknown> {
|
|
736
745
|
/** Default batch process options. */
|
|
737
746
|
batchProcessOptions?: Omit<BatchProcessOptions<unknown, unknown>, 'batchHandler' | 'unprocessedItemExtractor'>;
|
|
738
747
|
/** {@link EntityManager | `EntityManager`} instance. */
|
|
739
|
-
entityManager: EntityManager<CC>;
|
|
748
|
+
entityManager: EntityManager<CC, CF>;
|
|
740
749
|
/** Injected logger object. Must support `debug` and `error` methods. Default: `console` */
|
|
741
750
|
logger?: Pick<Console, 'debug' | 'error'>;
|
|
742
751
|
}
|
|
@@ -744,23 +753,27 @@ interface BaseEntityClientOptions<CC extends BaseConfigMap> {
|
|
|
744
753
|
/**
|
|
745
754
|
* Base EntityClient class. Integrates {@link EntityManager | `EntityManager`} with injected logging & enhanced batch processing.
|
|
746
755
|
*
|
|
747
|
-
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
756
|
+
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
757
|
+
* {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}.
|
|
758
|
+
* If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
759
|
+
* @typeParam CF - Values-first config literal type captured by the manager (phantom; type-only). Propagated so
|
|
760
|
+
* client-facing calls that return `IndexTokensOf<CF>` retain the narrowed union.
|
|
748
761
|
*
|
|
749
762
|
* @category EntityClient
|
|
750
763
|
*/
|
|
751
|
-
declare abstract class BaseEntityClient<CC extends BaseConfigMap> {
|
|
764
|
+
declare abstract class BaseEntityClient<CC extends BaseConfigMap, CF = unknown> {
|
|
752
765
|
/** Default batch process options. */
|
|
753
|
-
readonly batchProcessOptions: NonNullable<BaseEntityClientOptions<CC>['batchProcessOptions']>;
|
|
766
|
+
readonly batchProcessOptions: NonNullable<BaseEntityClientOptions<CC, CF>['batchProcessOptions']>;
|
|
754
767
|
/** {@link EntityManager | `EntityManager`} instance. */
|
|
755
|
-
readonly entityManager: EntityManager<CC>;
|
|
768
|
+
readonly entityManager: EntityManager<CC, CF>;
|
|
756
769
|
/** Injected logger object. Must support `debug` and `error` methods. Default: `console` */
|
|
757
|
-
readonly logger: NonNullable<BaseEntityClientOptions<CC>['logger']>;
|
|
770
|
+
readonly logger: NonNullable<BaseEntityClientOptions<CC, CF>['logger']>;
|
|
758
771
|
/**
|
|
759
|
-
*
|
|
772
|
+
* Base EntityClient constructor.
|
|
760
773
|
*
|
|
761
774
|
* @param options - {@link BaseEntityClientOptions | `BaseEntityClientOptions`} object.
|
|
762
775
|
*/
|
|
763
|
-
constructor(options: BaseEntityClientOptions<CC>);
|
|
776
|
+
constructor(options: BaseEntityClientOptions<CC, CF>);
|
|
764
777
|
}
|
|
765
778
|
|
|
766
779
|
type ConfigOfClient<EC> = EC extends BaseEntityClient<infer CC> ? CC : never;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base EntityClient class. Integrates {@link EntityManager | `EntityManager`} with injected logging & enhanced batch processing.
|
|
3
3
|
*
|
|
4
|
-
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
4
|
+
* @typeParam CC - {@link ConfigMap | `ConfigMap`} that defines an {@link Config | `EntityManager configuration`}'s
|
|
5
|
+
* {@link EntityMap | `EntityMap`}, key properties, and {@link TranscodeRegistry | `TranscodeRegistry`}.
|
|
6
|
+
* If omitted, defaults to {@link BaseConfigMap | `BaseConfigMap`}.
|
|
7
|
+
* @typeParam CF - Values-first config literal type captured by the manager (phantom; type-only). Propagated so
|
|
8
|
+
* client-facing calls that return `IndexTokensOf<CF>` retain the narrowed union.
|
|
5
9
|
*
|
|
6
10
|
* @category EntityClient
|
|
7
11
|
*/
|
|
8
12
|
class BaseEntityClient {
|
|
9
13
|
/**
|
|
10
|
-
*
|
|
14
|
+
* Base EntityClient constructor.
|
|
11
15
|
*
|
|
12
16
|
* @param options - {@link BaseEntityClientOptions | `BaseEntityClientOptions`} object.
|
|
13
17
|
*/
|
|
@@ -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