@karmaniverous/entity-manager 6.13.3 → 6.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +330 -16
- package/dist/cjs/{EntityManager.js → EntityManager/EntityManager.js} +18 -44
- package/dist/cjs/{ParsedConfig.js → EntityManager/ParsedConfig.js} +46 -55
- package/dist/cjs/{addKeys.js → EntityManager/addKeys.js} +1 -0
- package/dist/cjs/{decodeElement.js → EntityManager/decodeElement.js} +2 -1
- package/dist/cjs/{dehydratePageKeyMap.js → EntityManager/dehydratePageKeyMap.js} +3 -1
- package/dist/cjs/{encodeElement.js → EntityManager/encodeElement.js} +2 -2
- package/dist/cjs/{encodeGeneratedProperty.js → EntityManager/encodeGeneratedProperty.js} +1 -1
- package/dist/cjs/EntityManager/getPrimaryKey.js +25 -0
- package/dist/cjs/{rehydratePageKeyMap.js → EntityManager/rehydratePageKeyMap.js} +3 -1
- package/dist/cjs/{removeKeys.js → EntityManager/removeKeys.js} +10 -8
- package/dist/cjs/{updateItemHashKey.js → EntityManager/updateItemHashKey.js} +4 -1
- package/dist/cjs/index.js +5 -3
- package/dist/index.d.ts +109 -252
- package/dist/mjs/{EntityManager.js → EntityManager/EntityManager.js} +18 -44
- package/dist/mjs/{ParsedConfig.js → EntityManager/ParsedConfig.js} +46 -55
- package/dist/mjs/{addKeys.js → EntityManager/addKeys.js} +1 -0
- package/dist/mjs/{decodeElement.js → EntityManager/decodeElement.js} +2 -1
- package/dist/mjs/{dehydratePageKeyMap.js → EntityManager/dehydratePageKeyMap.js} +3 -1
- package/dist/mjs/{encodeElement.js → EntityManager/encodeElement.js} +2 -2
- package/dist/mjs/{encodeGeneratedProperty.js → EntityManager/encodeGeneratedProperty.js} +1 -1
- package/dist/mjs/EntityManager/getPrimaryKey.js +23 -0
- package/dist/mjs/{rehydratePageKeyMap.js → EntityManager/rehydratePageKeyMap.js} +3 -1
- package/dist/mjs/{removeKeys.js → EntityManager/removeKeys.js} +10 -8
- package/dist/mjs/{updateItemHashKey.js → EntityManager/updateItemHashKey.js} +4 -1
- package/dist/mjs/index.js +4 -3
- package/package.json +44 -45
- /package/dist/cjs/{BaseEntityClient.js → BaseEntityClient/BaseEntityClient.js} +0 -0
- /package/dist/cjs/{BaseQueryBuilder.js → BaseQueryBuilder/BaseQueryBuilder.js} +0 -0
- /package/dist/cjs/{decodeGeneratedProperty.js → EntityManager/decodeGeneratedProperty.js} +0 -0
- /package/dist/cjs/{dehydrateIndexItem.js → EntityManager/dehydrateIndexItem.js} +0 -0
- /package/dist/cjs/{findIndexToken.js → EntityManager/findIndexToken.js} +0 -0
- /package/dist/cjs/{getHashKeySpace.js → EntityManager/getHashKeySpace.js} +0 -0
- /package/dist/cjs/{getIndexComponents.js → EntityManager/getIndexComponents.js} +0 -0
- /package/dist/cjs/{getShardBump.js → EntityManager/getShardBump.js} +0 -0
- /package/dist/cjs/{query.js → EntityManager/query.js} +0 -0
- /package/dist/cjs/{rehydrateIndexItem.js → EntityManager/rehydrateIndexItem.js} +0 -0
- /package/dist/cjs/{unwrapIndex.js → EntityManager/unwrapIndex.js} +0 -0
- /package/dist/cjs/{updateItemRangeKey.js → EntityManager/updateItemRangeKey.js} +0 -0
- /package/dist/cjs/{validateEntityToken.js → EntityManager/validateEntityToken.js} +0 -0
- /package/dist/cjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js} +0 -0
- /package/dist/cjs/{validateIndexToken.js → EntityManager/validateIndexToken.js} +0 -0
- /package/dist/cjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js} +0 -0
- /package/dist/mjs/{BaseEntityClient.js → BaseEntityClient/BaseEntityClient.js} +0 -0
- /package/dist/mjs/{BaseQueryBuilder.js → BaseQueryBuilder/BaseQueryBuilder.js} +0 -0
- /package/dist/mjs/{decodeGeneratedProperty.js → EntityManager/decodeGeneratedProperty.js} +0 -0
- /package/dist/mjs/{dehydrateIndexItem.js → EntityManager/dehydrateIndexItem.js} +0 -0
- /package/dist/mjs/{findIndexToken.js → EntityManager/findIndexToken.js} +0 -0
- /package/dist/mjs/{getHashKeySpace.js → EntityManager/getHashKeySpace.js} +0 -0
- /package/dist/mjs/{getIndexComponents.js → EntityManager/getIndexComponents.js} +0 -0
- /package/dist/mjs/{getShardBump.js → EntityManager/getShardBump.js} +0 -0
- /package/dist/mjs/{query.js → EntityManager/query.js} +0 -0
- /package/dist/mjs/{rehydrateIndexItem.js → EntityManager/rehydrateIndexItem.js} +0 -0
- /package/dist/mjs/{unwrapIndex.js → EntityManager/unwrapIndex.js} +0 -0
- /package/dist/mjs/{updateItemRangeKey.js → EntityManager/updateItemRangeKey.js} +0 -0
- /package/dist/mjs/{validateEntityToken.js → EntityManager/validateEntityToken.js} +0 -0
- /package/dist/mjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js} +0 -0
- /package/dist/mjs/{validateIndexToken.js → EntityManager/validateIndexToken.js} +0 -0
- /package/dist/mjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js} +0 -0
|
@@ -8,7 +8,7 @@ const validateArrayUnique = (arr, ctx, identity = (item) => item, path = []) =>
|
|
|
8
8
|
for (const [element, count] of Object.entries(counts)) {
|
|
9
9
|
if (count > 1)
|
|
10
10
|
ctx.addIssue({
|
|
11
|
-
code:
|
|
11
|
+
code: 'custom',
|
|
12
12
|
message: `duplicate array element`,
|
|
13
13
|
params: { element },
|
|
14
14
|
path,
|
|
@@ -19,7 +19,7 @@ const validateKeysExclusive = (keys, label, ref, ctx) => {
|
|
|
19
19
|
const intersection = keys.filter((key) => ref.includes(key));
|
|
20
20
|
if (intersection.length)
|
|
21
21
|
ctx.addIssue({
|
|
22
|
-
code:
|
|
22
|
+
code: 'custom',
|
|
23
23
|
message: `${label} key collision: ${intersection.toString()}`,
|
|
24
24
|
});
|
|
25
25
|
};
|
|
@@ -30,26 +30,14 @@ const componentArray = z
|
|
|
30
30
|
const configSchema = z
|
|
31
31
|
.object({
|
|
32
32
|
entities: z
|
|
33
|
-
.record(z
|
|
33
|
+
.record(z.string(), z
|
|
34
34
|
.object({
|
|
35
|
-
defaultLimit: z
|
|
36
|
-
|
|
37
|
-
.int()
|
|
38
|
-
.positive()
|
|
39
|
-
.safe()
|
|
40
|
-
.optional()
|
|
41
|
-
.default(10),
|
|
42
|
-
defaultPageSize: z
|
|
43
|
-
.number()
|
|
44
|
-
.int()
|
|
45
|
-
.positive()
|
|
46
|
-
.safe()
|
|
47
|
-
.optional()
|
|
48
|
-
.default(10),
|
|
35
|
+
defaultLimit: z.number().int().positive().optional().default(10),
|
|
36
|
+
defaultPageSize: z.number().int().positive().optional().default(10),
|
|
49
37
|
shardBumps: z
|
|
50
38
|
.array(z
|
|
51
39
|
.object({
|
|
52
|
-
timestamp: z.number().
|
|
40
|
+
timestamp: z.number().int().nonnegative(),
|
|
53
41
|
charBits: z.number().int().min(1).max(5),
|
|
54
42
|
chars: z.number().int().min(0).max(40),
|
|
55
43
|
})
|
|
@@ -77,7 +65,7 @@ const configSchema = z
|
|
|
77
65
|
for (let i = 1; i < val.length; i++)
|
|
78
66
|
if (val[i].chars <= val[i - 1].chars)
|
|
79
67
|
ctx.addIssue({
|
|
80
|
-
code:
|
|
68
|
+
code: 'custom',
|
|
81
69
|
message: `shardBump chars do not monotonically increase at timestamp ${val[i].timestamp.toString()}`,
|
|
82
70
|
path: [i],
|
|
83
71
|
});
|
|
@@ -91,14 +79,14 @@ const configSchema = z
|
|
|
91
79
|
.default({}),
|
|
92
80
|
generatedProperties: z
|
|
93
81
|
.object({
|
|
94
|
-
sharded: z.record(componentArray).optional().default({}),
|
|
95
|
-
unsharded: z.record(componentArray).optional().default({}),
|
|
82
|
+
sharded: z.record(z.string(), componentArray).optional().default({}),
|
|
83
|
+
unsharded: z.record(z.string(), componentArray).optional().default({}),
|
|
96
84
|
})
|
|
97
85
|
.optional()
|
|
98
86
|
.default({ sharded: {}, unsharded: {} }),
|
|
99
87
|
hashKey: z.string(),
|
|
100
88
|
indexes: z
|
|
101
|
-
.record(z.object({
|
|
89
|
+
.record(z.string(), z.object({
|
|
102
90
|
hashKey: z.string().min(1),
|
|
103
91
|
rangeKey: z.string().min(1),
|
|
104
92
|
projections: z
|
|
@@ -110,15 +98,18 @@ const configSchema = z
|
|
|
110
98
|
.default({}),
|
|
111
99
|
generatedKeyDelimiter: z.string().regex(/\W+/).optional().default('|'),
|
|
112
100
|
generatedValueDelimiter: z.string().regex(/\W+/).optional().default('#'),
|
|
113
|
-
propertyTranscodes: z.record(z.string()).optional().default({}),
|
|
101
|
+
propertyTranscodes: z.record(z.string(), z.string()).optional().default({}),
|
|
114
102
|
rangeKey: z.string(),
|
|
115
103
|
shardKeyDelimiter: z.string().regex(/\W+/).optional().default('!'),
|
|
116
|
-
throttle: z.number().int().positive().
|
|
104
|
+
throttle: z.number().int().positive().optional().default(10),
|
|
117
105
|
transcodes: z
|
|
118
|
-
.record(z
|
|
106
|
+
.record(z.string(), z
|
|
119
107
|
.object({
|
|
120
|
-
|
|
121
|
-
|
|
108
|
+
// Accept function shapes without relying on z.function()
|
|
109
|
+
// to avoid TS inference conflicts across Zod versions and
|
|
110
|
+
// to remain compatible with narrower parameter types.
|
|
111
|
+
encode: z.custom((fn) => typeof fn === 'function'),
|
|
112
|
+
decode: z.custom((fn) => typeof fn === 'function'),
|
|
122
113
|
})
|
|
123
114
|
.strict())
|
|
124
115
|
.optional()
|
|
@@ -129,7 +120,7 @@ const configSchema = z
|
|
|
129
120
|
// validate no generated key delimiter collision
|
|
130
121
|
if (data.generatedKeyDelimiter.includes(data.generatedValueDelimiter))
|
|
131
122
|
ctx.addIssue({
|
|
132
|
-
code:
|
|
123
|
+
code: 'custom',
|
|
133
124
|
message: 'generatedKeyDelimiter contains generatedValueDelimiter',
|
|
134
125
|
params: {
|
|
135
126
|
generatedKeyDelimiter: data.generatedKeyDelimiter,
|
|
@@ -139,7 +130,7 @@ const configSchema = z
|
|
|
139
130
|
});
|
|
140
131
|
if (data.generatedKeyDelimiter.includes(data.shardKeyDelimiter))
|
|
141
132
|
ctx.addIssue({
|
|
142
|
-
code:
|
|
133
|
+
code: 'custom',
|
|
143
134
|
message: 'generatedKeyDelimiter contains shardKeyDelimiter',
|
|
144
135
|
params: {
|
|
145
136
|
generatedKeyDelimiter: data.generatedKeyDelimiter,
|
|
@@ -150,7 +141,7 @@ const configSchema = z
|
|
|
150
141
|
// validate no generated value delimiter collision
|
|
151
142
|
if (data.generatedValueDelimiter.includes(data.generatedKeyDelimiter))
|
|
152
143
|
ctx.addIssue({
|
|
153
|
-
code:
|
|
144
|
+
code: 'custom',
|
|
154
145
|
message: 'generatedValueDelimiter contains generatedKeyDelimiter',
|
|
155
146
|
params: {
|
|
156
147
|
generatedValueDelimiter: data.generatedValueDelimiter,
|
|
@@ -160,7 +151,7 @@ const configSchema = z
|
|
|
160
151
|
});
|
|
161
152
|
if (data.generatedValueDelimiter.includes(data.shardKeyDelimiter))
|
|
162
153
|
ctx.addIssue({
|
|
163
|
-
code:
|
|
154
|
+
code: 'custom',
|
|
164
155
|
message: 'generatedValueDelimiter contains shardKeyDelimiter',
|
|
165
156
|
params: {
|
|
166
157
|
generatedValueDelimiter: data.generatedValueDelimiter,
|
|
@@ -171,7 +162,7 @@ const configSchema = z
|
|
|
171
162
|
// validate no shard key delimiter collision
|
|
172
163
|
if (data.shardKeyDelimiter.includes(data.generatedKeyDelimiter))
|
|
173
164
|
ctx.addIssue({
|
|
174
|
-
code:
|
|
165
|
+
code: 'custom',
|
|
175
166
|
message: 'shardKeyDelimiter contains generatedKeyDelimiter',
|
|
176
167
|
params: {
|
|
177
168
|
generatedKeyDelimiter: data.generatedKeyDelimiter,
|
|
@@ -181,7 +172,7 @@ const configSchema = z
|
|
|
181
172
|
});
|
|
182
173
|
if (data.shardKeyDelimiter.includes(data.generatedValueDelimiter))
|
|
183
174
|
ctx.addIssue({
|
|
184
|
-
code:
|
|
175
|
+
code: 'custom',
|
|
185
176
|
message: 'shardKeyDelimiter contains generatedValueDelimiter',
|
|
186
177
|
params: {
|
|
187
178
|
generatedValueDelimiter: data.generatedValueDelimiter,
|
|
@@ -211,19 +202,17 @@ const configSchema = z
|
|
|
211
202
|
for (const [property, transcode] of Object.entries(data.propertyTranscodes))
|
|
212
203
|
if (!transcodes.includes(transcode))
|
|
213
204
|
ctx.addIssue({
|
|
214
|
-
code:
|
|
215
|
-
|
|
205
|
+
code: 'custom',
|
|
206
|
+
message: `propertyTranscodes['${property}'] references unknown transcode '${transcode}'`,
|
|
216
207
|
path: ['propertyTranscodes', property],
|
|
217
|
-
received: transcode,
|
|
218
208
|
});
|
|
219
209
|
// Validate all sharded property elements are transcoded properties.
|
|
220
210
|
for (const [property, elements] of Object.entries(data.generatedProperties.sharded))
|
|
221
211
|
for (const element of elements)
|
|
222
212
|
if (!transcodedProperties.includes(element))
|
|
223
213
|
ctx.addIssue({
|
|
224
|
-
code:
|
|
225
|
-
|
|
226
|
-
received: element,
|
|
214
|
+
code: 'custom',
|
|
215
|
+
message: `generatedProperties.sharded['${property}'] contains non-transcoded element '${element}'`,
|
|
227
216
|
path: ['generatedProperties', 'sharded', property],
|
|
228
217
|
});
|
|
229
218
|
// Validate all unsharded property elements are transcoded properties.
|
|
@@ -231,9 +220,8 @@ const configSchema = z
|
|
|
231
220
|
for (const element of elements)
|
|
232
221
|
if (!transcodedProperties.includes(element))
|
|
233
222
|
ctx.addIssue({
|
|
234
|
-
code:
|
|
235
|
-
|
|
236
|
-
received: element,
|
|
223
|
+
code: 'custom',
|
|
224
|
+
message: `generatedProperties.unsharded['${property}'] contains non-transcoded element '${element}'`,
|
|
237
225
|
path: ['generatedProperties', 'unsharded', property],
|
|
238
226
|
});
|
|
239
227
|
// Validate indexes.
|
|
@@ -242,19 +230,24 @@ const configSchema = z
|
|
|
242
230
|
// Validate hash key is sharded.
|
|
243
231
|
if (![data.hashKey, ...shardedKeys].includes(hashKey)) {
|
|
244
232
|
ctx.addIssue({
|
|
245
|
-
code:
|
|
246
|
-
|
|
233
|
+
code: 'custom',
|
|
234
|
+
message: `index '${indexKey}' hashKey '${hashKey}' must be one of [${[
|
|
235
|
+
data.hashKey,
|
|
236
|
+
...shardedKeys,
|
|
237
|
+
].join(', ')}]`,
|
|
247
238
|
path: ['indexes', indexKey, 'hashKey'],
|
|
248
|
-
received: hashKey,
|
|
249
239
|
});
|
|
250
240
|
}
|
|
251
241
|
// Validate range key is unsharded or transcodable.
|
|
252
242
|
if (![data.rangeKey, ...unshardedKeys, ...transcodedProperties].includes(rangeKey)) {
|
|
253
243
|
ctx.addIssue({
|
|
254
|
-
code:
|
|
255
|
-
|
|
244
|
+
code: 'custom',
|
|
245
|
+
message: `index '${indexKey}' rangeKey '${rangeKey}' must be one of [${[
|
|
246
|
+
data.rangeKey,
|
|
247
|
+
...unshardedKeys,
|
|
248
|
+
...transcodedProperties,
|
|
249
|
+
].join(', ')}]`,
|
|
256
250
|
path: ['indexes', indexKey, 'rangeKey'],
|
|
257
|
-
received: rangeKey,
|
|
258
251
|
});
|
|
259
252
|
}
|
|
260
253
|
// Validate no index projections are keys.
|
|
@@ -269,7 +262,7 @@ const configSchema = z
|
|
|
269
262
|
...unshardedKeys,
|
|
270
263
|
].includes(projection))
|
|
271
264
|
ctx.addIssue({
|
|
272
|
-
code:
|
|
265
|
+
code: 'custom',
|
|
273
266
|
message: 'index projection is a key',
|
|
274
267
|
params: { projection },
|
|
275
268
|
path: ['indexes', indexKey, 'projections'],
|
|
@@ -280,18 +273,16 @@ const configSchema = z
|
|
|
280
273
|
// validate timestampProperty is a transcoded property.
|
|
281
274
|
if (!transcodedProperties.includes(timestampProperty))
|
|
282
275
|
ctx.addIssue({
|
|
283
|
-
code:
|
|
284
|
-
|
|
276
|
+
code: 'custom',
|
|
277
|
+
message: `entities['${entityToken}'].timestampProperty '${timestampProperty}' must be one of [${transcodedProperties.join(', ')}]`,
|
|
285
278
|
path: ['entities', entityToken, 'timestampProperty'],
|
|
286
|
-
received: timestampProperty,
|
|
287
279
|
});
|
|
288
280
|
// validate uniqueProperty is a transcoded property.
|
|
289
281
|
if (!transcodedProperties.includes(uniqueProperty))
|
|
290
282
|
ctx.addIssue({
|
|
291
|
-
code:
|
|
292
|
-
|
|
283
|
+
code: 'custom',
|
|
284
|
+
message: `entities['${entityToken}'].uniqueProperty '${uniqueProperty}' must be one of [${transcodedProperties.join(', ')}]`,
|
|
293
285
|
path: ['entities', entityToken, 'uniqueProperty'],
|
|
294
|
-
received: uniqueProperty,
|
|
295
286
|
});
|
|
296
287
|
}
|
|
297
288
|
});
|
|
@@ -22,7 +22,8 @@ function decodeElement(entityManager, element, value) {
|
|
|
22
22
|
if (!value)
|
|
23
23
|
return;
|
|
24
24
|
const { propertyTranscodes, transcodes } = entityManager.config;
|
|
25
|
-
const
|
|
25
|
+
const decodeFn = transcodes[propertyTranscodes[element]].decode;
|
|
26
|
+
const decoded = decodeFn(value);
|
|
26
27
|
entityManager.logger.debug('decoded entity element', {
|
|
27
28
|
element,
|
|
28
29
|
value,
|
|
@@ -38,7 +38,9 @@ function dehydratePageKeyMap(entityManager, entityToken, pageKeyMap) {
|
|
|
38
38
|
}
|
|
39
39
|
// Extract, sort & validate indexs.
|
|
40
40
|
const indexes = Object.keys(pageKeyMap).sort();
|
|
41
|
-
indexes.map((index) =>
|
|
41
|
+
indexes.map((index) => {
|
|
42
|
+
validateIndexToken(entityManager, index);
|
|
43
|
+
});
|
|
42
44
|
// Extract & sort hash keys.
|
|
43
45
|
const hashKeys = Object.keys(pageKeyMap[indexes[0]]);
|
|
44
46
|
// Dehydrate page keys.
|
|
@@ -19,8 +19,8 @@ function encodeElement(entityManager, element, item) {
|
|
|
19
19
|
const value = item[element];
|
|
20
20
|
if (value === undefined || [hashKey, rangeKey].includes(element))
|
|
21
21
|
return value;
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const encodeFn = transcodes[propertyTranscodes[element]].encode;
|
|
23
|
+
const encoded = encodeFn(item[element]) || undefined;
|
|
24
24
|
entityManager.logger.debug('encoded entity element', {
|
|
25
25
|
element,
|
|
26
26
|
item,
|
|
@@ -28,7 +28,7 @@ function encodeGeneratedProperty(entityManager, property, item) {
|
|
|
28
28
|
...(sharded
|
|
29
29
|
? [item[entityManager.config.hashKey]]
|
|
30
30
|
: []),
|
|
31
|
-
...elementMap.map(([element, value]) => [element,
|
|
31
|
+
...elementMap.map(([element, value]) => [element, `${value ?? ''}`].join(entityManager.config.generatedValueDelimiter)),
|
|
32
32
|
].join(entityManager.config.generatedKeyDelimiter);
|
|
33
33
|
entityManager.logger.debug('encoded generated property', {
|
|
34
34
|
property,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { pick } from 'radash';
|
|
2
|
+
import { addKeys } from './addKeys.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Convert an {@link EntityItem | `EntityItem`} into an {@link EntityKey | `EntityKey`}.
|
|
6
|
+
*
|
|
7
|
+
* @param entityManager - {@link EntityManager | `EntityManager`} instance.
|
|
8
|
+
* @param entityToken - {@link Config | `Config`} `entities` key.
|
|
9
|
+
* @param item - {@link EntityItem | `EntityItem`} object.
|
|
10
|
+
* @param overwrite - Overwrite existing properties (default `false`).
|
|
11
|
+
*
|
|
12
|
+
* @returns {@link EntityKey | `EntityKey`} extracted from shallow clone of `item` with updated properties.
|
|
13
|
+
*
|
|
14
|
+
* @throws `Error` if `entityToken` is invalid.
|
|
15
|
+
*/
|
|
16
|
+
function getPrimaryKey(entityManager, entityToken, item, overwrite = false) {
|
|
17
|
+
const { hashKey, rangeKey } = entityManager.config;
|
|
18
|
+
return pick(!overwrite && item[hashKey] && item[rangeKey]
|
|
19
|
+
? item
|
|
20
|
+
: addKeys(entityManager, entityToken, item, overwrite), [entityManager.config.hashKey, entityManager.config.rangeKey]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { getPrimaryKey };
|
|
@@ -45,7 +45,9 @@ function rehydratePageKeyMap(entityManager, entityToken, indexTokens, item, dehy
|
|
|
45
45
|
if (hashKeys.length > 1)
|
|
46
46
|
throw new Error('inconsistent hashKeys');
|
|
47
47
|
const [hashKeyToken] = hashKeys;
|
|
48
|
-
indexTokens.map((index) =>
|
|
48
|
+
indexTokens.map((index) => {
|
|
49
|
+
validateIndexToken(entityManager, index);
|
|
50
|
+
});
|
|
49
51
|
// Shortcut empty dehydrated.
|
|
50
52
|
if (dehydrated && !dehydrated.length)
|
|
51
53
|
return [hashKeyToken, {}];
|
|
@@ -15,14 +15,16 @@ function removeKeys(entityManager, entityToken, item) {
|
|
|
15
15
|
try {
|
|
16
16
|
// Validate params.
|
|
17
17
|
validateEntityToken(entityManager, entityToken);
|
|
18
|
-
//
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
// Build a set of keys to strip (hash, range, and all generated properties).
|
|
19
|
+
const { hashKey, rangeKey, generatedProperties: { sharded, unsharded }, } = entityManager.config;
|
|
20
|
+
const keysToStrip = new Set([
|
|
21
|
+
hashKey,
|
|
22
|
+
rangeKey,
|
|
23
|
+
...Object.keys(sharded),
|
|
24
|
+
...Object.keys(unsharded),
|
|
25
|
+
]);
|
|
26
|
+
// Create a shallow copy of item omitting the keys above (no delete operator).
|
|
27
|
+
const newItem = Object.fromEntries(Object.entries(item).filter(([key]) => !keysToStrip.has(key)));
|
|
26
28
|
entityManager.logger.debug('stripped entity item generated properties', {
|
|
27
29
|
entityToken,
|
|
28
30
|
item,
|
|
@@ -40,12 +40,15 @@ function updateItemHashKey(entityManager, entityToken, item, overwrite = false)
|
|
|
40
40
|
if (chars) {
|
|
41
41
|
// Radix is the numerical base of the shardKey.
|
|
42
42
|
const radix = 2 ** charBits;
|
|
43
|
+
// Compute the full shard space for this bump. Use radix ** chars to ensure
|
|
44
|
+
// all placeholders are utilized (e.g., chars=2, charBits=2 => 16 combos).
|
|
45
|
+
const space = radix ** chars;
|
|
43
46
|
// Get item unique property & validate.
|
|
44
47
|
const uniqueId = item[entityManager.config.entities[entityToken]
|
|
45
48
|
.uniqueProperty];
|
|
46
49
|
if (isNil(uniqueId))
|
|
47
50
|
throw new Error(`missing item unique property`);
|
|
48
|
-
hashKey += (stringHash(uniqueId
|
|
51
|
+
hashKey += (stringHash(uniqueId) % space)
|
|
49
52
|
.toString(radix)
|
|
50
53
|
.padStart(chars, '0');
|
|
51
54
|
}
|
package/dist/mjs/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { BaseEntityClient } from './BaseEntityClient.js';
|
|
2
|
-
export { BaseQueryBuilder } from './BaseQueryBuilder.js';
|
|
3
|
-
export { EntityManager } from './EntityManager.js';
|
|
1
|
+
export { BaseEntityClient } from './BaseEntityClient/BaseEntityClient.js';
|
|
2
|
+
export { BaseQueryBuilder } from './BaseQueryBuilder/BaseQueryBuilder.js';
|
|
3
|
+
export { EntityManager } from './EntityManager/EntityManager.js';
|
|
4
|
+
export { configSchema } from './EntityManager/ParsedConfig.js';
|
package/package.json
CHANGED
|
@@ -5,58 +5,52 @@
|
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@karmaniverous/batch-process": "^0.1.0",
|
|
8
|
-
"@karmaniverous/entity-tools": "^0.6.
|
|
8
|
+
"@karmaniverous/entity-tools": "^0.6.9",
|
|
9
9
|
"@karmaniverous/string-utilities": "^0.2.1",
|
|
10
10
|
"lz-string": "^1.5.0",
|
|
11
|
-
"radash": "^12.1.
|
|
11
|
+
"radash": "^12.1.1",
|
|
12
12
|
"string-hash": "^1.1.3",
|
|
13
|
-
"zod": "^
|
|
13
|
+
"zod": "^4.1.12"
|
|
14
14
|
},
|
|
15
15
|
"description": "Rational indexing & cross-shard querying at scale in your NoSQL database so you can focus on your application logic.",
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@dotenvx/dotenvx": "^1.
|
|
18
|
-
"@eslint/js": "^9.
|
|
19
|
-
"@faker-js/faker": "^
|
|
20
|
-
"@karmaniverous/mock-db": "^0.3.
|
|
21
|
-
"@rollup/plugin-alias": "^
|
|
22
|
-
"@rollup/plugin-commonjs": "^
|
|
17
|
+
"@dotenvx/dotenvx": "^1.51.1",
|
|
18
|
+
"@eslint/js": "^9.39.1",
|
|
19
|
+
"@faker-js/faker": "^10.1.0",
|
|
20
|
+
"@karmaniverous/mock-db": "^0.3.5",
|
|
21
|
+
"@rollup/plugin-alias": "^6.0.0",
|
|
22
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
23
23
|
"@rollup/plugin-json": "^6.1.0",
|
|
24
|
-
"@rollup/plugin-node-resolve": "^
|
|
24
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
25
25
|
"@rollup/plugin-strip": "^3.0.4",
|
|
26
|
-
"@rollup/plugin-typescript": "^12.
|
|
27
|
-
"@types/
|
|
28
|
-
"@types/eslint__js": "^8.42.3",
|
|
29
|
-
"@types/eslint-config-prettier": "^6.11.3",
|
|
30
|
-
"@types/eslint-plugin-mocha": "^10.4.0",
|
|
31
|
-
"@types/mocha": "^10.0.9",
|
|
32
|
-
"@types/node": "^22.9.0",
|
|
26
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
27
|
+
"@types/node": "^24.10.0",
|
|
33
28
|
"@types/string-hash": "^1.1.3",
|
|
34
29
|
"auto-changelog": "^2.5.0",
|
|
35
|
-
"
|
|
36
|
-
"eslint": "^9.
|
|
37
|
-
"eslint-config-prettier": "^
|
|
38
|
-
"eslint-plugin-
|
|
30
|
+
"cross-env": "^10.1.0",
|
|
31
|
+
"eslint": "^9.39.1",
|
|
32
|
+
"eslint-config-prettier": "^10.1.8",
|
|
33
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
39
34
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
40
|
-
"eslint-plugin-tsdoc": "^0.
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"rollup": "^4.26.0",
|
|
50
|
-
"rollup-plugin-dts": "^6.1.1",
|
|
51
|
-
"source-map-support": "^0.5.21",
|
|
52
|
-
"ts-node": "^10.9.2",
|
|
35
|
+
"eslint-plugin-tsdoc": "^0.4.0",
|
|
36
|
+
"knip": "^5.67.1",
|
|
37
|
+
"lefthook": "^2.0.2",
|
|
38
|
+
"prettier": "^3.6.2",
|
|
39
|
+
"release-it": "^19.0.5",
|
|
40
|
+
"rimraf": "^6.1.0",
|
|
41
|
+
"rollup": "^4.52.5",
|
|
42
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
43
|
+
"tsd": "^0.33.0",
|
|
53
44
|
"tslib": "^2.8.1",
|
|
54
|
-
"typedoc": "^0.
|
|
55
|
-
"typedoc-plugin-mdn-links": "^
|
|
56
|
-
"typedoc-plugin-replace-text": "^4.
|
|
57
|
-
"typedoc-plugin-zod": "^1.
|
|
58
|
-
"
|
|
59
|
-
"
|
|
45
|
+
"typedoc": "^0.28.14",
|
|
46
|
+
"typedoc-plugin-mdn-links": "^5.0.10",
|
|
47
|
+
"typedoc-plugin-replace-text": "^4.2.0",
|
|
48
|
+
"typedoc-plugin-zod": "^1.4.3",
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.6",
|
|
50
|
+
"@vitest/eslint-plugin": "^1.4.0",
|
|
51
|
+
"vitest": "^4.0.6",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"typescript-eslint": "^8.46.3"
|
|
60
54
|
},
|
|
61
55
|
"exports": {
|
|
62
56
|
".": {
|
|
@@ -122,15 +116,20 @@
|
|
|
122
116
|
},
|
|
123
117
|
"scripts": {
|
|
124
118
|
"build": "rimraf dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
|
|
119
|
+
"changelog": "auto-changelog",
|
|
125
120
|
"docs": "typedoc",
|
|
126
121
|
"knip": "knip",
|
|
127
|
-
"lint": "eslint
|
|
128
|
-
"lint:fix": "
|
|
122
|
+
"lint": "eslint .",
|
|
123
|
+
"lint:fix": "npm run lint -- --fix .",
|
|
129
124
|
"release": "dotenvx run -f .env.local -- release-it",
|
|
130
|
-
"release:pre": "
|
|
131
|
-
"test": "
|
|
125
|
+
"release:pre": "npm run release -- --no-git.requireBranch --github.prerelease --preRelease",
|
|
126
|
+
"test": "vitest --run --silent",
|
|
127
|
+
"typecheck": "tsc && tsd"
|
|
128
|
+
},
|
|
129
|
+
"tsd": {
|
|
130
|
+
"directory": "test/types"
|
|
132
131
|
},
|
|
133
132
|
"type": "module",
|
|
134
133
|
"types": "dist/index.d.ts",
|
|
135
|
-
"version": "6.
|
|
134
|
+
"version": "6.14.1"
|
|
136
135
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/cjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js}
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/cjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/mjs/{validateGeneratedProperty.js → EntityManager/validateGeneratedProperty.js}
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/mjs/{validateTranscodedProperty.js → EntityManager/validateTranscodedProperty.js}
RENAMED
|
File without changes
|