dataflux 1.14.9 → 1.15.1
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 +22 -19
- package/dist/Model.js +20 -8
- package/dist/Store.js +25 -15
- package/dist/dataflux.min.js +1 -1
- package/dist/dataflux.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -302,7 +302,9 @@ All the possible options for a model creation are (they are all optional):
|
|
|
302
302
|
| lazyLoad | A boolean defining if the model should be lazy loaded on the first use. This takes precedence over the lazyLoad declared during store initialization. | false |
|
|
303
303
|
| validate | A dictionary containing functions to validate the objects of this model. See [objects validation](#objects-validation) | no validation |
|
|
304
304
|
| autoRefresh | Set auto refresh for the specific model. See `autoRefresh` in the [store config](#configuration). | |
|
|
305
|
-
|autoSave| It allows to specify `autoSave` at model level. If store.autoSave is true, `autoSave: false` at model level will allow to disable autoSave only for the specific model. |
|
|
305
|
+
| autoSave | It allows to specify `autoSave` at model level. If store.autoSave is true, `autoSave: false` at model level will allow to disable autoSave only for the specific model. |
|
|
306
|
+
| pre | A function that is executed for every object retrieved, before creating the collection in the store. It is useful for pre-processing every data item received from the API. |
|
|
307
|
+
| post | A function that is executed for every object retrieved before delete, update, and insert operations. It is useful for post-processing every data item before sending them back to the API. |
|
|
306
308
|
|
|
307
309
|
### Operations
|
|
308
310
|
As described in the table above, there are four possible operations: **retrieve, insert, update,** and **delete**. An operation can be defined as an operation object or a function.
|
|
@@ -573,6 +575,7 @@ The store has the following method.
|
|
|
573
575
|
| refresh(type) | This method syncs all the objects in the store with the remote version offered by the REST APIs (`remote -> local`). Remote changes are applied locally, including adding/removing objects. Objects edited locally but not yet persisted are preserved locally (tip: you can also create a store with the `autoRefresh` option). If a model type is passed, only objects of that type will be refreshed. |
|
|
574
576
|
| reset(type) | This method syncs all the objects in the store with the remote version offered by the REST APIs (`remote -> local`). Remote changes are applied locally, including adding/removing objects. Objects edited locally but not yet persisted are reverted to the corresponding remote object. If a model type is passed, only objects of that type will be reset. |
|
|
575
577
|
| findSync(type, filterFunction) | This method returns the objects in a synchronous way (no Promise). However, *it works only if you already performed an async operation (e.g., like refresh, load, find, subscribe) or if you set lazyLoad to false and the store had enough time to load.* |
|
|
578
|
+
| hasChanged(type, object) | This method receives in input a model type and an object (optional). It returns a boolean, `true` if the object is dirty (it changed but it has not yet being persisted). If the object is not passed, the method checks if any of the objects of the specified model type has changed. |
|
|
576
579
|
|
|
577
580
|
### Insert vs. Mock
|
|
578
581
|
|
|
@@ -612,22 +615,22 @@ The store emits the following events:
|
|
|
612
615
|
Each object created is enriched with the following methods.
|
|
613
616
|
|
|
614
617
|
|
|
615
|
-
| Method | Description
|
|
616
|
-
|
|
617
|
-
| getId() | It returns a unique ID used by the store to identify the object. The ID is unique inside a single model. Be aware, `object.id` and `objet.getId()` may return different values, since store's IDs can be different from the one of the REST API.
|
|
618
|
-
| set(attribute, value, hidden) | A method to set an attribute to the object. It provides some advantages compared to doing `object.attribute = value`, these are discussed in [below](#editing-objects). The third parameter is optional, and when set to true will set the attribute as hidden (see [hiddenFields](#models-creation)).
|
|
619
|
-
| setConstant(attribute, value) | A method to set an unmodifiable hidden attribute on the object. Setting the attribute as a constant will not propagate an update.
|
|
618
|
+
| Method | Description |
|
|
619
|
+
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
620
|
+
| getId() | It returns a unique ID used by the store to identify the object. The ID is unique inside a single model. Be aware, `object.id` and `objet.getId()` may return different values, since store's IDs can be different from the one of the REST API. |
|
|
621
|
+
| set(attribute, value, hidden) | A method to set an attribute to the object. It provides some advantages compared to doing `object.attribute = value`, these are discussed in [below](#editing-objects). The third parameter is optional, and when set to true will set the attribute as hidden (see [hiddenFields](#models-creation)). |
|
|
622
|
+
| setConstant(attribute, value) | A method to set an unmodifiable hidden attribute on the object. Setting the attribute as a constant will not propagate an update. |
|
|
620
623
|
| get(attribute, defaultValue) | Method to retrieve the value of an attribute. It does not provide any advantage compared to accessing directly the attribute (e.g., `author.name`); except for hidden fields and constants, which can be retrieved only with the `.get` method. Additionally, you can provide a default value as a second parameter in case the object doesn't have that attribute. |
|
|
621
|
-
| getRelation(model, filterFunction) | To get all the objects respecting a specific relation with this object (see [model relations](#model-relations)).
|
|
622
|
-
| save() | Method to save the object. You can do `store.save()` instead.
|
|
623
|
-
| destroy() | Method to delete the object. You can do `store.delete()` instead.
|
|
624
|
-
| toJSON() | It returns a pure JSON representation of the object.
|
|
625
|
-
| toString() | It returns a string representation of the object.
|
|
626
|
-
| getFingerprint() | It returns a hash of the object. The hash changes at every change of the object or of any nested object. Useful to detect object changes.
|
|
627
|
-
| getModel() | It returns the model of this object. Mostly useful to do `object.getModel().getType()` and obtain a string defining the type of the object.
|
|
628
|
-
| getError() | If an operation on an object triggers an error, this error can be retrieved with `getError()`. This allows to observe specific objects' errors, instead of the generic `store.on("error", ...)`.
|
|
629
|
-
| getError(attributeName) | This method allows you to check if the specificed attribute generated any error according to the validation property specified in the model. See [objects validation](#objects-validation).
|
|
630
|
-
| setError(error) | Additionally to DataFlux's errors, you can trigger your own errors with this method. Other components observing this objet's error will be notified.
|
|
624
|
+
| getRelation(model, filterFunction) | To get all the objects respecting a specific relation with this object (see [model relations](#model-relations)). |
|
|
625
|
+
| save() | Method to save the object. You can do `store.save()` instead. |
|
|
626
|
+
| destroy() | Method to delete the object. You can do `store.delete()` instead. |
|
|
627
|
+
| toJSON() | It returns a pure JSON representation of the object. |
|
|
628
|
+
| toString() | It returns a string representation of the object. |
|
|
629
|
+
| getFingerprint() | It returns a hash of the object. The hash changes at every change of the object or of any nested object. Useful to detect object changes. |
|
|
630
|
+
| getModel() | It returns the model of this object. Mostly useful to do `object.getModel().getType()` and obtain a string defining the type of the object. |
|
|
631
|
+
| getError() | If an operation on an object triggers an error, this error can be retrieved with `getError()`. This allows to observe specific objects' errors, instead of the generic `store.on("error", ...)`. |
|
|
632
|
+
| getError(attributeName) | This method allows you to check if the specificed attribute generated any error according to the validation property specified in the model. See [objects validation](#objects-validation). |
|
|
633
|
+
| setError(error) | Additionally to DataFlux's errors, you can trigger your own errors with this method. Other components observing this objet's error will be notified. |
|
|
631
634
|
|
|
632
635
|
### Deep Objects
|
|
633
636
|
When a model is declared with the option `deep: true` (default, see [model creation](#models-creation)), all the sub objects will also offer many of the methods above.
|
|
@@ -680,12 +683,12 @@ const book = new Model("book", {
|
|
|
680
683
|
url: "https://rest.example.net/api/v1/books/"
|
|
681
684
|
},
|
|
682
685
|
validate: {
|
|
683
|
-
isbn: ({isbn}) => {
|
|
686
|
+
isbn: ({isbn}, store) => {
|
|
684
687
|
if (typeof(isbn) !== "number") {
|
|
685
688
|
throw new Error("The isbn must be a number");
|
|
686
689
|
}
|
|
687
690
|
},
|
|
688
|
-
title: ({title}) => {
|
|
691
|
+
title: ({title}, store) => {
|
|
689
692
|
if (!title) {
|
|
690
693
|
throw new Error("The title is mandatory");
|
|
691
694
|
}
|
|
@@ -694,7 +697,7 @@ const book = new Model("book", {
|
|
|
694
697
|
});
|
|
695
698
|
```
|
|
696
699
|
|
|
697
|
-
Each key of the `validate` dictionary is an attribute of the object (a field name), each value is a function receiving in input the object and throwing an error in case the field is not valid.
|
|
700
|
+
Each key of the `validate` dictionary is an attribute of the object (a field name), each value is a function receiving in input the object and the store, and throwing an error in case the field is not valid.
|
|
698
701
|
|
|
699
702
|
> Be aware: A validation function cannot return a boolean, you have to throw an error.
|
|
700
703
|
|
package/dist/Model.js
CHANGED
|
@@ -90,7 +90,11 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
90
90
|
_ref5,
|
|
91
91
|
_options$autoSave,
|
|
92
92
|
_ref6,
|
|
93
|
-
_options$autoRefresh
|
|
93
|
+
_options$autoRefresh,
|
|
94
|
+
_ref7,
|
|
95
|
+
_options$pre,
|
|
96
|
+
_ref8,
|
|
97
|
+
_options$post;
|
|
94
98
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
95
99
|
var defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
96
100
|
_classCallCheck(this, Model);
|
|
@@ -219,6 +223,9 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
219
223
|
_classPrivateFieldSet(_singleItemQuery, _this, true);
|
|
220
224
|
}
|
|
221
225
|
return _classPrivateFieldGet(_toArray, _this).call(_this, data);
|
|
226
|
+
}).then(function (data) {
|
|
227
|
+
var _this$options;
|
|
228
|
+
return (_this$options = _this.options) !== null && _this$options !== void 0 && _this$options.pre ? data.map(_this.options.pre) : data;
|
|
222
229
|
});
|
|
223
230
|
});
|
|
224
231
|
_defineProperty(this, "insertObjects", function (objects) {
|
|
@@ -292,6 +299,9 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
292
299
|
_classPrivateFieldInitSpec(this, _unWrap, function (objects) {
|
|
293
300
|
var data = Object.values(objects).map(function (object) {
|
|
294
301
|
return _classPrivateFieldGet(_removeHiddenFields, _this).call(_this, object.toJSON());
|
|
302
|
+
}).map(function (object) {
|
|
303
|
+
var _this$options2;
|
|
304
|
+
return (_this$options2 = _this.options) !== null && _this$options2 !== void 0 && _this$options2.post ? _this.options.post(object) : object;
|
|
295
305
|
});
|
|
296
306
|
if (data.value != null && Object.keys(data).length === 1) {
|
|
297
307
|
return data.value;
|
|
@@ -386,7 +396,9 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
386
396
|
lazyLoad: (_options$lazyLoad = options.lazyLoad) !== null && _options$lazyLoad !== void 0 ? _options$lazyLoad : defaults.lazyLoad,
|
|
387
397
|
validate: (_ref4 = (_options$validate = options.validate) !== null && _options$validate !== void 0 ? _options$validate : defaults.validate) !== null && _ref4 !== void 0 ? _ref4 : {},
|
|
388
398
|
autoSave: (_ref5 = (_options$autoSave = options.autoSave) !== null && _options$autoSave !== void 0 ? _options$autoSave : defaults.autoSave) !== null && _ref5 !== void 0 ? _ref5 : null,
|
|
389
|
-
autoRefresh: (_ref6 = (_options$autoRefresh = options.autoRefresh) !== null && _options$autoRefresh !== void 0 ? _options$autoRefresh : defaults.autoRefresh) !== null && _ref6 !== void 0 ? _ref6 : false
|
|
399
|
+
autoRefresh: (_ref6 = (_options$autoRefresh = options.autoRefresh) !== null && _options$autoRefresh !== void 0 ? _options$autoRefresh : defaults.autoRefresh) !== null && _ref6 !== void 0 ? _ref6 : false,
|
|
400
|
+
pre: (_ref7 = (_options$pre = options.pre) !== null && _options$pre !== void 0 ? _options$pre : defaults.pre) !== null && _ref7 !== void 0 ? _ref7 : null,
|
|
401
|
+
post: (_ref8 = (_options$post = options.post) !== null && _options$post !== void 0 ? _options$post : defaults.post) !== null && _ref8 !== void 0 ? _ref8 : null
|
|
390
402
|
});
|
|
391
403
|
_classPrivateFieldSet(_store, this, null);
|
|
392
404
|
_classPrivateFieldSet(_includes, this, {});
|
|
@@ -399,12 +411,12 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
399
411
|
if (_classPrivateFieldGet(_loadFunction, this) && typeof _classPrivateFieldGet(_loadFunction, this) !== "function") {
|
|
400
412
|
throw new Error("The load option must be a function");
|
|
401
413
|
}
|
|
402
|
-
var
|
|
403
|
-
|
|
404
|
-
retrieveHook =
|
|
405
|
-
insertHook =
|
|
406
|
-
updateHook =
|
|
407
|
-
deleteHook =
|
|
414
|
+
var _ref9 = _typeof(options) === "object" ? (0, _modelHooksUtils.getHooksFromOptions)(options) : (0, _modelHooksUtils.getHooksFromUrl)(options),
|
|
415
|
+
_ref10 = _slicedToArray(_ref9, 4),
|
|
416
|
+
retrieveHook = _ref10[0],
|
|
417
|
+
insertHook = _ref10[1],
|
|
418
|
+
updateHook = _ref10[2],
|
|
419
|
+
deleteHook = _ref10[3];
|
|
408
420
|
_classPrivateFieldSet(_retrieveHook, this, retrieveHook);
|
|
409
421
|
_classPrivateFieldSet(_updateHook, this, updateHook);
|
|
410
422
|
_classPrivateFieldSet(_insertHook, this, insertHook);
|
package/dist/Store.js
CHANGED
|
@@ -358,8 +358,18 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
358
358
|
}, {
|
|
359
359
|
key: "hasChanged",
|
|
360
360
|
value: function hasChanged(type, object) {
|
|
361
|
-
var
|
|
362
|
-
|
|
361
|
+
var _this8 = this;
|
|
362
|
+
var _hasChanged = function _hasChanged(type, object) {
|
|
363
|
+
var obj = _this8.models[type].storedObjects[object.getId()];
|
|
364
|
+
return !obj || obj.fingerprint !== obj.object.getFingerprint();
|
|
365
|
+
};
|
|
366
|
+
if (object) {
|
|
367
|
+
return _hasChanged(type, object);
|
|
368
|
+
} else {
|
|
369
|
+
return Object.values(this.models[type].storedObjects).some(function (i) {
|
|
370
|
+
return _hasChanged(type, i);
|
|
371
|
+
});
|
|
372
|
+
}
|
|
363
373
|
}
|
|
364
374
|
}, {
|
|
365
375
|
key: "preload",
|
|
@@ -369,9 +379,9 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
369
379
|
}, {
|
|
370
380
|
key: "getDiff",
|
|
371
381
|
value: function getDiff(type, ifLoaded) {
|
|
372
|
-
var
|
|
382
|
+
var _this9 = this;
|
|
373
383
|
return this._getPromise(type, ifLoaded).then(function () {
|
|
374
|
-
var objects = Object.values(
|
|
384
|
+
var objects = Object.values(_this9.models[type].storedObjects);
|
|
375
385
|
var inserted = [];
|
|
376
386
|
var updated = [];
|
|
377
387
|
var deleted = [];
|
|
@@ -381,7 +391,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
381
391
|
inserted.push(object);
|
|
382
392
|
} else if (object.status === "deleted") {
|
|
383
393
|
deleted.push(object);
|
|
384
|
-
} else if (object.status === "old" &&
|
|
394
|
+
} else if (object.status === "old" && _this9.hasChanged(type, object.object)) {
|
|
385
395
|
updated.push(object);
|
|
386
396
|
} // Nothing for mock objects
|
|
387
397
|
}
|
|
@@ -395,7 +405,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
395
405
|
}, {
|
|
396
406
|
key: "factory",
|
|
397
407
|
value: function factory(type, params) {
|
|
398
|
-
var
|
|
408
|
+
var _this10 = this;
|
|
399
409
|
var item = this.models[type];
|
|
400
410
|
this.pubSub.publish("loading", {
|
|
401
411
|
status: "start",
|
|
@@ -407,14 +417,14 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
407
417
|
try {
|
|
408
418
|
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
409
419
|
var _item = _step4.value;
|
|
410
|
-
_classPrivateFieldGet(_insertObject,
|
|
420
|
+
_classPrivateFieldGet(_insertObject, _this10).call(_this10, type, _item, "old");
|
|
411
421
|
}
|
|
412
422
|
} catch (err) {
|
|
413
423
|
_iterator4.e(err);
|
|
414
424
|
} finally {
|
|
415
425
|
_iterator4.f();
|
|
416
426
|
}
|
|
417
|
-
|
|
427
|
+
_this10.pubSub.publish("loading", {
|
|
418
428
|
status: "end",
|
|
419
429
|
model: type
|
|
420
430
|
});
|
|
@@ -424,7 +434,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
424
434
|
}, {
|
|
425
435
|
key: "_getPromise",
|
|
426
436
|
value: function _getPromise(type) {
|
|
427
|
-
var
|
|
437
|
+
var _this11 = this;
|
|
428
438
|
var ifLoaded = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
429
439
|
if (!this.models[type]) {
|
|
430
440
|
return Promise.reject("The model doesn't exist");
|
|
@@ -432,7 +442,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
432
442
|
return Promise.reject("The model is not loaded");
|
|
433
443
|
} else if (!this.models[type].promise && this.options.lazyLoad && !ifLoaded) {
|
|
434
444
|
return _assertClassBrand(_Store_brand, this, _loadObjects).call(this, type).then(function () {
|
|
435
|
-
return
|
|
445
|
+
return _this11.models[type].promise;
|
|
436
446
|
});
|
|
437
447
|
} else if (!this.models[type].promise && this.options.lazyLoad && ifLoaded) {
|
|
438
448
|
return Promise.resolve();
|
|
@@ -448,9 +458,9 @@ function _error(error) {
|
|
|
448
458
|
return Promise.reject(error);
|
|
449
459
|
}
|
|
450
460
|
function _deleteByFilter(type, filterFunction) {
|
|
451
|
-
var
|
|
461
|
+
var _this12 = this;
|
|
452
462
|
return this._getPromise(type).then(function () {
|
|
453
|
-
var deleted = Object.values(
|
|
463
|
+
var deleted = Object.values(_this12.models[type].storedObjects).filter(function (i) {
|
|
454
464
|
return filterFunction(i.object);
|
|
455
465
|
});
|
|
456
466
|
var _iterator5 = _createForOfIteratorHelper(deleted),
|
|
@@ -471,7 +481,7 @@ function _deleteByFilter(type, filterFunction) {
|
|
|
471
481
|
});
|
|
472
482
|
}
|
|
473
483
|
function _loadObjects(type) {
|
|
474
|
-
var
|
|
484
|
+
var _this13 = this;
|
|
475
485
|
var item = this.models[type];
|
|
476
486
|
this.pubSub.publish("loading", {
|
|
477
487
|
status: "start",
|
|
@@ -483,14 +493,14 @@ function _loadObjects(type) {
|
|
|
483
493
|
try {
|
|
484
494
|
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
485
495
|
var _item2 = _step6.value;
|
|
486
|
-
_classPrivateFieldGet(_insertObject,
|
|
496
|
+
_classPrivateFieldGet(_insertObject, _this13).call(_this13, type, _item2, "old");
|
|
487
497
|
}
|
|
488
498
|
} catch (err) {
|
|
489
499
|
_iterator6.e(err);
|
|
490
500
|
} finally {
|
|
491
501
|
_iterator6.f();
|
|
492
502
|
}
|
|
493
|
-
|
|
503
|
+
_this13.pubSub.publish("loading", {
|
|
494
504
|
status: "end",
|
|
495
505
|
model: type
|
|
496
506
|
});
|