@karmaniverous/entity-manager 1.0.0 → 2.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.
package/README.md
CHANGED
|
@@ -221,7 +221,7 @@ 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
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
224
|
-
* [.query(entityToken, keyToken, item, shardQuery, [
|
|
224
|
+
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
225
225
|
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
226
226
|
* _inner_
|
|
227
227
|
* [~ShardQueryResult](#module_entity-manager..ShardQueryResult) : <code>object</code>
|
|
@@ -239,7 +239,7 @@ Manage DynamoDb entities.
|
|
|
239
239
|
* [new exports.EntityManager(options)](#new_module_entity-manager.EntityManager_new)
|
|
240
240
|
* [.addKeys(entityToken, item, [overwrite])](#module_entity-manager.EntityManager+addKeys) ⇒ <code>object</code>
|
|
241
241
|
* [.getKeySpace(entityToken, keyToken, item, timestamp)](#module_entity-manager.EntityManager+getKeySpace) ⇒ <code>Array.<string></code>
|
|
242
|
-
* [.query(entityToken, keyToken, item, shardQuery, [
|
|
242
|
+
* [.query(entityToken, keyToken, item, shardQuery, [options])](#module_entity-manager.EntityManager+query) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
243
243
|
* [.removeKeys(entityToken, item)](#module_entity-manager.EntityManager+removeKeys) ⇒ <code>object</code>
|
|
244
244
|
|
|
245
245
|
<a name="new_module_entity-manager.EntityManager_new"></a>
|
|
@@ -303,7 +303,7 @@ Return an array of sharded keys valid for a given entity token & timestamp.
|
|
|
303
303
|
|
|
304
304
|
<a name="module_entity-manager.EntityManager+query"></a>
|
|
305
305
|
|
|
306
|
-
#### entityManager.query(entityToken, keyToken, item, shardQuery, [
|
|
306
|
+
#### entityManager.query(entityToken, keyToken, item, shardQuery, [options]) ⇒ <code>Promise.<ShardedQueryResult></code>
|
|
307
307
|
Query an entity across shards.
|
|
308
308
|
|
|
309
309
|
**Kind**: instance method of [<code>EntityManager</code>](#module_entity-manager.EntityManager)
|
|
@@ -315,7 +315,9 @@ Query an entity across shards.
|
|
|
315
315
|
| keyToken | <code>string</code> | Key token. |
|
|
316
316
|
| item | <code>object</code> | Entity item sufficiently populated to generate property keyToken. |
|
|
317
317
|
| shardQuery | <code>ShardQueryFunction</code> | Sharded query function. |
|
|
318
|
-
| [
|
|
318
|
+
| [options] | <code>object</code> | Options object. |
|
|
319
|
+
| [options.limit] | <code>number</code> | Request limit. |
|
|
320
|
+
| [options.pageKeys] | <code>object</code> | Map of shard page keys. |
|
|
319
321
|
|
|
320
322
|
<a name="module_entity-manager.EntityManager+removeKeys"></a>
|
|
321
323
|
|
|
@@ -357,7 +359,9 @@ Shard query function
|
|
|
357
359
|
| Param | Type | Description |
|
|
358
360
|
| --- | --- | --- |
|
|
359
361
|
| shardedKey | <code>string</code> | Sharded key. |
|
|
360
|
-
| [
|
|
362
|
+
| [options] | <code>object</code> | Options object. |
|
|
363
|
+
| [options.limit] | <code>number</code> | Request limit. |
|
|
364
|
+
| [options.pageKey] | <code>\*</code> | Page key. |
|
|
361
365
|
|
|
362
366
|
<a name="module_entity-manager..ShardedQueryResult"></a>
|
|
363
367
|
|
|
@@ -4,9 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.EntityManager = void 0;
|
|
7
|
-
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
8
7
|
var _map2 = _interopRequireDefault(require("lodash/map"));
|
|
8
|
+
var _size2 = _interopRequireDefault(require("lodash/size"));
|
|
9
|
+
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
|
9
10
|
var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
|
|
11
|
+
var _isPlainObject2 = _interopRequireDefault(require("lodash/isPlainObject"));
|
|
12
|
+
var _isInteger2 = _interopRequireDefault(require("lodash/isInteger"));
|
|
13
|
+
var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));
|
|
14
|
+
var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
|
|
10
15
|
var _sortedUniq2 = _interopRequireDefault(require("lodash/sortedUniq"));
|
|
11
16
|
var _forEach2 = _interopRequireDefault(require("lodash/forEach"));
|
|
12
17
|
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
|
|
@@ -135,7 +140,9 @@ class EntityManager {
|
|
|
135
140
|
*
|
|
136
141
|
* @callback ShardQueryFunction
|
|
137
142
|
* @param {string} shardedKey - Sharded key.
|
|
138
|
-
* @param {
|
|
143
|
+
* @param {object} [options] - Options object.
|
|
144
|
+
* @param {number} [options.limit] - Request limit.
|
|
145
|
+
* @param {*} [options.pageKey] - Page key.
|
|
139
146
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
140
147
|
*/
|
|
141
148
|
|
|
@@ -152,31 +159,50 @@ class EntityManager {
|
|
|
152
159
|
* @param {string} keyToken - Key token.
|
|
153
160
|
* @param {object} item - Entity item sufficiently populated to generate property keyToken.
|
|
154
161
|
* @param {ShardQueryFunction} shardQuery - Sharded query function.
|
|
155
|
-
* @param {object} [
|
|
162
|
+
* @param {object} [options] - Options object.
|
|
163
|
+
* @param {number} [options.limit] - Request limit.
|
|
164
|
+
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
156
165
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
157
166
|
*/
|
|
158
|
-
async query(entityToken, keyToken, item, shardQuery
|
|
167
|
+
async query(entityToken, keyToken, item, shardQuery) {
|
|
168
|
+
let {
|
|
169
|
+
limit,
|
|
170
|
+
pageKeys
|
|
171
|
+
} = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
|
172
|
+
// Validate params.
|
|
173
|
+
_classPrivateFieldGet(this, _entityManager).validateKeyToken(entityToken, keyToken);
|
|
174
|
+
_classPrivateFieldGet(this, _entityManager).validateItem(item);
|
|
175
|
+
if (!(0, _isFunction2.default)(shardQuery)) throw new Error('shardQuery must be a function');
|
|
176
|
+
if (!(0, _isUndefined2.default)(limit) && !(0, _isInteger2.default)(limit)) throw new Error('limit must be an integer');
|
|
177
|
+
if (!(0, _isUndefined2.default)(pageKeys) && !(0, _isPlainObject2.default)(pageKeys)) throw new Error('pageKeys must be an object');
|
|
178
|
+
|
|
159
179
|
// Generate default pageKeys if not provided
|
|
160
180
|
pageKeys ??= (0, _fromPairs2.default)(this.getKeySpace(entityToken, keyToken, item).map(shardedKey => [shardedKey, undefined]));
|
|
161
181
|
|
|
182
|
+
// Return empty result if no pageKeys.
|
|
183
|
+
if ((0, _isEmpty2.default)(pageKeys)) return {
|
|
184
|
+
items: [],
|
|
185
|
+
pageKeys: {}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Calculate shard limit.
|
|
189
|
+
const shardLimit = (0, _isUndefined2.default)(limit) ? undefined : Math.ceil(limit / (0, _size2.default)(pageKeys));
|
|
190
|
+
|
|
162
191
|
// Query every shard in pageKeys.
|
|
163
|
-
const shardQueryResults = await Promise.all((0, _map2.default)(pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey,
|
|
192
|
+
const shardQueryResults = await Promise.all((0, _map2.default)(pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, {
|
|
193
|
+
pageKey,
|
|
194
|
+
limit: shardLimit
|
|
195
|
+
}).then(_ref2 => {
|
|
164
196
|
let {
|
|
165
197
|
items,
|
|
166
198
|
pageKey
|
|
167
199
|
} = _ref2;
|
|
168
|
-
console.log('shardQueryResult', {
|
|
169
|
-
shardedKey,
|
|
170
|
-
items,
|
|
171
|
-
pageKey
|
|
172
|
-
});
|
|
173
200
|
return resolve({
|
|
174
201
|
shardedKey,
|
|
175
202
|
items,
|
|
176
203
|
pageKey
|
|
177
204
|
});
|
|
178
205
|
}))));
|
|
179
|
-
console.log('shardQueryResults', shardQueryResults);
|
|
180
206
|
|
|
181
207
|
// Reduce shardQueryResults into a single result.
|
|
182
208
|
const result = shardQueryResults.reduce((shardedQueryResult, _ref3) => {
|
|
@@ -379,6 +379,22 @@ class PrivateEntityManager {
|
|
|
379
379
|
} else return true;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Tests whether a key token is valid.
|
|
384
|
+
*
|
|
385
|
+
* @param {string} entityToken - Entity token.
|
|
386
|
+
* @param {string} keyToken - Key token.
|
|
387
|
+
* @returns {boolean} true if keyToken is valid.
|
|
388
|
+
*/
|
|
389
|
+
validateKeyToken(entityToken, keyToken) {
|
|
390
|
+
this.validateEntityToken(entityToken);
|
|
391
|
+
if (!this.config.entities[entityToken].keys[keyToken]) {
|
|
392
|
+
const message = `Invalid entity ${entityToken} keyToken: ${keyToken}`;
|
|
393
|
+
this.logger.error(message);
|
|
394
|
+
throw new Error(message);
|
|
395
|
+
} else return true;
|
|
396
|
+
}
|
|
397
|
+
|
|
382
398
|
/**
|
|
383
399
|
* Tests whether an item is valid.
|
|
384
400
|
*
|
|
@@ -130,7 +130,9 @@ export class EntityManager {
|
|
|
130
130
|
*
|
|
131
131
|
* @callback ShardQueryFunction
|
|
132
132
|
* @param {string} shardedKey - Sharded key.
|
|
133
|
-
* @param {
|
|
133
|
+
* @param {object} [options] - Options object.
|
|
134
|
+
* @param {number} [options.limit] - Request limit.
|
|
135
|
+
* @param {*} [options.pageKey] - Page key.
|
|
134
136
|
* @returns {Promise<ShardQueryResult>} Sharded query result.
|
|
135
137
|
*/
|
|
136
138
|
|
|
@@ -147,10 +149,28 @@ export class EntityManager {
|
|
|
147
149
|
* @param {string} keyToken - Key token.
|
|
148
150
|
* @param {object} item - Entity item sufficiently populated to generate property keyToken.
|
|
149
151
|
* @param {ShardQueryFunction} shardQuery - Sharded query function.
|
|
150
|
-
* @param {object} [
|
|
152
|
+
* @param {object} [options] - Options object.
|
|
153
|
+
* @param {number} [options.limit] - Request limit.
|
|
154
|
+
* @param {object} [options.pageKeys] - Map of shard page keys.
|
|
151
155
|
* @returns {Promise<ShardedQueryResult>} Sharded query result.
|
|
152
156
|
*/
|
|
153
|
-
async query(
|
|
157
|
+
async query(
|
|
158
|
+
entityToken,
|
|
159
|
+
keyToken,
|
|
160
|
+
item,
|
|
161
|
+
shardQuery,
|
|
162
|
+
{ limit, pageKeys } = {}
|
|
163
|
+
) {
|
|
164
|
+
// Validate params.
|
|
165
|
+
this.#entityManager.validateKeyToken(entityToken, keyToken);
|
|
166
|
+
this.#entityManager.validateItem(item);
|
|
167
|
+
if (!_.isFunction(shardQuery))
|
|
168
|
+
throw new Error('shardQuery must be a function');
|
|
169
|
+
if (!_.isUndefined(limit) && !_.isInteger(limit))
|
|
170
|
+
throw new Error('limit must be an integer');
|
|
171
|
+
if (!_.isUndefined(pageKeys) && !_.isPlainObject(pageKeys))
|
|
172
|
+
throw new Error('pageKeys must be an object');
|
|
173
|
+
|
|
154
174
|
// Generate default pageKeys if not provided
|
|
155
175
|
pageKeys ??= _.fromPairs(
|
|
156
176
|
this.getKeySpace(entityToken, keyToken, item).map((shardedKey) => [
|
|
@@ -159,22 +179,27 @@ export class EntityManager {
|
|
|
159
179
|
])
|
|
160
180
|
);
|
|
161
181
|
|
|
182
|
+
// Return empty result if no pageKeys.
|
|
183
|
+
if (_.isEmpty(pageKeys)) return { items: [], pageKeys: {} };
|
|
184
|
+
|
|
185
|
+
// Calculate shard limit.
|
|
186
|
+
const shardLimit = _.isUndefined(limit)
|
|
187
|
+
? undefined
|
|
188
|
+
: Math.ceil(limit / _.size(pageKeys));
|
|
189
|
+
|
|
162
190
|
// Query every shard in pageKeys.
|
|
163
191
|
const shardQueryResults = await Promise.all(
|
|
164
192
|
_.map(
|
|
165
193
|
pageKeys,
|
|
166
194
|
(pageKey, shardedKey) =>
|
|
167
195
|
new Promise((resolve) =>
|
|
168
|
-
shardQuery(shardedKey,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
})
|
|
196
|
+
shardQuery(shardedKey, { pageKey, limit: shardLimit }).then(
|
|
197
|
+
({ items, pageKey }) => resolve({ shardedKey, items, pageKey })
|
|
198
|
+
)
|
|
172
199
|
)
|
|
173
200
|
)
|
|
174
201
|
);
|
|
175
202
|
|
|
176
|
-
console.log('shardQueryResults', shardQueryResults);
|
|
177
|
-
|
|
178
203
|
// Reduce shardQueryResults into a single result.
|
|
179
204
|
const result = shardQueryResults.reduce(
|
|
180
205
|
(shardedQueryResult, { shardedKey, items, pageKey }) => ({
|
|
@@ -348,6 +348,23 @@ export class PrivateEntityManager {
|
|
|
348
348
|
} else return true;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Tests whether a key token is valid.
|
|
353
|
+
*
|
|
354
|
+
* @param {string} entityToken - Entity token.
|
|
355
|
+
* @param {string} keyToken - Key token.
|
|
356
|
+
* @returns {boolean} true if keyToken is valid.
|
|
357
|
+
*/
|
|
358
|
+
validateKeyToken(entityToken, keyToken) {
|
|
359
|
+
this.validateEntityToken(entityToken);
|
|
360
|
+
|
|
361
|
+
if (!this.config.entities[entityToken].keys[keyToken]) {
|
|
362
|
+
const message = `Invalid entity ${entityToken} keyToken: ${keyToken}`;
|
|
363
|
+
this.logger.error(message);
|
|
364
|
+
throw new Error(message);
|
|
365
|
+
} else return true;
|
|
366
|
+
}
|
|
367
|
+
|
|
351
368
|
/**
|
|
352
369
|
* Tests whether an item is valid.
|
|
353
370
|
*
|