@acodeninja/persist 3.0.0-next.2 → 3.0.0-next.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acodeninja/persist",
3
- "version": "3.0.0-next.2",
3
+ "version": "3.0.0-next.3",
4
4
  "description": "A JSON based data modelling and persistence module with alternate storage mechanisms.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -20,34 +20,46 @@ export default class StorageEngine {
20
20
  const processedModels = [];
21
21
  const modelsToPut = [];
22
22
  const modelsToReindex = {};
23
+ const modelsToReindexSearch = {};
23
24
 
24
25
  /**
25
26
  * @param {Type.Model} modelToProcess
26
27
  * @return {Promise<void>}
27
28
  */
28
29
  const processModel = async (modelToProcess) => {
29
- if (processedModels.includes(modelToProcess.id)) return;
30
+ if (processedModels.includes(modelToProcess.id))
31
+ return;
30
32
 
31
33
  processedModels.push(modelToProcess.id);
32
34
 
33
- if (!Object.keys(this.models).includes(modelToProcess.constructor.name)) throw new ModelNotRegisteredStorageEngineError(modelToProcess, this);
35
+ if (!Object.keys(this.models).includes(modelToProcess.constructor.name))
36
+ throw new ModelNotRegisteredStorageEngineError(modelToProcess, this);
34
37
 
35
38
  modelToProcess.validate();
36
39
  const currentModel = await this.get(modelToProcess.id).catch(() => null);
37
40
 
38
- const modelToProcessHasChanged = (JSON.stringify(currentModel?.toData() || {}) !== JSON.stringify(modelToProcess.toData()));
41
+ const modelToProcessHasChanged = JSON.stringify(currentModel?.toData() || {}) !== JSON.stringify(modelToProcess.toData());
39
42
 
40
43
  if (modelToProcessHasChanged) modelsToPut.push(modelToProcess);
41
44
 
42
45
  if (
43
46
  Boolean(modelToProcess.constructor.indexedProperties().length) &&
44
- this._indexedFieldsHaveChanged(currentModel, modelToProcess)
47
+ indexedFieldsHaveChanged(currentModel, modelToProcess)
45
48
  ) {
46
49
  const modelToProcessConstructor = this.getModelConstructorFromId(modelToProcess.id);
47
50
  modelsToReindex[modelToProcessConstructor] = modelsToReindex[modelToProcessConstructor] || [];
48
51
  modelsToReindex[modelToProcessConstructor].push(modelToProcess);
49
52
  }
50
53
 
54
+ if (
55
+ Boolean(modelToProcess.constructor.searchProperties().length) &&
56
+ searchableFieldsHaveChanged(currentModel, modelToProcess)
57
+ ) {
58
+ const modelToProcessConstructor = this.getModelConstructorFromId(modelToProcess.id);
59
+ modelsToReindexSearch[modelToProcessConstructor] = modelsToReindexSearch[modelToProcessConstructor] || [];
60
+ modelsToReindexSearch[modelToProcessConstructor].push(modelToProcess);
61
+ }
62
+
51
63
  for (const [field, value] of Object.entries(modelToProcess)) {
52
64
  if (Type.Model.isModel(value)) {
53
65
  await processModel(modelToProcess[field]);
@@ -57,31 +69,27 @@ export default class StorageEngine {
57
69
 
58
70
  await processModel(model);
59
71
 
60
- await Promise.all(modelsToPut.map(m => this._putModel(m.toData())));
61
- await Promise.all(Object.entries(modelsToReindex).map(async ([constructor, models]) => {
62
- const modelConstructor = this.models[constructor];
63
- const index = await this._getIndex(modelConstructor);
72
+ await Promise.all([
73
+ Promise.all(modelsToPut.map(m => this._putModel(m.toData()))),
74
+ Promise.all(Object.entries(modelsToReindex).map(async ([constructorName, models]) => {
75
+ const modelConstructor = this.models[constructorName];
76
+ const index = await this._getIndex(modelConstructor);
64
77
 
65
- await this._putIndex(modelConstructor, {
66
- ...index || {},
67
- ...Object.fromEntries(models.map(m => [m.id, m.toIndexData()])),
68
- });
69
- }));
70
- }
78
+ await this._putIndex(modelConstructor, {
79
+ ...index || {},
80
+ ...Object.fromEntries(models.map(m => [m.id, m.toIndexData()])),
81
+ });
82
+ })),
83
+ Promise.all(Object.entries(modelsToReindexSearch).map(async ([constructorName, models]) => {
84
+ const modelConstructor = this.models[constructorName];
85
+ const index = await this._getSearchIndex(modelConstructor);
71
86
 
72
- /**
73
- * Decide if two models indexable fields have changed
74
- * @param {Type.Model} currentModel
75
- * @param {Type.Model} modelToProcess
76
- * @return {boolean}
77
- * @private
78
- */
79
- _indexedFieldsHaveChanged(currentModel, modelToProcess) {
80
- return !currentModel || Boolean(
81
- modelToProcess.constructor.indexedProperties()
82
- .filter(field => JSON.stringify(_.get(currentModel, field)) !== JSON.stringify(_.get(modelToProcess, field)))
83
- .length,
84
- );
87
+ await this._putSearchIndex(modelConstructor, {
88
+ ...index || {},
89
+ ...Object.fromEntries(models.map(m => [m.id, m.toIndexData()])),
90
+ });
91
+ })),
92
+ ]);
85
93
  }
86
94
 
87
95
  /**
@@ -198,6 +206,67 @@ export default class StorageEngine {
198
206
  _putIndex(_modelConstructor, _data) {
199
207
  return Promise.reject(new MethodNotImplementedStorageEngineError('_putIndex', this));
200
208
  }
209
+
210
+ /**
211
+ * Get a model's raw search index data
212
+ * @param {Model.constructor} _modelConstructor
213
+ * @throws MethodNotImplementedStorageEngineError
214
+ * @return Promise<void>
215
+ */
216
+ _getSearchIndex(_modelConstructor) {
217
+ return Promise.reject(new MethodNotImplementedStorageEngineError('_getSearchIndex', this));
218
+ }
219
+
220
+ /**
221
+ * Get a model's raw search index data
222
+ * @param {Model.constructor} _modelConstructor
223
+ * @throws MethodNotImplementedStorageEngineError
224
+ * @return Promise<void>
225
+ */
226
+ _getSearchIndexCompiled(_modelConstructor) {
227
+ return Promise.reject(new MethodNotImplementedStorageEngineError('_getSearchIndexCompiled', this));
228
+ }
229
+
230
+ /**
231
+ * Put a model's raw and compiled search index data
232
+ * @param {Model.constructor} _modelConstructor
233
+ * @param {object} _data
234
+ * @throws MethodNotImplementedStorageEngineError
235
+ * @return Promise<void>
236
+ */
237
+ _putSearchIndex(_modelConstructor, _data) {
238
+ return Promise.reject(new MethodNotImplementedStorageEngineError('_putSearchIndex', this));
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Decide if two models indexable fields have changed
244
+ * @param {Type.Model} currentModel
245
+ * @param {Type.Model} modelToProcess
246
+ * @return {boolean}
247
+ * @private
248
+ */
249
+ function indexedFieldsHaveChanged(currentModel, modelToProcess) {
250
+ return !currentModel || Boolean(
251
+ modelToProcess.constructor.indexedProperties()
252
+ .filter(field => JSON.stringify(_.get(currentModel, field)) !== JSON.stringify(_.get(modelToProcess, field)))
253
+ .length,
254
+ );
255
+ }
256
+
257
+ /**
258
+ * Decide if two models searchable fields have changed
259
+ * @param {Type.Model} currentModel
260
+ * @param {Type.Model} modelToProcess
261
+ * @return {boolean}
262
+ * @private
263
+ */
264
+ function searchableFieldsHaveChanged(currentModel, modelToProcess) {
265
+ return !currentModel || Boolean(
266
+ modelToProcess.constructor.searchProperties()
267
+ .filter(field => JSON.stringify(_.get(currentModel, field)) !== JSON.stringify(_.get(modelToProcess, field)))
268
+ .length,
269
+ );
201
270
  }
202
271
 
203
272
  /**