@karmaniverous/entity-manager 5.0.8 → 6.0.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.
Files changed (83) hide show
  1. package/README.md +15 -439
  2. package/dist/cjs/_virtual/_commonjsHelpers.js +7 -0
  3. package/dist/cjs/_virtual/lz-string.js +5 -0
  4. package/dist/cjs/node_modules/@karmaniverous/entity-tools/dist/mjs/Nil.js +14 -0
  5. package/dist/cjs/node_modules/@karmaniverous/entity-tools/dist/mjs/defaultTranscodes.js +94 -0
  6. package/dist/cjs/node_modules/@karmaniverous/entity-tools/dist/mjs/sort.js +52 -0
  7. package/dist/cjs/node_modules/lz-string/libs/lz-string.js +517 -0
  8. package/dist/cjs/node_modules/radash/dist/esm/array.js +90 -0
  9. package/dist/cjs/node_modules/radash/dist/esm/async.js +62 -0
  10. package/dist/cjs/node_modules/radash/dist/esm/object.js +25 -0
  11. package/dist/cjs/node_modules/radash/dist/esm/typed.js +35 -0
  12. package/dist/cjs/node_modules/string-hash/index.js +23 -0
  13. package/dist/cjs/node_modules/tslib/tslib.es6.js +39 -0
  14. package/dist/cjs/node_modules/zod/lib/index.js +4342 -0
  15. package/dist/cjs/src/EntityManager.js +93 -0
  16. package/dist/cjs/src/ParsedConfig.js +227 -0
  17. package/dist/cjs/src/addKeys.js +47 -0
  18. package/dist/cjs/src/decodeEntityElement.js +37 -0
  19. package/dist/cjs/src/decodeGeneratedProperty.js +48 -0
  20. package/dist/cjs/src/dehydrateIndexItem.js +52 -0
  21. package/dist/cjs/src/dehydratePageKeyMap.js +75 -0
  22. package/dist/cjs/src/encodeEntityElement.js +36 -0
  23. package/dist/cjs/src/encodeGeneratedProperty.js +44 -0
  24. package/dist/cjs/src/getHashKeySpace.js +41 -0
  25. package/dist/cjs/src/getShardBump.js +24 -0
  26. package/dist/cjs/src/index.js +7 -0
  27. package/dist/cjs/src/query.js +104 -0
  28. package/dist/cjs/src/rehydrateIndexItem.js +48 -0
  29. package/dist/cjs/src/rehydratePageKeyMap.js +66 -0
  30. package/dist/cjs/src/removeKeys.js +33 -0
  31. package/dist/cjs/src/unwrapIndex.js +40 -0
  32. package/dist/cjs/src/updateItemHashKey.js +55 -0
  33. package/dist/cjs/src/updateItemRangeKey.js +45 -0
  34. package/dist/cjs/src/validateEntityGeneratedProperty.js +29 -0
  35. package/dist/cjs/src/validateEntityIndexToken.js +22 -0
  36. package/dist/cjs/src/validateEntityToken.js +17 -0
  37. package/dist/index.d.cts +826 -0
  38. package/dist/index.d.mts +826 -0
  39. package/dist/index.d.ts +826 -0
  40. package/dist/mjs/_virtual/_commonjsHelpers.js +5 -0
  41. package/dist/mjs/_virtual/lz-string.js +3 -0
  42. package/dist/mjs/node_modules/@karmaniverous/entity-tools/dist/mjs/Nil.js +12 -0
  43. package/dist/mjs/node_modules/@karmaniverous/entity-tools/dist/mjs/defaultTranscodes.js +92 -0
  44. package/dist/mjs/node_modules/@karmaniverous/entity-tools/dist/mjs/sort.js +50 -0
  45. package/dist/mjs/node_modules/lz-string/libs/lz-string.js +515 -0
  46. package/dist/mjs/node_modules/radash/dist/esm/array.js +80 -0
  47. package/dist/mjs/node_modules/radash/dist/esm/async.js +58 -0
  48. package/dist/mjs/node_modules/radash/dist/esm/object.js +22 -0
  49. package/dist/mjs/node_modules/radash/dist/esm/typed.js +28 -0
  50. package/dist/mjs/node_modules/string-hash/index.js +21 -0
  51. package/dist/mjs/node_modules/tslib/tslib.es6.js +36 -0
  52. package/dist/mjs/node_modules/zod/lib/index.js +4233 -0
  53. package/dist/mjs/src/EntityManager.js +91 -0
  54. package/dist/mjs/src/ParsedConfig.js +225 -0
  55. package/dist/mjs/src/addKeys.js +45 -0
  56. package/dist/mjs/src/decodeEntityElement.js +35 -0
  57. package/dist/mjs/src/decodeGeneratedProperty.js +46 -0
  58. package/dist/mjs/src/dehydrateIndexItem.js +50 -0
  59. package/dist/mjs/src/dehydratePageKeyMap.js +73 -0
  60. package/dist/mjs/src/encodeEntityElement.js +34 -0
  61. package/dist/mjs/src/encodeGeneratedProperty.js +42 -0
  62. package/dist/mjs/src/getHashKeySpace.js +39 -0
  63. package/dist/mjs/src/getShardBump.js +22 -0
  64. package/dist/mjs/src/index.js +1 -0
  65. package/dist/mjs/src/query.js +102 -0
  66. package/dist/mjs/src/rehydrateIndexItem.js +46 -0
  67. package/dist/mjs/src/rehydratePageKeyMap.js +64 -0
  68. package/dist/mjs/src/removeKeys.js +31 -0
  69. package/dist/mjs/src/unwrapIndex.js +38 -0
  70. package/dist/mjs/src/updateItemHashKey.js +53 -0
  71. package/dist/mjs/src/updateItemRangeKey.js +43 -0
  72. package/dist/mjs/src/validateEntityGeneratedProperty.js +27 -0
  73. package/dist/mjs/src/validateEntityIndexToken.js +20 -0
  74. package/dist/mjs/src/validateEntityToken.js +15 -0
  75. package/package.json +108 -59
  76. package/.env +0 -1
  77. package/dist/default/lib/EntityManager/EntityManager.js +0 -423
  78. package/dist/default/lib/EntityManager/PrivateEntityManager.js +0 -421
  79. package/dist/default/lib/index.js +0 -12
  80. package/dist/package.json +0 -3
  81. package/lib/EntityManager/EntityManager.js +0 -396
  82. package/lib/EntityManager/PrivateEntityManager.js +0 -436
  83. package/lib/index.js +0 -1
@@ -1,421 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.PrivateEntityManager = exports.DEFAULT_PAGE_SIZE = exports.DEFAULT_LIMIT = void 0;
7
- var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
8
- var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
9
- var _range2 = _interopRequireDefault(require("lodash/range"));
10
- var _flatten2 = _interopRequireDefault(require("lodash/flatten"));
11
- var _filter2 = _interopRequireDefault(require("lodash/filter"));
12
- var _findLast2 = _interopRequireDefault(require("lodash/findLast"));
13
- var _has2 = _interopRequireDefault(require("lodash/has"));
14
- var _map2 = _interopRequireDefault(require("lodash/map"));
15
- var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
16
- var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
17
- var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
18
- var _forEach2 = _interopRequireDefault(require("lodash/forEach"));
19
- var _keys2 = _interopRequireDefault(require("lodash/keys"));
20
- var _difference2 = _interopRequireDefault(require("lodash/difference"));
21
- var _some2 = _interopRequireDefault(require("lodash/some"));
22
- var _toPairs2 = _interopRequireDefault(require("lodash/toPairs"));
23
- var _sortBy2 = _interopRequireDefault(require("lodash/sortBy"));
24
- var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
25
- var _mapValues2 = _interopRequireDefault(require("lodash/mapValues"));
26
- var _jsonschema = require("jsonschema");
27
- var _stringHash = _interopRequireDefault(require("string-hash"));
28
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
29
- const DEFAULT_LIMIT = exports.DEFAULT_LIMIT = 10;
30
- const DEFAULT_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = 10;
31
-
32
- /**
33
- * EntityManager config validation schema.
34
- *
35
- * @private
36
- */
37
- const configSchema = {
38
- type: 'object',
39
- properties: {
40
- entities: {
41
- type: 'object',
42
- patternProperties: {
43
- '^\\w+$': {
44
- type: 'object',
45
- properties: {
46
- defaultLimit: {
47
- type: 'integer'
48
- },
49
- defaultPageSize: {
50
- type: 'integer'
51
- },
52
- indexes: {
53
- type: 'object',
54
- additionalProperties: {
55
- type: 'array',
56
- items: {
57
- type: 'string'
58
- },
59
- minItems: 1
60
- }
61
- },
62
- keys: {
63
- type: 'object'
64
- },
65
- sharding: {
66
- type: 'object',
67
- properties: {
68
- bumps: {
69
- type: 'object',
70
- patternProperties: {
71
- '^\\d+$': {
72
- type: 'integer',
73
- minimum: 0
74
- }
75
- },
76
- additionalProperties: false
77
- },
78
- entityKey: {
79
- type: 'function'
80
- },
81
- nibbleBits: {
82
- type: 'integer',
83
- minimum: 1,
84
- maximum: 5
85
- },
86
- nibbles: {
87
- type: 'integer',
88
- minimum: 0
89
- },
90
- timestamp: {
91
- type: 'function'
92
- }
93
- },
94
- additionalProperties: false
95
- }
96
- },
97
- additionalProperties: false
98
- }
99
- },
100
- additionalProperties: false
101
- },
102
- shardKeyToken: {
103
- type: 'string',
104
- pattern: '^\\w+$'
105
- }
106
- },
107
- additionalProperties: false
108
- };
109
- const keySchema = {
110
- type: 'object',
111
- properties: {
112
- encode: {},
113
- decode: {},
114
- retain: {
115
- type: 'boolean'
116
- }
117
- },
118
- additionalProperties: false,
119
- required: ['encode']
120
- };
121
-
122
- /**
123
- * Private EntityManager implementation.
124
- *
125
- * @private
126
- */
127
- class PrivateEntityManager {
128
- #config;
129
- #logger;
130
-
131
- /**
132
- * Create a PrivateEntityManager instance.
133
- *
134
- * @param {object} options - Options object.
135
- * @param {object} [options.config] - EntityManager configuration object.
136
- * @param {object} [options.logger] - Logger instance (defaults to console, must support error & debug methods).
137
- * @throws {Error} If config is invalid.
138
- * @throws {Error} If logger is invalid.
139
- */
140
- constructor() {
141
- let {
142
- config = {},
143
- logger = console
144
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
145
- // Validate logger.
146
- if (!logger.error || !logger.debug) throw new Error('logger must implement error & debug methods.');
147
- this.#logger = logger;
148
- this.config = config;
149
- }
150
-
151
- /**
152
- * Get the current config.
153
- *
154
- * @returns {object} Current config.
155
- */
156
- get config() {
157
- return this.#config;
158
- }
159
-
160
- /**
161
- * Set the current config.
162
- *
163
- * @param {object} value - Config object.
164
- * @throws {Error} If config is invalid.
165
- * @throws {Error} If entity bumps do not monotonically increase.
166
- * @throws {Error} If entity nibbles are greater than minimum bump value.
167
- */
168
- set config(value) {
169
- // Validate config against schema.
170
- const validatorResult = (0, _jsonschema.validate)(value, configSchema);
171
- if (!validatorResult.valid) throw new Error(validatorResult.errors);
172
-
173
- // Conform config.
174
- const {
175
- entities = {},
176
- shardKeyToken = 'shardId'
177
- } = value;
178
- const conformedConfig = {
179
- entities: (0, _mapValues2.default)(entities, _ref => {
180
- let {
181
- defaultLimit = DEFAULT_LIMIT,
182
- defaultPageSize = DEFAULT_PAGE_SIZE,
183
- indexes = {},
184
- keys = {},
185
- sharding: {
186
- bumps = {},
187
- entityKey,
188
- nibbleBits = 1,
189
- nibbles = 0,
190
- timestamp
191
- } = {}
192
- } = _ref;
193
- return {
194
- defaultLimit,
195
- defaultPageSize,
196
- indexes,
197
- keys,
198
- sharding: {
199
- bumps: (0, _fromPairs2.default)((0, _sortBy2.default)((0, _toPairs2.default)(bumps), 0)),
200
- entityKey,
201
- nibbleBits,
202
- nibbles,
203
- timestamp
204
- }
205
- };
206
- }),
207
- shardKeyToken
208
- };
209
-
210
- // Conform & validate entity properties.
211
- (0, _some2.default)(conformedConfig.entities, (_ref2, entityToken) => {
212
- let {
213
- indexes,
214
- keys,
215
- sharding: {
216
- bumps,
217
- entityKey,
218
- nibbleBits,
219
- nibbles,
220
- timestamp
221
- }
222
- } = _ref2;
223
- // Validate entity index components are entity keys.
224
- (0, _some2.default)(indexes, (index, indexToken) => {
225
- const invalidIndexComponents = (0, _difference2.default)(index, (0, _keys2.default)(keys));
226
- if (invalidIndexComponents.length) throw new Error(`${entityToken} index '${indexToken}' components '${invalidIndexComponents}' are not entity keys.`);else return false;
227
- });
228
-
229
- // Conform & validate entity keys.
230
- (0, _forEach2.default)(keys, (value, key) => {
231
- keys[key] = (0, _isFunction2.default)(value) ? {
232
- encode: value
233
- } : value;
234
-
235
- // Validate key against schema.
236
- const validatorResult = (0, _jsonschema.validate)(keys[key], keySchema);
237
- if (!validatorResult.valid) throw new Error(validatorResult.errors);
238
- const {
239
- decode
240
- } = keys[key];
241
- if (!(0, _isUndefined2.default)(decode) && !(0, _isFunction2.default)(decode)) throw new Error(`entity ${entityKey} key '${key}' decode must be a function or undefined.`);
242
- });
243
-
244
- // Validate sharding bump values increase monotonically with keys.
245
- (0, _some2.default)((0, _toPairs2.default)(bumps), (_ref3, i, c) => {
246
- let [bump, value] = _ref3;
247
- const [lastBump, lastValue] = i ? c[i - 1] : [];
248
- if (value <= lastValue) throw new Error(`${entityToken} sharding bumps do not monotonically increase from '${lastBump}: ${lastValue}' to '${bump}: ${value}'.)`);else return false;
249
- });
250
-
251
- // Validate sharding entityKey is a function or undefined.
252
- if (!(0, _isNil2.default)(entityKey) && !(0, _isFunction2.default)(entityKey)) throw new Error(`${entityToken} sharding entityKey must be a function or nil`);
253
-
254
- // Validate sharding nibbles do not exceed 32 bits.
255
- if (nibbles * nibbleBits > 32) throw new Error(`${entityToken} nibbles (${nibbles} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`);
256
-
257
- // Validate sharding nibbles are less than first bump value.
258
- const firstBumpValue = (0, _map2.default)(bumps)[0];
259
- if (nibbles >= firstBumpValue) throw new Error(`${entityToken} nibbles (${nibbles}) not less than minimum bump value (${firstBumpValue})`);
260
-
261
- // Validate last bump value does not exceed 32 bits.
262
- const lastBumpValue = (0, _map2.default)(bumps).slice(-1);
263
- if (lastBumpValue * nibbleBits > 32) throw new Error(`${entityToken} maximum bump value (${lastBumpValue} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`);
264
-
265
- // Validate sharding timestamp is a function or undefined.
266
- if (!(0, _isNil2.default)(timestamp) && !(0, _isFunction2.default)(timestamp)) throw new Error(`${entityToken} sharding timestamp must be a function or nil.`);else return false;
267
- });
268
- this.#config = conformedConfig;
269
- }
270
-
271
- /**
272
- * Get logger instance.
273
- *
274
- * @returns {object} Logger instance.
275
- */
276
- get logger() {
277
- return this.#logger;
278
- }
279
-
280
- /**
281
- * Get shard key token.
282
- *
283
- * @returns {string} Shard key token.
284
- */
285
- get shardKeyToken() {
286
- return this.#config.shardKeyToken;
287
- }
288
-
289
- /**
290
- * Get entity config.
291
- *
292
- * @param {string} entityToken - Entity token.
293
- * @returns {object} Entity config.
294
- * @throws {Error} If entityToken is invalid.
295
- */
296
- getEntityConfig(entityToken) {
297
- this.validateEntityToken(entityToken);
298
- return this.config.entities[entityToken];
299
- }
300
- getIndexComponents(entityToken, indexToken) {
301
- const {
302
- indexes
303
- } = this.getEntityConfig(entityToken);
304
- if (!(0, _has2.default)(indexes, indexToken)) throw new Error(`Index '${indexToken}' does not exist for entity '${entityToken}'.`);
305
- return indexes[indexToken];
306
- }
307
-
308
- /**
309
- * Get the number of nibbles & nibbleBits for a given entityToken at a given timestamp.
310
- *
311
- * @param {string} entityToken - Entity token.
312
- * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
313
- * @returns {{nibbleBits: number, nibbles: number}} Result object.
314
- */
315
- getNibbles(entityToken) {
316
- let timestamp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now();
317
- const {
318
- nibbleBits,
319
- nibbles,
320
- bumps
321
- } = this.getEntityConfig(entityToken).sharding;
322
- this.validateTimestamp(timestamp);
323
- return {
324
- nibbleBits,
325
- nibbles: (0, _findLast2.default)(bumps, (value, key) => key <= timestamp) ?? nibbles
326
- };
327
- }
328
-
329
- /**
330
- * Return a shard key for a given entity token, entity id & timestamp.
331
- *
332
- * @param {string} entityToken - Entity token.
333
- * @param {string} entityKey - Entity id.
334
- * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
335
- * @returns {string} shard key.
336
- */
337
- getShardKey(entityToken, entityKey) {
338
- let timestamp = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Date.now();
339
- // Get nibbles for entityToken at timestamp (validates entityToken)
340
- const {
341
- nibbleBits,
342
- nibbles
343
- } = this.getNibbles(entityToken, timestamp);
344
-
345
- // Calculate shardKey.
346
- const radix = 2 ** nibbleBits;
347
- const shardKey = nibbles ? ((0, _stringHash.default)(entityKey) % (nibbles * radix)).toString(radix).padStart(nibbles, '0') : undefined;
348
- if ((0, _isNil2.default)(shardKey)) this.logger.debug(`no shard key generated for ${entityToken} id '${entityKey}' at timestamp ${timestamp}.`);else this.logger.debug(`generated shard key '${shardKey}' for ${entityToken} id '${entityKey}' at timestamp ${timestamp}.`);
349
- return shardKey;
350
- }
351
-
352
- /**
353
- * Return an array of shard keys valid for a given entity token & timestamp.
354
- *
355
- * @param {string} entityToken - Entity token.
356
- * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
357
- * @returns {string[]} shard key space.
358
- */
359
- getShardKeySpace(entityToken) {
360
- let timestamp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now();
361
- const {
362
- nibbleBits,
363
- nibbles,
364
- bumps
365
- } = this.getEntityConfig(entityToken).sharding;
366
- // if (!nibbles && !_.size(bumps)) return [''];
367
-
368
- this.validateTimestamp(timestamp);
369
- const nibbleSpace = [nibbles, ...(0, _map2.default)((0, _filter2.default)(bumps, (value, key) => key <= timestamp))];
370
- const radix = 2 ** nibbleBits;
371
- const shardKeySpace = (0, _flatten2.default)((0, _map2.default)(nibbleSpace, nibbles => {
372
- return nibbles ? (0, _range2.default)(0, radix ** nibbles).map(nibble => nibble.toString(radix).padStart(nibbles, '0')) : undefined;
373
- }));
374
- return shardKeySpace;
375
- }
376
-
377
- /**
378
- * Tests whether an entityToken is valid.
379
- *
380
- * @param {string} entityToken - Entity token.
381
- * @returns {boolean} true if entityToken is valid.
382
- */
383
- validateEntityToken(entityToken) {
384
- if (!this.config.entities[entityToken]) throw new Error(`Invalid entityToken: ${entityToken}`);else return true;
385
- }
386
-
387
- /**
388
- * Tests whether an item is valid.
389
- *
390
- * @param {string} item - Entity token.
391
- * @returns {boolean} true if entityToken is valid.
392
- */
393
- validateItem(item) {
394
- if (!(0, _isPlainObject2.default)(item)) throw new Error(`Invalid item: ${item}`);else return true;
395
- }
396
-
397
- /**
398
- * Tests whether a key token is valid.
399
- *
400
- * @param {string} entityToken - Entity token.
401
- * @param {string} keyToken - Key token.
402
- * @returns {boolean} true if keyToken is valid.
403
- */
404
- validateKeyToken(entityToken, keyToken) {
405
- this.validateEntityToken(entityToken);
406
- if (!this.config.entities[entityToken].keys[keyToken]) throw new Error(`Invalid entity ${entityToken} keyToken: ${keyToken}`);else return true;
407
- }
408
-
409
- /**
410
- * Tests whether a timestamp is valid.
411
- *
412
- * @param {number} timestamp - timestamp.
413
- * @param {boolean} [future] - true if timestamp must be in the future.
414
- * @returns {boolean} true if timestamp is valid.
415
- */
416
- validateTimestamp(timestamp) {
417
- let future = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
418
- if (!(0, _isInteger2.default)(timestamp) || future && timestamp <= Date.now()) throw new Error(`invalid timestamp (must be an integer${future ? ' in the future' : ''})`);else return true;
419
- }
420
- }
421
- exports.PrivateEntityManager = PrivateEntityManager;
@@ -1,12 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "EntityManager", {
7
- enumerable: true,
8
- get: function () {
9
- return _EntityManager.EntityManager;
10
- }
11
- });
12
- var _EntityManager = require("./EntityManager/EntityManager.js");
package/dist/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }