@acodeninja/persist 3.0.0-next.24 → 3.0.0-next.25
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/package.json +1 -1
- package/src/Connection.js +43 -37
- package/src/data/Model.js +1 -0
package/package.json
CHANGED
package/src/Connection.js
CHANGED
@@ -42,11 +42,11 @@ export default class Connection {
|
|
42
42
|
* @return {Promise<Model>}
|
43
43
|
*/
|
44
44
|
async get(modelId) {
|
45
|
-
const
|
45
|
+
const modelConstructor = this.#getModelConstructorFromId(modelId);
|
46
46
|
|
47
47
|
const data = await this.#storage.getModel(modelId);
|
48
48
|
|
49
|
-
return
|
49
|
+
return modelConstructor.fromData(data);
|
50
50
|
}
|
51
51
|
|
52
52
|
/**
|
@@ -157,33 +157,37 @@ export default class Connection {
|
|
157
157
|
throw new ModelNotRegisteredConnectionError(modelToProcess, this.#storage);
|
158
158
|
|
159
159
|
modelToProcess.validate();
|
160
|
-
|
160
|
+
|
161
|
+
const modelToProcessConstructor = this.#getModelConstructorFromId(modelToProcess.id);
|
162
|
+
const currentModel = await this.hydrate(modelToProcess).catch(() => null);
|
161
163
|
|
162
164
|
const modelToProcessHasChanged = !_.isEqual(currentModel?.toData() || {}, modelToProcess.toData());
|
163
165
|
|
164
166
|
if (modelToProcessHasChanged) modelsToPut.push(modelToProcess);
|
165
167
|
|
166
|
-
const
|
168
|
+
const modelToProcessConstructorName = modelToProcessConstructor.name;
|
167
169
|
|
168
170
|
if (
|
169
171
|
Boolean(modelToProcess.constructor.indexedProperties().length) &&
|
170
172
|
(!currentModel || !_.isEqual(currentModel.toIndexData(), modelToProcess.toIndexData()))
|
171
173
|
) {
|
172
|
-
modelsToReindex[
|
173
|
-
modelsToReindex[
|
174
|
+
modelsToReindex[modelToProcessConstructorName] = modelsToReindex[modelToProcessConstructorName] || [];
|
175
|
+
modelsToReindex[modelToProcessConstructorName].push(modelToProcess);
|
174
176
|
}
|
175
177
|
|
176
178
|
if (
|
177
179
|
Boolean(modelToProcess.constructor.searchProperties().length) &&
|
178
180
|
(!currentModel || !_.isEqual(currentModel.toSearchData(), modelToProcess.toSearchData()))
|
179
181
|
) {
|
180
|
-
modelsToReindexSearch[
|
181
|
-
modelsToReindexSearch[
|
182
|
+
modelsToReindexSearch[modelToProcessConstructorName] = modelsToReindexSearch[modelToProcessConstructorName] || [];
|
183
|
+
modelsToReindexSearch[modelToProcessConstructorName].push(modelToProcess);
|
182
184
|
}
|
183
185
|
|
184
|
-
for (const [
|
185
|
-
if (Model.isModel(
|
186
|
-
await processModel(
|
186
|
+
for (const [_name, property] of Object.entries(modelToProcess)) {
|
187
|
+
if (Model.isModel(property)) {
|
188
|
+
await processModel(property);
|
189
|
+
} else if (Array.isArray(property) && Model.isModel(property[0])) {
|
190
|
+
await Promise.all(property.map(processModel));
|
187
191
|
}
|
188
192
|
}
|
189
193
|
};
|
@@ -251,25 +255,23 @@ export default class Connection {
|
|
251
255
|
|
252
256
|
if (!modelsToDelete.includes(currentModel.id)) modelsToDelete.push(currentModel.id);
|
253
257
|
|
254
|
-
const modelToProcessConstructor = this.#getModelConstructorFromId(modelToProcess.id)
|
258
|
+
const modelToProcessConstructor = this.#getModelConstructorFromId(modelToProcess.id);
|
255
259
|
|
256
|
-
indexActions[modelToProcessConstructor] = indexActions[modelToProcessConstructor] ?? [];
|
257
|
-
searchIndexActions[modelToProcessConstructor] = searchIndexActions[modelToProcessConstructor] ?? [];
|
260
|
+
indexActions[modelToProcessConstructor.name] = indexActions[modelToProcessConstructor.name] ?? [];
|
261
|
+
searchIndexActions[modelToProcessConstructor.name] = searchIndexActions[modelToProcessConstructor.name] ?? [];
|
258
262
|
|
259
|
-
|
260
|
-
indexActions[modelToProcessConstructor].push(['delete', modelToProcess]);
|
261
|
-
}
|
263
|
+
indexActions[modelToProcessConstructor.name].push(['delete', modelToProcess]);
|
262
264
|
|
263
265
|
if (currentModel.constructor.searchProperties().length) {
|
264
|
-
searchIndexActions[modelToProcessConstructor].push(['delete', modelToProcess]);
|
266
|
+
searchIndexActions[modelToProcessConstructor.name].push(['delete', modelToProcess]);
|
265
267
|
}
|
266
268
|
|
267
269
|
const linkedModels = await this.#getInstancesLinkedTo(modelToProcess, indexCache);
|
268
270
|
const links = this.#getLinksFor(modelToProcess.constructor);
|
269
271
|
Object.values(Object.fromEntries(await Promise.all(
|
270
272
|
Object.entries(linkedModels)
|
271
|
-
.map(async ([
|
272
|
-
|
273
|
+
.map(async ([modelConstructor, updatableModels]) => [
|
274
|
+
modelConstructor,
|
273
275
|
await Promise.all(updatableModels.map(async m => {
|
274
276
|
const upToDateModel = modelCache[m.id] ?? await this.get(m.id);
|
275
277
|
modelCache[upToDateModel.id] = upToDateModel;
|
@@ -289,13 +291,16 @@ export default class Connection {
|
|
289
291
|
if (!modelsToDelete.includes(m.id)) modelsToDelete.push(m.id);
|
290
292
|
modelsToProcess.push(m);
|
291
293
|
} else {
|
294
|
+
const modelConstructor = this.#getModelConstructorFromId(m.id);
|
292
295
|
m[linkName] = undefined;
|
293
296
|
modelsToPut.push(m);
|
294
297
|
|
295
|
-
indexActions[
|
298
|
+
indexActions[modelConstructor.name] = indexActions[modelConstructor.name] ?? [];
|
299
|
+
indexActions[modelConstructor.name].push(['reindex', m]);
|
296
300
|
|
297
301
|
if (m.constructor.searchProperties().length) {
|
298
|
-
searchIndexActions[
|
302
|
+
searchIndexActions[modelConstructor.name] = searchIndexActions[modelConstructor.name] ?? [];
|
303
|
+
searchIndexActions[modelConstructor.name].push(['reindex', m]);
|
299
304
|
}
|
300
305
|
}
|
301
306
|
}),
|
@@ -309,6 +314,7 @@ export default class Connection {
|
|
309
314
|
await processModel(model);
|
310
315
|
|
311
316
|
const unrequestedDeletions = modelsToDelete.filter(m => !propagateTo.includes(m));
|
317
|
+
|
312
318
|
if (unrequestedDeletions.length) {
|
313
319
|
throw new DeleteHasUnintendedConsequencesStorageEngineError(model.id, {
|
314
320
|
willDelete: unrequestedDeletions,
|
@@ -351,8 +357,8 @@ export default class Connection {
|
|
351
357
|
]);
|
352
358
|
|
353
359
|
await Promise.all([
|
354
|
-
Promise.all(modelsToDelete.map(m => this.#storage.deleteModel(m))),
|
355
360
|
Promise.all(modelsToPut.map(m => this.#storage.putModel(m.toData()))),
|
361
|
+
Promise.all(modelsToDelete.map(m => this.#storage.deleteModel(m))),
|
356
362
|
Promise.all(
|
357
363
|
Object.entries(indexCache)
|
358
364
|
.map(([constructorName, index]) => this.#storage.putIndex(this.#models[constructorName], index)),
|
@@ -377,13 +383,13 @@ export default class Connection {
|
|
377
383
|
* Must include: '+foo bar' must include 'foo' and may include 'bar'
|
378
384
|
* Must not include: '-foo bar' must not include 'foo' and may include 'bar'
|
379
385
|
* Mixed include: '+foo -bar' must include 'foo' must not include 'bar'
|
380
|
-
* @param {Model.constructor}
|
386
|
+
* @param {Model.constructor} modelConstructor
|
381
387
|
* @param {string} query
|
382
388
|
* @return {Promise<Array<SearchResult>>}
|
383
389
|
*/
|
384
|
-
async search(
|
385
|
-
const searchIndex = await this.#storage.getSearchIndex(
|
386
|
-
.then(index => new SearchIndex(
|
390
|
+
async search(modelConstructor, query) {
|
391
|
+
const searchIndex = await this.#storage.getSearchIndex(modelConstructor)
|
392
|
+
.then(index => new SearchIndex(modelConstructor, index));
|
387
393
|
|
388
394
|
return searchIndex.search(query);
|
389
395
|
}
|
@@ -391,13 +397,13 @@ export default class Connection {
|
|
391
397
|
/**
|
392
398
|
* Find using a structured query and indexed fields.
|
393
399
|
*
|
394
|
-
* @param {Model.constructor}
|
400
|
+
* @param {Model.constructor} modelConstructor
|
395
401
|
* @param {Object} query
|
396
402
|
* @return {Promise<Array<SearchResult>>}
|
397
403
|
*/
|
398
|
-
async find(
|
399
|
-
const findIndex = await this.#storage.getIndex(
|
400
|
-
.then(index => new FindIndex(
|
404
|
+
async find(modelConstructor, query) {
|
405
|
+
const findIndex = await this.#storage.getIndex(modelConstructor)
|
406
|
+
.then(index => new FindIndex(modelConstructor, index));
|
401
407
|
|
402
408
|
return findIndex.query(query);
|
403
409
|
}
|
@@ -467,11 +473,11 @@ export default class Connection {
|
|
467
473
|
*/
|
468
474
|
#getModelConstructorFromId(modelId) {
|
469
475
|
const modelName = modelId.split('/')[0];
|
470
|
-
const
|
476
|
+
const modelConstructor = this.#models[modelName];
|
471
477
|
|
472
|
-
if (!
|
478
|
+
if (!modelConstructor) throw new ModelNotRegisteredConnectionError(modelName, this.#storage);
|
473
479
|
|
474
|
-
return
|
480
|
+
return modelConstructor;
|
475
481
|
}
|
476
482
|
|
477
483
|
/**
|
@@ -577,11 +583,11 @@ export class MissingArgumentsConnectionError extends ConnectionError {
|
|
577
583
|
*/
|
578
584
|
export class ModelNotRegisteredConnectionError extends ConnectionError {
|
579
585
|
/**
|
580
|
-
* @param {Model|String}
|
586
|
+
* @param {Model|String} modelConstructor
|
581
587
|
* @param {Connection} connection
|
582
588
|
*/
|
583
|
-
constructor(
|
584
|
-
const modelName = typeof
|
589
|
+
constructor(modelConstructor, connection) {
|
590
|
+
const modelName = typeof modelConstructor === 'string' ? modelConstructor : modelConstructor.constructor.name;
|
585
591
|
super(`The model ${modelName} is not registered in the storage engine ${connection.constructor.name}`);
|
586
592
|
}
|
587
593
|
}
|
package/src/data/Model.js
CHANGED
@@ -199,6 +199,7 @@ class Model {
|
|
199
199
|
.filter(([_name, type]) => !type._type && !this.isModel(type) && !type._items?._type && (this.isModel(type._items) || this.isModel(type()._items)))
|
200
200
|
.map(([name, _type]) => `${name}.[*].id`),
|
201
201
|
...this.indexedProperties(),
|
202
|
+
'id',
|
202
203
|
];
|
203
204
|
}
|
204
205
|
|