dataflux 1.16.0 → 1.17.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 -21
- package/dist/BasicObj.js +3 -0
- package/dist/Model.js +12 -3
- package/dist/Store.js +60 -29
- package/dist/dataflux.min.js +1 -1
- package/dist/dataflux.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -350,25 +350,25 @@ const book = new Model("book", options);
|
|
|
350
350
|
|
|
351
351
|
All the possible options for a model creation are (they are all optional):
|
|
352
352
|
|
|
353
|
-
| Name
|
|
354
|
-
|
|
355
|
-
| retrieve
|
|
356
|
-
| insert
|
|
357
|
-
| update
|
|
358
|
-
| delete
|
|
359
|
-
| fields
|
|
360
|
-
| headers
|
|
361
|
-
| load
|
|
362
|
-
| axios
|
|
363
|
-
| parseMoment
|
|
364
|
-
| hiddenFields
|
|
365
|
-
| deep
|
|
366
|
-
| lazyLoad
|
|
367
|
-
| validate
|
|
368
|
-
| autoRefresh
|
|
369
|
-
| autoSave
|
|
370
|
-
| pre
|
|
371
|
-
| post
|
|
353
|
+
| Name | Description | Default |
|
|
354
|
+
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|
|
|
355
|
+
| retrieve | Describes the operation to retrieve the collection of objects from the REST API. It can be an operation object or a function. See [operations](#operations). | `{method: "get"}` |
|
|
356
|
+
| insert | Describes the operation to insert a new object in the collection. It can be an operation object or a function. See [operations](#operations). | `{method: "post"}` |
|
|
357
|
+
| update | Describes the operation to update objects of the collection. It can be an operation object or a function. See [operations](#operations). | `{method: "put"}` |
|
|
358
|
+
| delete | Describes the operation to remove objects from the collection. It can be an operation object or a function. See [operations](#operations). | `{method: "delete"}` |
|
|
359
|
+
| fields | An array of strings defining which attributes the retrieved objects should have. Essentially, it allows you to contemporarily specify the [X-Fields header](https://flask-restplus.readthedocs.io/en/stable/mask.html) and the [fields GET parameter](https://developers.google.com/slides/api/guides/performance#partial). This reduces transfer size and memory usage. E.g., if you have a collection of books, of which you are interested only in the name, you can define `fields: ["name"]`. In combination with `load` it allows for partial lazy load of the objects. | All the fields |
|
|
360
|
+
| headers | A dictionary of headers for the HTTP request. E.g., `{"Authorization": "bearer XXXX"}`. | No headers |
|
|
361
|
+
| load | A function that allows to enrich the objects on demand. E.g., you can use `fields` to download only the titles of a collection of books, and `load` to load completely the object. See [object enrichment](#object-enrichment). |
|
|
362
|
+
| axios | It allows to specify an axios instance to be used for the queries. If not specified, a new one will be used. | A new axios instance |
|
|
363
|
+
| parseMoment | Automatically creates Moment.js objects out of ISO8601 strings. E.g., if an object has a property `createdAt: "2022-01-07T21:38:50.295Z"`, this will be transformed to a moment object. | |
|
|
364
|
+
| hiddenFields | An array of attribute names that will never be sent back to the API. E.g., if you set `hiddenFields: ["pages"]`, a book object can contain an attribute `pages` locally, but this will be stripped out in PUT/POST requests. |
|
|
365
|
+
| deep | A boolean defining if nested objects should be enriched with the object methods. | true |
|
|
366
|
+
| 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 |
|
|
367
|
+
| validate | A dictionary containing functions to validate the objects of this model. See [objects validation](#objects-validation) | no validation |
|
|
368
|
+
| autoRefresh | Set auto refresh for the specific model. See `autoRefresh` in the [store config](#configuration). | |
|
|
369
|
+
| 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. |
|
|
370
|
+
| pre(object, objects) | 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. It receives in input a object of the collection (first parameter) and the entire collection (second parameter). |
|
|
371
|
+
| 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. It receives in input a object of the collection (first parameter) and the entire collection (second parameter). |
|
|
372
372
|
|
|
373
373
|
### Operations
|
|
374
374
|
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.
|
|
@@ -624,7 +624,7 @@ The store has the following method.
|
|
|
624
624
|
| addModel(model) | Introduce a new model to the store. If lazyLoad = false (default), the model is populated with the objects coming from the API. |
|
|
625
625
|
| get(type, id) | It allows to retrieve an object based on its type and store's ID (see `getId()` in [objects methods](#objects-methods). The type is the name of the model. |
|
|
626
626
|
| find(type, filterFunction) | The promise-oriented method to access objects given a type and a filter function. If the filter function is missing, all the objects are returned. See [example 1](#example-1). |
|
|
627
|
-
| delete(objects) | It deletes an array of objects. See [example
|
|
627
|
+
| delete(objects) | It deletes an array of objects. See [example 3](#example-3). |
|
|
628
628
|
| delete(type, filterFunction) | It deleted objects given an array and a filter function. See [example 1](#example-3). |
|
|
629
629
|
| insert(type, object) | It creates a new object of a given type and inserts it in the store. The object inserted MUST be ready to be persisted, read `mock()` below. |
|
|
630
630
|
| mock(type, object) | It creates a mock object of a given type and inserts it in the store. The mock object behaves exactly like a real object, except that it is not persisted (sent to the API) as long as you don't call `object.insert()`. This is useful when you want to create an object but you need to be able to change some properties before to send it to the API. Read [insert vs. mock](#insert-vs-mock). |
|
|
@@ -632,7 +632,7 @@ The store has the following method.
|
|
|
632
632
|
| multipleSubscribe(subscriptions, callback) | A method to subscribe to multiple models. The first parameter is an array of models' names and filterFunctions, the second parameter is the callback to be called when the cumulative dataset is ready. E.g., `multipleSubscribe([["book", filterFunction1], ["author", filterFunction2]], callback)`. It returns the key of the subscription. See [example 5](#example-5---observability). |
|
|
633
633
|
| unsubscribe(key) | Method to terminate a subscription given a subscription key. See [example 5](#example-5---observability). |
|
|
634
634
|
| findOne(type, stateAttribute, context, filterFunction) | This method automatically injects and updates the React state with the requested data. If multiple objects satisfy the query, only the first is selected. The `stateAttribute` is the name of the attribute that will be added/updated in the state, the `context` is the React.Component. It automatically unsubscribe when the React.Component will unmount. See [example 6](#example-6---observability--react). |
|
|
635
|
-
| findAll(type, stateAttribute, context, filterFunction) | This method automatically injects and updates the React state with the requested data. The `stateAttribute` is the name of the attribute that will be added/updated in the state, the `context` is the React.Component. It automatically unsubscribe when the React.Component will unmount. If the filter function is missing, all the objects are returned. See [example
|
|
635
|
+
| findAll(type, stateAttribute, context, filterFunction) | This method automatically injects and updates the React state with the requested data. The `stateAttribute` is the name of the attribute that will be added/updated in the state, the `context` is the React.Component. It automatically unsubscribe when the React.Component will unmount. If the filter function is missing, all the objects are returned. See [example 7](#example-6---observability--react). |
|
|
636
636
|
| preload(type) | This method allows to preLoad all objects of a given model. If you initialize the store with `lazyLoad:true`, the objects of a model are retrieved from the API at the first query performed on that model (e.g., at the first `.find()`). However, sometimes you may want to speed up the first query by pre loading the objects of a specific model while keeping `lazyLoad:true` on the store; in such a case you can use `store.preload(type)`. |
|
|
637
637
|
| save() | Persist the changes. Edited local objects will be sent to the REST APIs (insert/update/delete). See also [editing objects](#editing-objects). |
|
|
638
638
|
| save() | Persist the changes (`local -> remote`). Edited local objects will be sent to the REST APIs (insert/update/delete). See also [editing objects](#editing-objects). |
|
|
@@ -641,6 +641,7 @@ The store has the following method.
|
|
|
641
641
|
| 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.* |
|
|
642
642
|
| 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. |
|
|
643
643
|
| didUpdate(context) | If you pass an object as a prop to a React component, the component will not refresh if the object changes. To address this, you can use this method inside the `componentDidUpdate` to check if any of the objects changed. See [example 6](#example-7---react-props-and-observability) |
|
|
644
|
+
| getCollection(type) | This method receives in input a model type . It returns all the raw (JSON) objects available for that model. |
|
|
644
645
|
|
|
645
646
|
### Insert vs. Mock
|
|
646
647
|
|
package/dist/BasicObj.js
CHANGED
|
@@ -81,6 +81,9 @@ var BasicObj = exports.BasicObj = /*#__PURE__*/function () {
|
|
|
81
81
|
_defineProperty(this, "isDataflux", function () {
|
|
82
82
|
return true;
|
|
83
83
|
});
|
|
84
|
+
_defineProperty(this, "isMock", function () {
|
|
85
|
+
return false;
|
|
86
|
+
});
|
|
84
87
|
_defineProperty(this, "setId", function (id) {
|
|
85
88
|
_this.id = id;
|
|
86
89
|
});
|
package/dist/Model.js
CHANGED
|
@@ -225,7 +225,9 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
225
225
|
return _classPrivateFieldGet(_toArray, _this).call(_this, data);
|
|
226
226
|
}).then(function (data) {
|
|
227
227
|
var _this$options;
|
|
228
|
-
return (_this$options = _this.options) !== null && _this$options !== void 0 && _this$options.pre ? data.map(
|
|
228
|
+
return (_this$options = _this.options) !== null && _this$options !== void 0 && _this$options.pre ? data.map(function (n) {
|
|
229
|
+
return _this.options.pre(n, data);
|
|
230
|
+
}) : data;
|
|
229
231
|
});
|
|
230
232
|
});
|
|
231
233
|
_defineProperty(this, "insertObjects", function (objects) {
|
|
@@ -273,6 +275,12 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
273
275
|
} finally {
|
|
274
276
|
_iterator.f();
|
|
275
277
|
}
|
|
278
|
+
for (var _i = 0, _Object$values = Object.values(json); _i < _Object$values.length; _i++) {
|
|
279
|
+
var obj = _Object$values[_i];
|
|
280
|
+
if (_typeof(obj) === "object") {
|
|
281
|
+
_classPrivateFieldGet(_removeHiddenFields, _this).call(_this, obj);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
276
284
|
return json;
|
|
277
285
|
});
|
|
278
286
|
_classPrivateFieldInitSpec(this, _toArray, function (data) {
|
|
@@ -297,11 +305,12 @@ var Model = exports["default"] = /*#__PURE__*/_createClass(function Model(name)
|
|
|
297
305
|
}
|
|
298
306
|
});
|
|
299
307
|
_classPrivateFieldInitSpec(this, _unWrap, function (objects) {
|
|
300
|
-
var
|
|
308
|
+
var arrayObjects = Object.values(objects);
|
|
309
|
+
var data = arrayObjects.map(function (object) {
|
|
301
310
|
return _classPrivateFieldGet(_removeHiddenFields, _this).call(_this, object.toJSON());
|
|
302
311
|
}).map(function (object) {
|
|
303
312
|
var _this$options2;
|
|
304
|
-
return (_this$options2 = _this.options) !== null && _this$options2 !== void 0 && _this$options2.post ? _this.options.post(object) : object;
|
|
313
|
+
return (_this$options2 = _this.options) !== null && _this$options2 !== void 0 && _this$options2.post ? _this.options.post(object, arrayObjects) : object;
|
|
305
314
|
});
|
|
306
315
|
if (data.value != null && Object.keys(data).length === 1) {
|
|
307
316
|
return data.value;
|
package/dist/Store.js
CHANGED
|
@@ -74,6 +74,32 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
74
74
|
});
|
|
75
75
|
return filterFunction ? all.filter(filterFunction) : all;
|
|
76
76
|
});
|
|
77
|
+
_defineProperty(this, "_validateTypeInput", function (type) {
|
|
78
|
+
if (!_this.models[type]) {
|
|
79
|
+
throw new Error("Not valid model type");
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
_defineProperty(this, "_getDiffSync", function (type) {
|
|
83
|
+
var objects = Object.values(_this.models[type].storedObjects);
|
|
84
|
+
var inserted = [];
|
|
85
|
+
var updated = [];
|
|
86
|
+
var deleted = [];
|
|
87
|
+
for (var _i = 0, _objects = objects; _i < _objects.length; _i++) {
|
|
88
|
+
var object = _objects[_i];
|
|
89
|
+
if (object.status === "new") {
|
|
90
|
+
inserted.push(object);
|
|
91
|
+
} else if (object.status === "deleted") {
|
|
92
|
+
deleted.push(object);
|
|
93
|
+
} else if (object.status === "old" && _this.hasChanged(type, object.object)) {
|
|
94
|
+
updated.push(object);
|
|
95
|
+
} // Nothing for mock objects
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
inserted: inserted,
|
|
99
|
+
updated: updated,
|
|
100
|
+
deleted: deleted
|
|
101
|
+
};
|
|
102
|
+
});
|
|
77
103
|
_defineProperty(this, "refreshObjectByType", function (type) {
|
|
78
104
|
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
79
105
|
return _this._getPromise(type).then(function () {
|
|
@@ -174,8 +200,14 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
174
200
|
throw new Error("The provided status is not valid");
|
|
175
201
|
}
|
|
176
202
|
if (status === "mock") {
|
|
203
|
+
wrapper.isMock = function () {
|
|
204
|
+
return true;
|
|
205
|
+
};
|
|
177
206
|
wrapper.insert = function () {
|
|
178
207
|
_this.models[type].storedObjects[id].status = "new";
|
|
208
|
+
wrapper.isMock = function () {
|
|
209
|
+
return false;
|
|
210
|
+
};
|
|
179
211
|
_this.update([wrapper]);
|
|
180
212
|
delete wrapper.insert;
|
|
181
213
|
};
|
|
@@ -359,9 +391,7 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
359
391
|
key: "hasChanged",
|
|
360
392
|
value: function hasChanged(type, object) {
|
|
361
393
|
var _this8 = this;
|
|
362
|
-
|
|
363
|
-
throw new Error("Not valid model type");
|
|
364
|
-
}
|
|
394
|
+
this._validateTypeInput(type);
|
|
365
395
|
var _hasChanged = function _hasChanged(type, object) {
|
|
366
396
|
var obj = _this8.models[type].storedObjects[object.getId()];
|
|
367
397
|
return !obj || obj.fingerprint !== obj.object.getFingerprint();
|
|
@@ -369,8 +399,12 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
369
399
|
if (object) {
|
|
370
400
|
return _hasChanged(type, object);
|
|
371
401
|
} else {
|
|
372
|
-
|
|
373
|
-
|
|
402
|
+
var _this$_getDiffSync = this._getDiffSync(type),
|
|
403
|
+
inserted = _this$_getDiffSync.inserted,
|
|
404
|
+
updated = _this$_getDiffSync.updated,
|
|
405
|
+
deleted = _this$_getDiffSync.deleted;
|
|
406
|
+
return [inserted, updated, deleted].some(function (i) {
|
|
407
|
+
return i.length > 0;
|
|
374
408
|
});
|
|
375
409
|
}
|
|
376
410
|
}
|
|
@@ -383,26 +417,9 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
383
417
|
key: "getDiff",
|
|
384
418
|
value: function getDiff(type, ifLoaded) {
|
|
385
419
|
var _this9 = this;
|
|
420
|
+
this._validateTypeInput(type);
|
|
386
421
|
return this._getPromise(type, ifLoaded).then(function () {
|
|
387
|
-
|
|
388
|
-
var inserted = [];
|
|
389
|
-
var updated = [];
|
|
390
|
-
var deleted = [];
|
|
391
|
-
for (var _i = 0, _objects = objects; _i < _objects.length; _i++) {
|
|
392
|
-
var object = _objects[_i];
|
|
393
|
-
if (object.status === "new") {
|
|
394
|
-
inserted.push(object);
|
|
395
|
-
} else if (object.status === "deleted") {
|
|
396
|
-
deleted.push(object);
|
|
397
|
-
} else if (object.status === "old" && _this9.hasChanged(type, object.object)) {
|
|
398
|
-
updated.push(object);
|
|
399
|
-
} // Nothing for mock objects
|
|
400
|
-
}
|
|
401
|
-
return {
|
|
402
|
-
inserted: inserted,
|
|
403
|
-
updated: updated,
|
|
404
|
-
deleted: deleted
|
|
405
|
-
};
|
|
422
|
+
return _this9._getDiffSync(type);
|
|
406
423
|
});
|
|
407
424
|
}
|
|
408
425
|
}, {
|
|
@@ -453,6 +470,20 @@ var Store = exports["default"] = /*#__PURE__*/function () {
|
|
|
453
470
|
return this.models[type].promise;
|
|
454
471
|
}
|
|
455
472
|
}
|
|
473
|
+
}, {
|
|
474
|
+
key: "getCollection",
|
|
475
|
+
value: function getCollection(type) {
|
|
476
|
+
var _this12 = this;
|
|
477
|
+
return this._getPromise(type).then(function () {
|
|
478
|
+
return Object.values(_this12.models[type].storedObjects).map(function (i) {
|
|
479
|
+
return i.object;
|
|
480
|
+
}).sort(function (a, b) {
|
|
481
|
+
return a.getId().localeCompare(b.getId());
|
|
482
|
+
}).map(function (i) {
|
|
483
|
+
return i.toJSON();
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
}
|
|
456
487
|
}]);
|
|
457
488
|
}();
|
|
458
489
|
function _error(error) {
|
|
@@ -461,9 +492,9 @@ function _error(error) {
|
|
|
461
492
|
return Promise.reject(error);
|
|
462
493
|
}
|
|
463
494
|
function _deleteByFilter(type, filterFunction) {
|
|
464
|
-
var
|
|
495
|
+
var _this13 = this;
|
|
465
496
|
return this._getPromise(type).then(function () {
|
|
466
|
-
var deleted = Object.values(
|
|
497
|
+
var deleted = Object.values(_this13.models[type].storedObjects).filter(function (i) {
|
|
467
498
|
return filterFunction(i.object);
|
|
468
499
|
});
|
|
469
500
|
var _iterator5 = _createForOfIteratorHelper(deleted),
|
|
@@ -484,7 +515,7 @@ function _deleteByFilter(type, filterFunction) {
|
|
|
484
515
|
});
|
|
485
516
|
}
|
|
486
517
|
function _loadObjects(type) {
|
|
487
|
-
var
|
|
518
|
+
var _this14 = this;
|
|
488
519
|
var item = this.models[type];
|
|
489
520
|
this.pubSub.publish("loading", {
|
|
490
521
|
status: "start",
|
|
@@ -496,14 +527,14 @@ function _loadObjects(type) {
|
|
|
496
527
|
try {
|
|
497
528
|
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
498
529
|
var _item2 = _step6.value;
|
|
499
|
-
_classPrivateFieldGet(_insertObject,
|
|
530
|
+
_classPrivateFieldGet(_insertObject, _this14).call(_this14, type, _item2, "old");
|
|
500
531
|
}
|
|
501
532
|
} catch (err) {
|
|
502
533
|
_iterator6.e(err);
|
|
503
534
|
} finally {
|
|
504
535
|
_iterator6.f();
|
|
505
536
|
}
|
|
506
|
-
|
|
537
|
+
_this14.pubSub.publish("loading", {
|
|
507
538
|
status: "end",
|
|
508
539
|
model: type
|
|
509
540
|
});
|