@karmaniverous/entity-manager 2.1.0 → 2.1.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/README.md
CHANGED
|
@@ -221,10 +221,10 @@ This change can be accomplished with no breaking changes to existing implementat
|
|
|
221
221
|
* [new exports.EntityManager(options)](#new_module_entity-manager.EntityManager_new)
|
|
222
222
|
* [.addKeys(entityToken, item, [overwrite])](#module_entity-manager.EntityManager+addKeys) ⇒ <code>object</code>
|
|
223
223
|
* [.calcShardKey(entityToken, item)](#module_entity-manager.EntityManager+calcShardKey) ⇒ <code>string</code>
|
|
224
|
-
* [.dehydrateIndex(entityToken, indexToken,
|
|
225
|
-
* [.rehydrateIndex(entityToken, indexToken, value, [delimiter])](#module_entity-manager.EntityManager+rehydrateIndex) ⇒ <code>object</code>
|
|
224
|
+
* [.dehydrateIndex(entityToken, indexToken, index, [delimiter])](#module_entity-manager.EntityManager+dehydrateIndex) ⇒ <code>string</code>
|
|
226
225
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
227
226
|
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
227
|
+
* [.rehydrateIndex(entityToken, indexToken, value, [delimiter])](#module_entity-manager.EntityManager+rehydrateIndex) ⇒ <code>object</code>
|
|
228
228
|
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
229
229
|
* _inner_
|
|
230
230
|
* [~ShardQueryResult](#module_entity-manager..ShardQueryResult) : <code>object</code>
|
|
@@ -242,10 +242,10 @@ Manage DynamoDb entities.
|
|
|
242
242
|
* [new exports.EntityManager(options)](#new_module_entity-manager.EntityManager_new)
|
|
243
243
|
* [.addKeys(entityToken, item, [overwrite])](#module_entity-manager.EntityManager+addKeys) ⇒ <code>object</code>
|
|
244
244
|
* [.calcShardKey(entityToken, item)](#module_entity-manager.EntityManager+calcShardKey) ⇒ <code>string</code>
|
|
245
|
-
* [.dehydrateIndex(entityToken, indexToken,
|
|
246
|
-
* [.rehydrateIndex(entityToken, indexToken, value, [delimiter])](#module_entity-manager.EntityManager+rehydrateIndex) ⇒ <code>object</code>
|
|
245
|
+
* [.dehydrateIndex(entityToken, indexToken, index, [delimiter])](#module_entity-manager.EntityManager+dehydrateIndex) ⇒ <code>string</code>
|
|
247
246
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
248
247
|
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
248
|
+
* [.rehydrateIndex(entityToken, indexToken, value, [delimiter])](#module_entity-manager.EntityManager+rehydrateIndex) ⇒ <code>object</code>
|
|
249
249
|
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
250
250
|
|
|
251
251
|
<a name="new_module_entity-manager.EntityManager_new"></a>
|
|
@@ -300,8 +300,8 @@ Calculated the shard key for an entity item.
|
|
|
300
300
|
|
|
301
301
|
<a name="module_entity-manager.EntityManager+dehydrateIndex"></a>
|
|
302
302
|
|
|
303
|
-
#### entityManager.dehydrateIndex(entityToken, indexToken,
|
|
304
|
-
|
|
303
|
+
#### entityManager.dehydrateIndex(entityToken, indexToken, index, [delimiter]) ⇒ <code>string</code>
|
|
304
|
+
Condense an index object into a delimited string.
|
|
305
305
|
|
|
306
306
|
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
307
307
|
**Returns**: <code>string</code> - Dehydrated index.
|
|
@@ -316,27 +316,7 @@ Convert a item into a delimited string containing the properties of a named inde
|
|
|
316
316
|
| --- | --- | --- | --- |
|
|
317
317
|
| entityToken | <code>string</code> | | Entity token. |
|
|
318
318
|
| indexToken | <code>string</code> | | Index token. |
|
|
319
|
-
|
|
|
320
|
-
| [delimiter] | <code>string</code> | <code>"~"</code> | Delimiter. |
|
|
321
|
-
|
|
322
|
-
<a name="module_entity-manager.EntityManager+rehydrateIndex"></a>
|
|
323
|
-
|
|
324
|
-
#### entityManager.rehydrateIndex(entityToken, indexToken, value, [delimiter]) ⇒ <code>object</code>
|
|
325
|
-
Convert a delimited string into a named index key.
|
|
326
|
-
|
|
327
|
-
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
328
|
-
**Returns**: <code>object</code> - Rehydrated index key.
|
|
329
|
-
**Throws**:
|
|
330
|
-
|
|
331
|
-
- <code>Error</code> If entityToken is invalid.
|
|
332
|
-
- <code>Error</code> If indexToken is invalid.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
| Param | Type | Default | Description |
|
|
336
|
-
| --- | --- | --- | --- |
|
|
337
|
-
| entityToken | <code>string</code> | | Entity token. |
|
|
338
|
-
| indexToken | <code>string</code> | | Index token. |
|
|
339
|
-
| value | <code>string</code> | | Dehydrated index value. |
|
|
319
|
+
| index | <code>object</code> | | Index object. |
|
|
340
320
|
| [delimiter] | <code>string</code> | <code>"~"</code> | Delimiter. |
|
|
341
321
|
|
|
342
322
|
<a name="module_entity-manager.EntityManager+getKeySpace"></a>
|
|
@@ -379,6 +359,26 @@ Query an entity across shards.
|
|
|
379
359
|
| [options.limit] | <code>number</code> | Request limit. |
|
|
380
360
|
| [options.pageKeys] | <code>object</code> | Map of shard page keys. |
|
|
381
361
|
|
|
362
|
+
<a name="module_entity-manager.EntityManager+rehydrateIndex"></a>
|
|
363
|
+
|
|
364
|
+
#### entityManager.rehydrateIndex(entityToken, indexToken, value, [delimiter]) ⇒ <code>object</code>
|
|
365
|
+
Convert a delimited string into a named index key.
|
|
366
|
+
|
|
367
|
+
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
368
|
+
**Returns**: <code>object</code> - Rehydrated index key.
|
|
369
|
+
**Throws**:
|
|
370
|
+
|
|
371
|
+
- <code>Error</code> If entityToken is invalid.
|
|
372
|
+
- <code>Error</code> If indexToken is invalid.
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
| Param | Type | Default | Description |
|
|
376
|
+
| --- | --- | --- | --- |
|
|
377
|
+
| entityToken | <code>string</code> | | Entity token. |
|
|
378
|
+
| indexToken | <code>string</code> | | Index token. |
|
|
379
|
+
| value | <code>string</code> | | Dehydrated index value. |
|
|
380
|
+
| [delimiter] | <code>string</code> | <code>"~"</code> | Delimiter. |
|
|
381
|
+
|
|
382
382
|
<a name="module_entity-manager.EntityManager+removeKeys"></a>
|
|
383
383
|
|
|
384
384
|
#### entityManager.removeKeys(entityToken, item) ⇒ <code>object</code>
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.EntityManager = void 0;
|
|
7
|
+
var _zipObject2 = _interopRequireDefault(require("lodash/zipObject"));
|
|
7
8
|
var _map2 = _interopRequireDefault(require("lodash/map"));
|
|
8
9
|
var _size2 = _interopRequireDefault(require("lodash/size"));
|
|
9
10
|
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
|
@@ -11,14 +12,11 @@ var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
|
|
|
11
12
|
var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
|
|
12
13
|
var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
|
|
13
14
|
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
14
|
-
var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
|
|
15
15
|
var _sortedUniq2 = _interopRequireDefault(require("lodash/sortedUniq"));
|
|
16
|
-
var
|
|
17
|
-
var _flatten2 = _interopRequireDefault(require("lodash/flatten"));
|
|
18
|
-
var _uniq2 = _interopRequireDefault(require("lodash/uniq"));
|
|
16
|
+
var _entries2 = _interopRequireDefault(require("lodash/entries"));
|
|
19
17
|
var _sortBy2 = _interopRequireDefault(require("lodash/sortBy"));
|
|
20
|
-
var
|
|
21
|
-
var
|
|
18
|
+
var _sortedUniqBy2 = _interopRequireDefault(require("lodash/sortedUniqBy"));
|
|
19
|
+
var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
|
|
22
20
|
var _forEach2 = _interopRequireDefault(require("lodash/forEach"));
|
|
23
21
|
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
|
|
24
22
|
var _cloneDeep2 = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
@@ -33,7 +31,6 @@ function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _
|
|
|
33
31
|
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
|
|
34
32
|
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
|
|
35
33
|
var _entityManager = /*#__PURE__*/new WeakMap();
|
|
36
|
-
var _getIndexProperties = /*#__PURE__*/new WeakMap();
|
|
37
34
|
/**
|
|
38
35
|
* Manage DynamoDb entities.
|
|
39
36
|
*
|
|
@@ -59,10 +56,6 @@ class EntityManager {
|
|
|
59
56
|
writable: true,
|
|
60
57
|
value: void 0
|
|
61
58
|
});
|
|
62
|
-
_classPrivateFieldInitSpec(this, _getIndexProperties, {
|
|
63
|
-
writable: true,
|
|
64
|
-
value: (entityToken, indexComponents) => (0, _sortBy2.default)((0, _uniq2.default)((0, _flatten2.default)(indexComponents.map(keyToken => (0, _inspectParametersDeclaration.getParametersNames)(_classPrivateFieldGet(this, _entityManager).getKeyGenerator(entityToken, keyToken))))))
|
|
65
|
-
});
|
|
66
59
|
_classPrivateFieldSet(this, _entityManager, new _PrivateEntityManager.PrivateEntityManager({
|
|
67
60
|
config,
|
|
68
61
|
logger
|
|
@@ -103,8 +96,11 @@ class EntityManager {
|
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
// Add keys.
|
|
106
|
-
(0, _forEach2.default)(keys, (
|
|
107
|
-
|
|
99
|
+
(0, _forEach2.default)(keys, (_ref2, key) => {
|
|
100
|
+
let {
|
|
101
|
+
encode
|
|
102
|
+
} = _ref2;
|
|
103
|
+
if (overwrite || (0, _isNil2.default)(newItem[key])) newItem[key] = encode(newItem);
|
|
108
104
|
});
|
|
109
105
|
_classPrivateFieldGet(this, _entityManager).logger.debug('done', newItem);
|
|
110
106
|
|
|
@@ -130,52 +126,42 @@ class EntityManager {
|
|
|
130
126
|
}
|
|
131
127
|
|
|
132
128
|
/**
|
|
133
|
-
*
|
|
129
|
+
* Condense an index object into a delimited string.
|
|
134
130
|
*
|
|
135
131
|
* @param {string} entityToken - Entity token.
|
|
136
132
|
* @param {string} indexToken - Index token.
|
|
137
|
-
* @param {object}
|
|
133
|
+
* @param {object} index - Index object.
|
|
138
134
|
* @param {string} [delimiter] - Delimiter.
|
|
139
135
|
* @returns {string} Dehydrated index.
|
|
140
136
|
* @throws {Error} If entityToken is invalid.
|
|
141
137
|
* @throws {Error} If indexToken is invalid.
|
|
142
138
|
* @throws {Error} If item is invalid.
|
|
143
139
|
*/
|
|
144
|
-
dehydrateIndex(entityToken, indexToken,
|
|
140
|
+
dehydrateIndex(entityToken, indexToken, index) {
|
|
145
141
|
let delimiter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '~';
|
|
146
142
|
// Validate item.
|
|
147
|
-
_classPrivateFieldGet(this, _entityManager).validateItem(
|
|
143
|
+
_classPrivateFieldGet(this, _entityManager).validateItem(index);
|
|
148
144
|
const indexComponents = _classPrivateFieldGet(this, _entityManager).getIndexComponents(entityToken, indexToken);
|
|
149
|
-
const indexProperties =
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
rehydrateIndex(entityToken, indexToken) {
|
|
170
|
-
let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
|
|
171
|
-
let delimiter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '~';
|
|
172
|
-
const indexComponents = _classPrivateFieldGet(this, _entityManager).getIndexComponents(entityToken, indexToken);
|
|
173
|
-
const indexProperties = _classPrivateFieldGet(this, _getIndexProperties).call(this, entityToken, indexComponents);
|
|
174
|
-
const item = (0, _zipObject2.default)(indexProperties, value.split(delimiter));
|
|
175
|
-
return indexComponents.reduce((index, component) => ({
|
|
176
|
-
...index,
|
|
177
|
-
[component]: _classPrivateFieldGet(this, _entityManager).getKeyGenerator(entityToken, component)(item)
|
|
178
|
-
}), {});
|
|
145
|
+
const indexProperties = indexComponents.reduce((properties, component) => {
|
|
146
|
+
const {
|
|
147
|
+
decode
|
|
148
|
+
} = _classPrivateFieldGet(this, _entityManager).getKey(entityToken, component);
|
|
149
|
+
if (!(0, _isFunction2.default)(decode)) throw new Error(`no decode function defined on ${entityToken} entity key '${component}'`);
|
|
150
|
+
return {
|
|
151
|
+
...properties,
|
|
152
|
+
...(decode(index[component])?.groups ?? [])
|
|
153
|
+
};
|
|
154
|
+
}, {});
|
|
155
|
+
return (0, _sortedUniqBy2.default)((0, _sortBy2.default)((0, _entries2.default)(indexProperties), _ref3 => {
|
|
156
|
+
let [key] = _ref3;
|
|
157
|
+
return key;
|
|
158
|
+
}), _ref4 => {
|
|
159
|
+
let [key] = _ref4;
|
|
160
|
+
return key;
|
|
161
|
+
}).map(_ref5 => {
|
|
162
|
+
let [, value] = _ref5;
|
|
163
|
+
return value;
|
|
164
|
+
}).join(delimiter);
|
|
179
165
|
}
|
|
180
166
|
|
|
181
167
|
/**
|
|
@@ -195,7 +181,7 @@ class EntityManager {
|
|
|
195
181
|
let timestamp = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Date.now();
|
|
196
182
|
_classPrivateFieldGet(this, _entityManager).logger.debug(`getting shard key space for ${entityToken} on key '${keyToken}' at timestamp ${timestamp}...`, item);
|
|
197
183
|
const shardKeySpace = _classPrivateFieldGet(this, _entityManager).getShardKeySpace(entityToken, timestamp);
|
|
198
|
-
const result = (0, _sortedUniq2.default)(shardKeySpace.map(shardKey => _classPrivateFieldGet(this, _entityManager).
|
|
184
|
+
const result = (0, _sortedUniq2.default)(shardKeySpace.map(shardKey => _classPrivateFieldGet(this, _entityManager).getKey(entityToken, keyToken).encode({
|
|
199
185
|
...item,
|
|
200
186
|
[_classPrivateFieldGet(this, _entityManager).shardKeyToken]: shardKey
|
|
201
187
|
})));
|
|
@@ -266,11 +252,11 @@ class EntityManager {
|
|
|
266
252
|
const shardQueryResults = await Promise.all((0, _map2.default)(pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, {
|
|
267
253
|
pageKey,
|
|
268
254
|
limit: shardLimit
|
|
269
|
-
}).then(
|
|
255
|
+
}).then(_ref6 => {
|
|
270
256
|
let {
|
|
271
257
|
items,
|
|
272
258
|
pageKey
|
|
273
|
-
} =
|
|
259
|
+
} = _ref6;
|
|
274
260
|
return resolve({
|
|
275
261
|
shardedKey,
|
|
276
262
|
items,
|
|
@@ -279,12 +265,12 @@ class EntityManager {
|
|
|
279
265
|
}))));
|
|
280
266
|
|
|
281
267
|
// Reduce shardQueryResults into a single result.
|
|
282
|
-
const result = shardQueryResults.reduce((shardedQueryResult,
|
|
268
|
+
const result = shardQueryResults.reduce((shardedQueryResult, _ref7) => {
|
|
283
269
|
let {
|
|
284
270
|
shardedKey,
|
|
285
271
|
items,
|
|
286
272
|
pageKey
|
|
287
|
-
} =
|
|
273
|
+
} = _ref7;
|
|
288
274
|
return {
|
|
289
275
|
items: [...shardedQueryResult.items, ...items],
|
|
290
276
|
pageKeys: {
|
|
@@ -301,6 +287,39 @@ class EntityManager {
|
|
|
301
287
|
return result;
|
|
302
288
|
}
|
|
303
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Convert a delimited string into a named index key.
|
|
292
|
+
*
|
|
293
|
+
* @param {string} entityToken - Entity token.
|
|
294
|
+
* @param {string} indexToken - Index token.
|
|
295
|
+
* @param {string} value - Dehydrated index value.
|
|
296
|
+
* @param {string} [delimiter] - Delimiter.
|
|
297
|
+
* @returns {object} Rehydrated index key.
|
|
298
|
+
* @throws {Error} If entityToken is invalid.
|
|
299
|
+
* @throws {Error} If indexToken is invalid.
|
|
300
|
+
*/
|
|
301
|
+
rehydrateIndex(entityToken, indexToken) {
|
|
302
|
+
let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
|
|
303
|
+
let delimiter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '~';
|
|
304
|
+
const indexComponents = _classPrivateFieldGet(this, _entityManager).getIndexComponents(entityToken, indexToken);
|
|
305
|
+
const indexKeys = (0, _sortBy2.default)(indexComponents.reduce((keys, component) => {
|
|
306
|
+
const {
|
|
307
|
+
encode
|
|
308
|
+
} = _classPrivateFieldGet(this, _entityManager).getKey(entityToken, component);
|
|
309
|
+
return [...new Set([...keys, ...(0, _inspectParametersDeclaration.getParametersNames)(encode)]).values()];
|
|
310
|
+
}, []));
|
|
311
|
+
const indexProperies = (0, _zipObject2.default)(indexKeys, value.split(delimiter));
|
|
312
|
+
return indexComponents.reduce((index, component) => {
|
|
313
|
+
const {
|
|
314
|
+
encode
|
|
315
|
+
} = _classPrivateFieldGet(this, _entityManager).getKey(entityToken, component);
|
|
316
|
+
return {
|
|
317
|
+
...index,
|
|
318
|
+
[component]: encode(indexProperies)
|
|
319
|
+
};
|
|
320
|
+
}, {});
|
|
321
|
+
}
|
|
322
|
+
|
|
304
323
|
/**
|
|
305
324
|
* Remove sharded keys from an entity item. Does not mutate original item.
|
|
306
325
|
*
|
|
@@ -12,8 +12,10 @@ var _filter2 = _interopRequireDefault(require("lodash/filter"));
|
|
|
12
12
|
var _findLast2 = _interopRequireDefault(require("lodash/findLast"));
|
|
13
13
|
var _has2 = _interopRequireDefault(require("lodash/has"));
|
|
14
14
|
var _map2 = _interopRequireDefault(require("lodash/map"));
|
|
15
|
-
var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
|
|
16
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"));
|
|
17
19
|
var _keys2 = _interopRequireDefault(require("lodash/keys"));
|
|
18
20
|
var _difference2 = _interopRequireDefault(require("lodash/difference"));
|
|
19
21
|
var _some2 = _interopRequireDefault(require("lodash/some"));
|
|
@@ -102,6 +104,15 @@ const configSchema = {
|
|
|
102
104
|
},
|
|
103
105
|
additionalProperties: false
|
|
104
106
|
};
|
|
107
|
+
const keySchema = {
|
|
108
|
+
type: 'object',
|
|
109
|
+
properties: {
|
|
110
|
+
encode: {},
|
|
111
|
+
decode: {}
|
|
112
|
+
},
|
|
113
|
+
additionalProperties: false,
|
|
114
|
+
required: ['encode']
|
|
115
|
+
};
|
|
105
116
|
|
|
106
117
|
/**
|
|
107
118
|
* Private EntityManager implementation.
|
|
@@ -159,10 +170,7 @@ class PrivateEntityManager {
|
|
|
159
170
|
set config(value) {
|
|
160
171
|
// Validate config against schema.
|
|
161
172
|
const validatorResult = (0, _jsonschema.validate)(value, configSchema);
|
|
162
|
-
if (!validatorResult.valid)
|
|
163
|
-
validatorResult.errors.forEach(error => this.logger.error(error.message));
|
|
164
|
-
throw new Error(validatorResult.errors);
|
|
165
|
-
}
|
|
173
|
+
if (!validatorResult.valid) throw new Error(validatorResult.errors);
|
|
166
174
|
|
|
167
175
|
// Conform config.
|
|
168
176
|
const {
|
|
@@ -197,7 +205,7 @@ class PrivateEntityManager {
|
|
|
197
205
|
shardKeyToken
|
|
198
206
|
};
|
|
199
207
|
|
|
200
|
-
//
|
|
208
|
+
// Conform & validate entity properties.
|
|
201
209
|
(0, _some2.default)(conformedConfig.entities, (_ref2, entityToken) => {
|
|
202
210
|
let {
|
|
203
211
|
indexes,
|
|
@@ -213,69 +221,47 @@ class PrivateEntityManager {
|
|
|
213
221
|
// Validate entity index components are entity keys.
|
|
214
222
|
(0, _some2.default)(indexes, (index, indexToken) => {
|
|
215
223
|
const invalidIndexComponents = (0, _difference2.default)(index, (0, _keys2.default)(keys));
|
|
216
|
-
if (invalidIndexComponents.length) {
|
|
217
|
-
const message = `${entityToken} index '${indexToken}' components '${invalidIndexComponents}' are not entity keys.`;
|
|
218
|
-
this.logger.error(message);
|
|
219
|
-
throw new Error(message);
|
|
220
|
-
} else return false;
|
|
224
|
+
if (invalidIndexComponents.length) throw new Error(`${entityToken} index '${indexToken}' components '${invalidIndexComponents}' are not entity keys.`);else return false;
|
|
221
225
|
});
|
|
222
226
|
|
|
223
|
-
//
|
|
224
|
-
(0,
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
227
|
+
// Conform & validate entity keys.
|
|
228
|
+
(0, _forEach2.default)(keys, (value, key) => {
|
|
229
|
+
keys[key] = (0, _isFunction2.default)(value) ? {
|
|
230
|
+
encode: value
|
|
231
|
+
} : value;
|
|
232
|
+
|
|
233
|
+
// Validate key against schema.
|
|
234
|
+
const validatorResult = (0, _jsonschema.validate)(keys[key], keySchema);
|
|
235
|
+
if (!validatorResult.valid) throw new Error(validatorResult.errors);
|
|
236
|
+
const {
|
|
237
|
+
decode
|
|
238
|
+
} = keys[key];
|
|
239
|
+
if (!(0, _isUndefined2.default)(decode) && !(0, _isFunction2.default)(decode)) throw new Error(`entity ${entityKey} key '${key}' decode must be a function or undefined.`);
|
|
230
240
|
});
|
|
231
241
|
|
|
232
242
|
// Validate sharding bump values increase monotonically with keys.
|
|
233
243
|
(0, _some2.default)((0, _toPairs2.default)(bumps), (_ref3, i, c) => {
|
|
234
244
|
let [bump, value] = _ref3;
|
|
235
245
|
const [lastBump, lastValue] = i ? c[i - 1] : [];
|
|
236
|
-
if (value <= lastValue) {
|
|
237
|
-
const message = `${entityToken} sharding bumps do not monotonically increase from '${lastBump}: ${lastValue}' to '${bump}: ${value}'.)`;
|
|
238
|
-
this.logger.error(message);
|
|
239
|
-
throw new Error(message);
|
|
240
|
-
} else return false;
|
|
246
|
+
if (value <= lastValue) throw new Error(`${entityToken} sharding bumps do not monotonically increase from '${lastBump}: ${lastValue}' to '${bump}: ${value}'.)`);else return false;
|
|
241
247
|
});
|
|
242
248
|
|
|
243
249
|
// Validate sharding entityKey is a function or undefined.
|
|
244
|
-
if (!(0, _isNil2.default)(entityKey) && !(0, _isFunction2.default)(entityKey)) {
|
|
245
|
-
const message = `${entityToken} sharding entityKey must be a function or nil`;
|
|
246
|
-
this.logger.error(message);
|
|
247
|
-
throw new Error(message);
|
|
248
|
-
}
|
|
250
|
+
if (!(0, _isNil2.default)(entityKey) && !(0, _isFunction2.default)(entityKey)) throw new Error(`${entityToken} sharding entityKey must be a function or nil`);
|
|
249
251
|
|
|
250
252
|
// Validate sharding nibbles do not exceed 32 bits.
|
|
251
|
-
if (nibbles * nibbleBits > 32) {
|
|
252
|
-
const message = `${entityToken} nibbles (${nibbles} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`;
|
|
253
|
-
this.logger.error(message);
|
|
254
|
-
throw new Error(message);
|
|
255
|
-
}
|
|
253
|
+
if (nibbles * nibbleBits > 32) throw new Error(`${entityToken} nibbles (${nibbles} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`);
|
|
256
254
|
|
|
257
255
|
// Validate sharding nibbles are less than first bump value.
|
|
258
256
|
const firstBumpValue = (0, _map2.default)(bumps)[0];
|
|
259
|
-
if (nibbles >= firstBumpValue) {
|
|
260
|
-
const message = `${entityToken} nibbles (${nibbles}) not less than minimum bump value (${firstBumpValue})`;
|
|
261
|
-
this.logger.error(message);
|
|
262
|
-
throw new Error(message);
|
|
263
|
-
}
|
|
257
|
+
if (nibbles >= firstBumpValue) throw new Error(`${entityToken} nibbles (${nibbles}) not less than minimum bump value (${firstBumpValue})`);
|
|
264
258
|
|
|
265
259
|
// Validate last bump value does not exceed 32 bits.
|
|
266
260
|
const lastBumpValue = (0, _map2.default)(bumps).slice(-1);
|
|
267
|
-
if (lastBumpValue * nibbleBits > 32) {
|
|
268
|
-
const message = `${entityToken} maximum bump value (${lastBumpValue} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`;
|
|
269
|
-
this.logger.error(message);
|
|
270
|
-
throw new Error(message);
|
|
271
|
-
}
|
|
261
|
+
if (lastBumpValue * nibbleBits > 32) throw new Error(`${entityToken} maximum bump value (${lastBumpValue} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`);
|
|
272
262
|
|
|
273
263
|
// Validate sharding timestamp is a function or undefined.
|
|
274
|
-
if (!(0, _isNil2.default)(timestamp) && !(0, _isFunction2.default)(timestamp)) {
|
|
275
|
-
const message = `${entityToken} sharding timestamp must be a function or nil.`;
|
|
276
|
-
this.logger.error(message);
|
|
277
|
-
throw new Error(message);
|
|
278
|
-
} else return false;
|
|
264
|
+
if (!(0, _isNil2.default)(timestamp) && !(0, _isFunction2.default)(timestamp)) throw new Error(`${entityToken} sharding timestamp must be a function or nil.`);else return false;
|
|
279
265
|
});
|
|
280
266
|
_classPrivateFieldSet(this, _config, conformedConfig);
|
|
281
267
|
}
|
|
@@ -313,22 +299,14 @@ class PrivateEntityManager {
|
|
|
313
299
|
const {
|
|
314
300
|
indexes
|
|
315
301
|
} = this.getEntityConfig(entityToken);
|
|
316
|
-
if (!(0, _has2.default)(indexes, indexToken)) {
|
|
317
|
-
const message = `Index '${indexToken}' does not exist for entity '${entityToken}'.`;
|
|
318
|
-
this.logger.error(message);
|
|
319
|
-
throw new Error(message);
|
|
320
|
-
}
|
|
302
|
+
if (!(0, _has2.default)(indexes, indexToken)) throw new Error(`Index '${indexToken}' does not exist for entity '${entityToken}'.`);
|
|
321
303
|
return indexes[indexToken];
|
|
322
304
|
}
|
|
323
|
-
|
|
305
|
+
getKey(entityToken, keyToken) {
|
|
324
306
|
const {
|
|
325
307
|
keys
|
|
326
308
|
} = this.getEntityConfig(entityToken);
|
|
327
|
-
if (!(0, _has2.default)(keys, keyToken)) {
|
|
328
|
-
const message = `Key '${keyToken}' does not exist for entity '${entityToken}'.`;
|
|
329
|
-
this.logger.error(message);
|
|
330
|
-
throw new Error(message);
|
|
331
|
-
}
|
|
309
|
+
if (!(0, _has2.default)(keys, keyToken)) throw new Error(`Key '${keyToken}' does not exist for entity '${entityToken}'.`);
|
|
332
310
|
return keys[keyToken];
|
|
333
311
|
}
|
|
334
312
|
|
|
@@ -408,11 +386,17 @@ class PrivateEntityManager {
|
|
|
408
386
|
* @returns {boolean} true if entityToken is valid.
|
|
409
387
|
*/
|
|
410
388
|
validateEntityToken(entityToken) {
|
|
411
|
-
if (!this.config.entities[entityToken]) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
389
|
+
if (!this.config.entities[entityToken]) throw new Error(`Invalid entityToken: ${entityToken}`);else return true;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Tests whether an item is valid.
|
|
394
|
+
*
|
|
395
|
+
* @param {string} item - Entity token.
|
|
396
|
+
* @returns {boolean} true if entityToken is valid.
|
|
397
|
+
*/
|
|
398
|
+
validateItem(item) {
|
|
399
|
+
if (!(0, _isPlainObject2.default)(item)) throw new Error(`Invalid item: ${item}`);else return true;
|
|
416
400
|
}
|
|
417
401
|
|
|
418
402
|
/**
|
|
@@ -424,25 +408,7 @@ class PrivateEntityManager {
|
|
|
424
408
|
*/
|
|
425
409
|
validateKeyToken(entityToken, keyToken) {
|
|
426
410
|
this.validateEntityToken(entityToken);
|
|
427
|
-
if (!this.config.entities[entityToken].keys[keyToken]) {
|
|
428
|
-
const message = `Invalid entity ${entityToken} keyToken: ${keyToken}`;
|
|
429
|
-
this.logger.error(message);
|
|
430
|
-
throw new Error(message);
|
|
431
|
-
} else return true;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Tests whether an item is valid.
|
|
436
|
-
*
|
|
437
|
-
* @param {string} item - Entity token.
|
|
438
|
-
* @returns {boolean} true if entityToken is valid.
|
|
439
|
-
*/
|
|
440
|
-
validateItem(item) {
|
|
441
|
-
if (!(0, _isPlainObject2.default)(item)) {
|
|
442
|
-
const message = `Invalid item: ${item}`;
|
|
443
|
-
this.logger.error(message);
|
|
444
|
-
throw new Error(message);
|
|
445
|
-
} else return true;
|
|
411
|
+
if (!this.config.entities[entityToken].keys[keyToken]) throw new Error(`Invalid entity ${entityToken} keyToken: ${keyToken}`);else return true;
|
|
446
412
|
}
|
|
447
413
|
|
|
448
414
|
/**
|
|
@@ -63,8 +63,8 @@ export class EntityManager {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Add keys.
|
|
66
|
-
_.forEach(keys, (
|
|
67
|
-
if (overwrite || _.isNil(newItem[key])) newItem[key] =
|
|
66
|
+
_.forEach(keys, ({ encode }, key) => {
|
|
67
|
+
if (overwrite || _.isNil(newItem[key])) newItem[key] = encode(newItem);
|
|
68
68
|
});
|
|
69
69
|
this.#entityManager.logger.debug('done', newItem);
|
|
70
70
|
|
|
@@ -90,90 +90,42 @@ export class EntityManager {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* Condense an index object into a delimited string.
|
|
94
94
|
*
|
|
95
95
|
* @param {string} entityToken - Entity token.
|
|
96
96
|
* @param {string} indexToken - Index token.
|
|
97
|
-
* @param {object}
|
|
97
|
+
* @param {object} index - Index object.
|
|
98
98
|
* @param {string} [delimiter] - Delimiter.
|
|
99
99
|
* @returns {string} Dehydrated index.
|
|
100
100
|
* @throws {Error} If entityToken is invalid.
|
|
101
101
|
* @throws {Error} If indexToken is invalid.
|
|
102
102
|
* @throws {Error} If item is invalid.
|
|
103
103
|
*/
|
|
104
|
-
dehydrateIndex(entityToken, indexToken,
|
|
104
|
+
dehydrateIndex(entityToken, indexToken, index, delimiter = '~') {
|
|
105
105
|
// Validate item.
|
|
106
|
-
this.#entityManager.validateItem(
|
|
107
|
-
|
|
108
|
-
const indexComponents = this.#entityManager.getIndexComponents(
|
|
109
|
-
entityToken,
|
|
110
|
-
indexToken
|
|
111
|
-
);
|
|
106
|
+
this.#entityManager.validateItem(index);
|
|
112
107
|
|
|
113
|
-
const indexProperties = this.#getIndexProperties(
|
|
114
|
-
entityToken,
|
|
115
|
-
indexComponents
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
const { shardKeyToken } = this.#entityManager;
|
|
119
|
-
return _.values(
|
|
120
|
-
_.pick(
|
|
121
|
-
{
|
|
122
|
-
...item,
|
|
123
|
-
[shardKeyToken]: this.calcShardKey(entityToken, item),
|
|
124
|
-
},
|
|
125
|
-
indexProperties
|
|
126
|
-
)
|
|
127
|
-
).join(delimiter);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
#getIndexProperties = (entityToken, indexComponents) =>
|
|
131
|
-
_.sortBy(
|
|
132
|
-
_.uniq(
|
|
133
|
-
_.flatten(
|
|
134
|
-
indexComponents.map((keyToken) =>
|
|
135
|
-
getParametersNames(
|
|
136
|
-
this.#entityManager.getKeyGenerator(entityToken, keyToken)
|
|
137
|
-
)
|
|
138
|
-
)
|
|
139
|
-
)
|
|
140
|
-
)
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Convert a delimited string into a named index key.
|
|
145
|
-
*
|
|
146
|
-
* @param {string} entityToken - Entity token.
|
|
147
|
-
* @param {string} indexToken - Index token.
|
|
148
|
-
* @param {string} value - Dehydrated index value.
|
|
149
|
-
* @param {string} [delimiter] - Delimiter.
|
|
150
|
-
* @returns {object} Rehydrated index key.
|
|
151
|
-
* @throws {Error} If entityToken is invalid.
|
|
152
|
-
* @throws {Error} If indexToken is invalid.
|
|
153
|
-
*/
|
|
154
|
-
rehydrateIndex(entityToken, indexToken, value = '', delimiter = '~') {
|
|
155
108
|
const indexComponents = this.#entityManager.getIndexComponents(
|
|
156
109
|
entityToken,
|
|
157
110
|
indexToken
|
|
158
111
|
);
|
|
159
112
|
|
|
160
|
-
const indexProperties =
|
|
161
|
-
entityToken,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
);
|
|
113
|
+
const indexProperties = indexComponents.reduce((properties, component) => {
|
|
114
|
+
const { decode } = this.#entityManager.getKey(entityToken, component);
|
|
115
|
+
if (!_.isFunction(decode))
|
|
116
|
+
throw new Error(
|
|
117
|
+
`no decode function defined on ${entityToken} entity key '${component}'`
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return { ...properties, ...(decode(index[component])?.groups ?? []) };
|
|
121
|
+
}, {});
|
|
122
|
+
|
|
123
|
+
return _.sortedUniqBy(
|
|
124
|
+
_.sortBy(_.entries(indexProperties), ([key]) => key),
|
|
125
|
+
([key]) => key
|
|
126
|
+
)
|
|
127
|
+
.map(([, value]) => value)
|
|
128
|
+
.join(delimiter);
|
|
177
129
|
}
|
|
178
130
|
|
|
179
131
|
/**
|
|
@@ -202,10 +154,7 @@ export class EntityManager {
|
|
|
202
154
|
|
|
203
155
|
const result = _.sortedUniq(
|
|
204
156
|
shardKeySpace.map((shardKey) =>
|
|
205
|
-
this.#entityManager.
|
|
206
|
-
entityToken,
|
|
207
|
-
keyToken
|
|
208
|
-
)({
|
|
157
|
+
this.#entityManager.getKey(entityToken, keyToken).encode({
|
|
209
158
|
...item,
|
|
210
159
|
[this.#entityManager.shardKeyToken]: shardKey,
|
|
211
160
|
})
|
|
@@ -312,6 +261,38 @@ export class EntityManager {
|
|
|
312
261
|
return result;
|
|
313
262
|
}
|
|
314
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Convert a delimited string into a named index key.
|
|
266
|
+
*
|
|
267
|
+
* @param {string} entityToken - Entity token.
|
|
268
|
+
* @param {string} indexToken - Index token.
|
|
269
|
+
* @param {string} value - Dehydrated index value.
|
|
270
|
+
* @param {string} [delimiter] - Delimiter.
|
|
271
|
+
* @returns {object} Rehydrated index key.
|
|
272
|
+
* @throws {Error} If entityToken is invalid.
|
|
273
|
+
* @throws {Error} If indexToken is invalid.
|
|
274
|
+
*/
|
|
275
|
+
rehydrateIndex(entityToken, indexToken, value = '', delimiter = '~') {
|
|
276
|
+
const indexComponents = this.#entityManager.getIndexComponents(
|
|
277
|
+
entityToken,
|
|
278
|
+
indexToken
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const indexKeys = _.sortBy(
|
|
282
|
+
indexComponents.reduce((keys, component) => {
|
|
283
|
+
const { encode } = this.#entityManager.getKey(entityToken, component);
|
|
284
|
+
return [...new Set([...keys, ...getParametersNames(encode)]).values()];
|
|
285
|
+
}, [])
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const indexProperies = _.zipObject(indexKeys, value.split(delimiter));
|
|
289
|
+
|
|
290
|
+
return indexComponents.reduce((index, component) => {
|
|
291
|
+
const { encode } = this.#entityManager.getKey(entityToken, component);
|
|
292
|
+
return { ...index, [component]: encode(indexProperies) };
|
|
293
|
+
}, {});
|
|
294
|
+
}
|
|
295
|
+
|
|
315
296
|
/**
|
|
316
297
|
* Remove sharded keys from an entity item. Does not mutate original item.
|
|
317
298
|
*
|
|
@@ -67,6 +67,16 @@ const configSchema = {
|
|
|
67
67
|
additionalProperties: false,
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
const keySchema = {
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: {
|
|
73
|
+
encode: {},
|
|
74
|
+
decode: {},
|
|
75
|
+
},
|
|
76
|
+
additionalProperties: false,
|
|
77
|
+
required: ['encode'],
|
|
78
|
+
};
|
|
79
|
+
|
|
70
80
|
/**
|
|
71
81
|
* Private EntityManager implementation.
|
|
72
82
|
*
|
|
@@ -114,12 +124,7 @@ export class PrivateEntityManager {
|
|
|
114
124
|
set config(value) {
|
|
115
125
|
// Validate config against schema.
|
|
116
126
|
const validatorResult = validate(value, configSchema);
|
|
117
|
-
if (!validatorResult.valid)
|
|
118
|
-
validatorResult.errors.forEach((error) =>
|
|
119
|
-
this.logger.error(error.message)
|
|
120
|
-
);
|
|
121
|
-
throw new Error(validatorResult.errors);
|
|
122
|
-
}
|
|
127
|
+
if (!validatorResult.valid) throw new Error(validatorResult.errors);
|
|
123
128
|
|
|
124
129
|
// Conform config.
|
|
125
130
|
const { entities = {}, shardKeyToken = 'shardId' } = value;
|
|
@@ -151,7 +156,7 @@ export class PrivateEntityManager {
|
|
|
151
156
|
shardKeyToken,
|
|
152
157
|
};
|
|
153
158
|
|
|
154
|
-
//
|
|
159
|
+
// Conform & validate entity properties.
|
|
155
160
|
_.some(
|
|
156
161
|
conformedConfig.entities,
|
|
157
162
|
(
|
|
@@ -165,68 +170,70 @@ export class PrivateEntityManager {
|
|
|
165
170
|
// Validate entity index components are entity keys.
|
|
166
171
|
_.some(indexes, (index, indexToken) => {
|
|
167
172
|
const invalidIndexComponents = _.difference(index, _.keys(keys));
|
|
168
|
-
if (invalidIndexComponents.length)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
if (invalidIndexComponents.length)
|
|
174
|
+
throw new Error(
|
|
175
|
+
`${entityToken} index '${indexToken}' components '${invalidIndexComponents}' are not entity keys.`
|
|
176
|
+
);
|
|
177
|
+
else return false;
|
|
173
178
|
});
|
|
174
179
|
|
|
175
|
-
//
|
|
176
|
-
_.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
// Conform & validate entity keys.
|
|
181
|
+
_.forEach(keys, (value, key) => {
|
|
182
|
+
keys[key] = _.isFunction(value) ? { encode: value } : value;
|
|
183
|
+
|
|
184
|
+
// Validate key against schema.
|
|
185
|
+
const validatorResult = validate(keys[key], keySchema);
|
|
186
|
+
if (!validatorResult.valid) throw new Error(validatorResult.errors);
|
|
187
|
+
|
|
188
|
+
const { decode } = keys[key];
|
|
189
|
+
if (!_.isUndefined(decode) && !_.isFunction(decode))
|
|
190
|
+
throw new Error(
|
|
191
|
+
`entity ${entityKey} key '${key}' decode must be a function or undefined.`
|
|
192
|
+
);
|
|
182
193
|
});
|
|
183
194
|
|
|
184
195
|
// Validate sharding bump values increase monotonically with keys.
|
|
185
196
|
_.some(_.toPairs(bumps), ([bump, value], i, c) => {
|
|
186
197
|
const [lastBump, lastValue] = i ? c[i - 1] : [];
|
|
187
|
-
if (value <= lastValue)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
198
|
+
if (value <= lastValue)
|
|
199
|
+
throw new Error(
|
|
200
|
+
`${entityToken} sharding bumps do not monotonically increase from '${lastBump}: ${lastValue}' to '${bump}: ${value}'.)`
|
|
201
|
+
);
|
|
202
|
+
else return false;
|
|
192
203
|
});
|
|
193
204
|
|
|
194
205
|
// Validate sharding entityKey is a function or undefined.
|
|
195
|
-
if (!_.isNil(entityKey) && !_.isFunction(entityKey))
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
206
|
+
if (!_.isNil(entityKey) && !_.isFunction(entityKey))
|
|
207
|
+
throw new Error(
|
|
208
|
+
`${entityToken} sharding entityKey must be a function or nil`
|
|
209
|
+
);
|
|
200
210
|
|
|
201
211
|
// Validate sharding nibbles do not exceed 32 bits.
|
|
202
|
-
if (nibbles * nibbleBits > 32)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
212
|
+
if (nibbles * nibbleBits > 32)
|
|
213
|
+
throw new Error(
|
|
214
|
+
`${entityToken} nibbles (${nibbles} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`
|
|
215
|
+
);
|
|
207
216
|
|
|
208
217
|
// Validate sharding nibbles are less than first bump value.
|
|
209
218
|
const firstBumpValue = _.map(bumps)[0];
|
|
210
|
-
if (nibbles >= firstBumpValue)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
219
|
+
if (nibbles >= firstBumpValue)
|
|
220
|
+
throw new Error(
|
|
221
|
+
`${entityToken} nibbles (${nibbles}) not less than minimum bump value (${firstBumpValue})`
|
|
222
|
+
);
|
|
215
223
|
|
|
216
224
|
// Validate last bump value does not exceed 32 bits.
|
|
217
225
|
const lastBumpValue = _.map(bumps).slice(-1);
|
|
218
|
-
if (lastBumpValue * nibbleBits > 32)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
226
|
+
if (lastBumpValue * nibbleBits > 32)
|
|
227
|
+
throw new Error(
|
|
228
|
+
`${entityToken} maximum bump value (${lastBumpValue} nibbles at ${nibbleBits} nibbleBits) exceed 32 bits`
|
|
229
|
+
);
|
|
223
230
|
|
|
224
231
|
// Validate sharding timestamp is a function or undefined.
|
|
225
|
-
if (!_.isNil(timestamp) && !_.isFunction(timestamp))
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
if (!_.isNil(timestamp) && !_.isFunction(timestamp))
|
|
233
|
+
throw new Error(
|
|
234
|
+
`${entityToken} sharding timestamp must be a function or nil.`
|
|
235
|
+
);
|
|
236
|
+
else return false;
|
|
230
237
|
}
|
|
231
238
|
);
|
|
232
239
|
|
|
@@ -266,23 +273,21 @@ export class PrivateEntityManager {
|
|
|
266
273
|
getIndexComponents(entityToken, indexToken) {
|
|
267
274
|
const { indexes } = this.getEntityConfig(entityToken);
|
|
268
275
|
|
|
269
|
-
if (!_.has(indexes, indexToken))
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
276
|
+
if (!_.has(indexes, indexToken))
|
|
277
|
+
throw new Error(
|
|
278
|
+
`Index '${indexToken}' does not exist for entity '${entityToken}'.`
|
|
279
|
+
);
|
|
274
280
|
|
|
275
281
|
return indexes[indexToken];
|
|
276
282
|
}
|
|
277
283
|
|
|
278
|
-
|
|
284
|
+
getKey(entityToken, keyToken) {
|
|
279
285
|
const { keys } = this.getEntityConfig(entityToken);
|
|
280
286
|
|
|
281
|
-
if (!_.has(keys, keyToken))
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
287
|
+
if (!_.has(keys, keyToken))
|
|
288
|
+
throw new Error(
|
|
289
|
+
`Key '${keyToken}' does not exist for entity '${entityToken}'.`
|
|
290
|
+
);
|
|
286
291
|
|
|
287
292
|
return keys[keyToken];
|
|
288
293
|
}
|
|
@@ -376,11 +381,20 @@ export class PrivateEntityManager {
|
|
|
376
381
|
* @returns {boolean} true if entityToken is valid.
|
|
377
382
|
*/
|
|
378
383
|
validateEntityToken(entityToken) {
|
|
379
|
-
if (!this.config.entities[entityToken])
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
+
if (!this.config.entities[entityToken])
|
|
385
|
+
throw new Error(`Invalid entityToken: ${entityToken}`);
|
|
386
|
+
else return true;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Tests whether an item is valid.
|
|
391
|
+
*
|
|
392
|
+
* @param {string} item - Entity token.
|
|
393
|
+
* @returns {boolean} true if entityToken is valid.
|
|
394
|
+
*/
|
|
395
|
+
validateItem(item) {
|
|
396
|
+
if (!_.isPlainObject(item)) throw new Error(`Invalid item: ${item}`);
|
|
397
|
+
else return true;
|
|
384
398
|
}
|
|
385
399
|
|
|
386
400
|
/**
|
|
@@ -393,25 +407,9 @@ export class PrivateEntityManager {
|
|
|
393
407
|
validateKeyToken(entityToken, keyToken) {
|
|
394
408
|
this.validateEntityToken(entityToken);
|
|
395
409
|
|
|
396
|
-
if (!this.config.entities[entityToken].keys[keyToken])
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
throw new Error(message);
|
|
400
|
-
} else return true;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Tests whether an item is valid.
|
|
405
|
-
*
|
|
406
|
-
* @param {string} item - Entity token.
|
|
407
|
-
* @returns {boolean} true if entityToken is valid.
|
|
408
|
-
*/
|
|
409
|
-
validateItem(item) {
|
|
410
|
-
if (!_.isPlainObject(item)) {
|
|
411
|
-
const message = `Invalid item: ${item}`;
|
|
412
|
-
this.logger.error(message);
|
|
413
|
-
throw new Error(message);
|
|
414
|
-
} else return true;
|
|
410
|
+
if (!this.config.entities[entityToken].keys[keyToken])
|
|
411
|
+
throw new Error(`Invalid entity ${entityToken} keyToken: ${keyToken}`);
|
|
412
|
+
else return true;
|
|
415
413
|
}
|
|
416
414
|
|
|
417
415
|
/**
|