dataflux 1.8.0 → 1.9.2
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 +125 -24
- package/dist/BasicObj.js +53 -6
- package/dist/Model.js +144 -29
- package/dist/ObserverStore.js +18 -6
- package/dist/PersistentStore.js +55 -22
- package/dist/Store.js +202 -64
- package/dist/dataflux.min.js +1 -1
- package/dist/dataflux.min.js.map +1 -1
- package/dist/modelHooksUtils.js +19 -13
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -258,11 +258,12 @@ function MyComponent() {
|
|
|
258
258
|
The store can be configured with the following options:
|
|
259
259
|
|
|
260
260
|
|
|
261
|
-
| Option
|
|
262
|
-
|
|
263
|
-
| autoSave
|
|
264
|
-
| saveDelay
|
|
265
|
-
| lazyLoad
|
|
261
|
+
| Option | Description | Default |
|
|
262
|
+
|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|
|
263
|
+
| autoSave | It can be `true`, `false`, or an amount of milliseconds (integer). If `false`, you will have to perform `store.save()` manually. If `true`, the store will automatically perform `store.save()` when objects change. If an amount of milliseconds is provided, the objects are saved periodically AND when a change is detected. See [Editing objects](#editing-objects) for more information. | true |
|
|
264
|
+
| saveDelay | An amount of milliseconds used to defer synching operations with the server. It triggers `store.save()` milliseconds after the last change on the store's objects is detedect. This allows to bundle together multiple changes operated by an interacting user. See [Editing objects](#editing-objects) for more information. | 1000 |
|
|
265
|
+
| lazyLoad | A boolean. If set to `false`, the store is pre-populated with all the models' objects. If set to `true`, models' objects are loaded only on first usage (e.g., 'find', 'subscribe', 'getRelation'). LazyLoad operates per model, only the objects of the used models are loaded. | false |
|
|
266
|
+
| autoRefresh | It can be `true`, `false`, or an amount of milliseconds (integer). If `false`, you will have to perform `store.refresh()` manually. If `true`, the store will automatically perform `store.refresh()` every 2 minutes. If an amount of milliseconds is provided, the `store.refresh()` is performed periodically. See [store methods](#store-methods) for more information. | false |
|
|
266
267
|
|
|
267
268
|
|
|
268
269
|
|
|
@@ -296,6 +297,7 @@ All the possible options for a model creation are (they are all optional):
|
|
|
296
297
|
| 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. |
|
|
297
298
|
| deep | A boolean defining if nested objects should be enriched with the object methods. | true |
|
|
298
299
|
| 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 |
|
|
300
|
+
| validate | A dictionary containing functions to validate the objects of this model. See [objects validation](#objects-validation) | no validation |
|
|
299
301
|
|
|
300
302
|
### Operations
|
|
301
303
|
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.
|
|
@@ -553,41 +555,73 @@ The store has the following method.
|
|
|
553
555
|
| 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). |
|
|
554
556
|
| delete(objects) | It deletes an array of objects. See [example 1](#example-3). |
|
|
555
557
|
| delete(type, filterFunction) | It deleted objects given an array and a filter function. See [example 1](#example-3). |
|
|
556
|
-
| insert(type, object) | It creates a new object of a given type and inserts it in the store.
|
|
558
|
+
| 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. |
|
|
559
|
+
| 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). |
|
|
557
560
|
| subscribe(type, callback, filterFunction) | The callback-oriented method to access objects given a type and a filter function. It returns the key of the subscription, needed to unsubscribe. If the filter function is missing, all the objects are returned. **DataFlux remembers your query and calls the callback every time any change is affecting the result of your query.** See [example 5](#example-5---observability). |
|
|
558
561
|
| 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). |
|
|
559
562
|
| unsubscribe(key) | Method to terminate a subscription given a subscription key. See [example 5](#example-5---observability). |
|
|
560
563
|
| 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). |
|
|
561
564
|
| 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 6](#example-6---observability--react). |
|
|
562
565
|
| 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)`. |
|
|
566
|
+
| save() | Persist the changes. Edited local objects will be sent to the REST APIs (insert/update/delete). See also [editing objects](#editing-objects). |
|
|
567
|
+
| 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). |
|
|
568
|
+
| refresh() | 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). |
|
|
569
|
+
### Insert vs. Mock
|
|
570
|
+
|
|
571
|
+
If you do:
|
|
572
|
+
```js
|
|
573
|
+
store.insert("book", {title: "The little prince"});
|
|
574
|
+
```
|
|
575
|
+
when the store will try to save, the object `{title: "The little prince"}` will be sent to the API in a post request. However, the API may require an attribute "price" for each book object, hence the post request will fail.
|
|
576
|
+
Of course, you can add the attribute directly in the `.insert()` call; however, the value of this attribute may not be known at that time. For example, the user may need to input the price in a text field.
|
|
577
|
+
|
|
578
|
+
You may think to delay the `.insert()` up to when all the required attributes are available; however, **this is a bad idea**, because as long as the object is not in the store, you will not benefit from the observability provided by DataFlux. _E.g., your React state will not update automatically and you will need to handle the changes triggered by the input fields yourself_ ([reinventing the wheel](https://en.wikipedia.org/wiki/Reinventing_the_wheel)).
|
|
579
|
+
|
|
580
|
+
Solution, use `.mock()` to create a mock object:
|
|
581
|
+
|
|
582
|
+
```js
|
|
583
|
+
store.mock("book", {title: "The little prince"});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
The mock object behaves exactly like a normal object: you can retrieve it with `.find`/`.findAll`/`.findOne`/`.subscribe`.
|
|
587
|
+
|
|
588
|
+
However, the mock object is not sent to the API as long as you don't call `.insert()` on the object itself. When you call `.insert()`, the mock object is promoted to real object.
|
|
589
|
+
|
|
590
|
+
> Warning: to promote a mock object, you need to call `object.insert()` on the object itself (you must first retrieve it) and NOT `store.insert()`.
|
|
591
|
+
|
|
563
592
|
|
|
564
593
|
## Store events
|
|
565
594
|
The store emits the following events:
|
|
566
595
|
|
|
567
|
-
| Name
|
|
568
|
-
|
|
569
|
-
| error
|
|
570
|
-
| save
|
|
571
|
-
| loading
|
|
596
|
+
| Name | Description |
|
|
597
|
+
|------------|---------------------------------------------------------------------------------------------------------------------------------------|
|
|
598
|
+
| error | To listen the errors emitted by the store. |
|
|
599
|
+
| save | Possible emitted values are `start` and `end`. They are emitted when the store starts/finishes to persist the data (API interaction). |
|
|
600
|
+
| loading | The event is emitted while a new model is loaded. The value contains something like `{status: "start", model: "book"}` |
|
|
601
|
+
| refreshing | The event is emitted while a model is refreshed. The value contains something like `{status: "start", model: "book"}` |
|
|
572
602
|
|
|
573
603
|
## Objects methods
|
|
574
604
|
Each object created is enriched with the following methods.
|
|
575
605
|
|
|
576
606
|
|
|
577
|
-
| Method | Description
|
|
578
|
-
|
|
579
|
-
| 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.
|
|
580
|
-
| 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)).
|
|
581
|
-
| 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.
|
|
607
|
+
| Method | Description |
|
|
608
|
+
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
609
|
+
| 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. |
|
|
610
|
+
| 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)). |
|
|
611
|
+
| 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. |
|
|
582
612
|
| 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. |
|
|
583
|
-
| getRelation(model, filterFunction) | To get all the objects respecting a specific relation with this object (see [model relations](#model-relations)).
|
|
584
|
-
| save() | Method to save the object. You can do `store.save()` instead.
|
|
585
|
-
| destroy() | Method to delete the object. You can do `store.delete()` instead.
|
|
586
|
-
| toJSON() | It returns a pure JSON representation of the object.
|
|
587
|
-
| toString() | It returns a string representation of the object.
|
|
588
|
-
| 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.
|
|
589
|
-
| 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.
|
|
590
|
-
|
|
613
|
+
| getRelation(model, filterFunction) | To get all the objects respecting a specific relation with this object (see [model relations](#model-relations)). |
|
|
614
|
+
| save() | Method to save the object. You can do `store.save()` instead. |
|
|
615
|
+
| destroy() | Method to delete the object. You can do `store.delete()` instead. |
|
|
616
|
+
| toJSON() | It returns a pure JSON representation of the object. |
|
|
617
|
+
| toString() | It returns a string representation of the object. |
|
|
618
|
+
| 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. |
|
|
619
|
+
| 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. |
|
|
620
|
+
| 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", ...)`. |
|
|
621
|
+
| 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). |
|
|
622
|
+
| 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. |
|
|
623
|
+
|
|
624
|
+
### Deep Objects
|
|
591
625
|
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.
|
|
592
626
|
|
|
593
627
|
Imagine the API returns:
|
|
@@ -624,8 +658,75 @@ store.find("book")
|
|
|
624
658
|
});
|
|
625
659
|
```
|
|
626
660
|
|
|
661
|
+
### Objects validation
|
|
662
|
+
|
|
663
|
+
DataFlux supports automatic validation of the objects. This is important for two reasons:
|
|
664
|
+
* Objects that contain invalid attributes' values are not sent back to the API;
|
|
665
|
+
* Validation errors can be used to automatically suggest errors in the UI.
|
|
666
|
+
|
|
667
|
+
To specify the validation of the objects for a specific model, you need to add a `validate` dictionary during model creation.
|
|
668
|
+
|
|
669
|
+
```js
|
|
670
|
+
const book = new Model("book", {
|
|
671
|
+
retrieve: {
|
|
672
|
+
url: "https://rest.example.net/api/v1/books/"
|
|
673
|
+
},
|
|
674
|
+
validate: {
|
|
675
|
+
isbn: ({isbn}) => {
|
|
676
|
+
if (typeof(isbn) !== "number") {
|
|
677
|
+
throw new Error("The isbn must be a number");
|
|
678
|
+
}
|
|
679
|
+
},
|
|
680
|
+
title: ({title}) => {
|
|
681
|
+
if (!title) {
|
|
682
|
+
throw new Error("The title is mandatory");
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
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.
|
|
690
|
+
|
|
691
|
+
> Be aware: A validation function cannot return a boolean, you have to throw an error.
|
|
692
|
+
|
|
693
|
+
To validate a specific attribute of an object, you can do `object.getError(attributeName)` (e.g., `book.getError(isbn)`). In case of error, a string describing the error is returned, `false` otherwise.
|
|
694
|
+
|
|
695
|
+
Example of usage in a React component.
|
|
696
|
+
|
|
697
|
+
```js
|
|
698
|
+
class MyComponent extends React.Component {
|
|
699
|
+
constructor(props) {
|
|
700
|
+
super(props);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
render(){
|
|
704
|
+
const {book} = this.state;
|
|
705
|
+
|
|
706
|
+
// A textfield to edit the title of a book
|
|
707
|
+
return <TextField
|
|
708
|
+
value={book.title}
|
|
709
|
+
onChange={store.handleChange(book, "title")}
|
|
710
|
+
error={object.getError("title")}
|
|
711
|
+
// E.g., in material UI the test field will be red in case of errors
|
|
712
|
+
/>;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
> Be aware: if you do `object.getError()` without specifying any attribute, you will receive object errors not associated with any field, such as API errors. This is similar to `store.on("error")`
|
|
718
|
+
|
|
627
719
|
|
|
628
720
|
## Editing objects
|
|
721
|
+
|
|
722
|
+
The preferred method to edit objects is using the `.set()` method that each object has, instead of editing directly the attributes. However, there are a few notions to keep in mind.
|
|
723
|
+
|
|
724
|
+
#### Client-side object validaion will not work when editing attributes directly.
|
|
725
|
+
|
|
726
|
+
You will be able to validate objects only if you use `.set()`. If you edit directly the attribute (e.g., `book.title = "test"`) errors will be discovered only by the API.
|
|
727
|
+
|
|
728
|
+
#### Auto save may not work when editing attributes directly.
|
|
729
|
+
|
|
629
730
|
The option `autoSave` can be `true`, `false`, or a number (milliseconds).
|
|
630
731
|
|
|
631
732
|
* When `autoSave` is set to `false`, the following operations are equivalent:
|
package/dist/BasicObj.js
CHANGED
|
@@ -24,20 +24,21 @@ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedec
|
|
|
24
24
|
|
|
25
25
|
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
26
26
|
|
|
27
|
-
function
|
|
27
|
+
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
|
|
28
28
|
|
|
29
|
-
function
|
|
29
|
+
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
|
|
30
30
|
|
|
31
|
-
function
|
|
31
|
+
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
|
|
32
32
|
|
|
33
33
|
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
|
|
34
34
|
|
|
35
|
-
function
|
|
35
|
+
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
|
|
36
36
|
|
|
37
37
|
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
38
38
|
|
|
39
39
|
var dateRegex = new RegExp("^[0-9][0-9][0-9][0-9]-[0-9].*T[0-9].*Z$");
|
|
40
40
|
exports.dateRegex = dateRegex;
|
|
41
|
+
var globalError = "_object";
|
|
41
42
|
|
|
42
43
|
function setValues(values, model, SubObj, parent, context) {
|
|
43
44
|
Object.keys(values).forEach(function (key) {
|
|
@@ -64,6 +65,10 @@ var _setHidden = /*#__PURE__*/new WeakMap();
|
|
|
64
65
|
|
|
65
66
|
var _id = /*#__PURE__*/new WeakMap();
|
|
66
67
|
|
|
68
|
+
var _error = /*#__PURE__*/new WeakMap();
|
|
69
|
+
|
|
70
|
+
var _model = /*#__PURE__*/new WeakMap();
|
|
71
|
+
|
|
67
72
|
var BasicObj = /*#__PURE__*/_createClass(function BasicObj(values, model) {
|
|
68
73
|
var _this = this;
|
|
69
74
|
|
|
@@ -79,10 +84,26 @@ var BasicObj = /*#__PURE__*/_createClass(function BasicObj(values, model) {
|
|
|
79
84
|
value: null
|
|
80
85
|
});
|
|
81
86
|
|
|
87
|
+
_classPrivateFieldInitSpec(this, _error, {
|
|
88
|
+
writable: true,
|
|
89
|
+
value: {}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
_classPrivateFieldInitSpec(this, _model, {
|
|
93
|
+
writable: true,
|
|
94
|
+
value: void 0
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
_defineProperty(this, "setId", function (id) {
|
|
98
|
+
_classPrivateFieldSet(_this, _id, id);
|
|
99
|
+
});
|
|
100
|
+
|
|
82
101
|
_defineProperty(this, "getId", function () {
|
|
83
102
|
if (!_classPrivateFieldGet(_this, _id)) {
|
|
84
103
|
if (_this.id && (typeof _this.id === "string" || typeof _this.id === "number")) {
|
|
85
104
|
_classPrivateFieldSet(_this, _id, _this.id.toString());
|
|
105
|
+
|
|
106
|
+
delete _this.setId;
|
|
86
107
|
} else {
|
|
87
108
|
_classPrivateFieldSet(_this, _id, (0, _uuid.v4)());
|
|
88
109
|
}
|
|
@@ -106,15 +127,39 @@ var BasicObj = /*#__PURE__*/_createClass(function BasicObj(values, model) {
|
|
|
106
127
|
}
|
|
107
128
|
|
|
108
129
|
_this[attribute] = value;
|
|
130
|
+
|
|
131
|
+
_classPrivateFieldGet(_this, _model).validateObjectAttribute(_this, attribute);
|
|
109
132
|
}
|
|
110
133
|
|
|
111
134
|
return _this.update();
|
|
112
135
|
});
|
|
113
136
|
|
|
114
|
-
_defineProperty(this, "
|
|
137
|
+
_defineProperty(this, "getError", function () {
|
|
115
138
|
var _classPrivateFieldGet3;
|
|
116
139
|
|
|
117
|
-
|
|
140
|
+
var attribute = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
141
|
+
var key = attribute ? attribute : globalError;
|
|
142
|
+
return (_classPrivateFieldGet3 = _classPrivateFieldGet(_this, _error)[key]) !== null && _classPrivateFieldGet3 !== void 0 ? _classPrivateFieldGet3 : false;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
_defineProperty(this, "setError", function (error) {
|
|
146
|
+
var attribute = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
147
|
+
|
|
148
|
+
if (error && attribute) {
|
|
149
|
+
_classPrivateFieldGet(_this, _error)[attribute] = error;
|
|
150
|
+
} else if (error && !attribute) {
|
|
151
|
+
_classPrivateFieldGet(_this, _error)[globalError] = error;
|
|
152
|
+
} else if (!error && attribute) {
|
|
153
|
+
delete _classPrivateFieldGet(_this, _error)[attribute];
|
|
154
|
+
} else {
|
|
155
|
+
_classPrivateFieldSet(_this, _error, {});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
_defineProperty(this, "setConstant", function (attribute, value) {
|
|
160
|
+
var _classPrivateFieldGet4;
|
|
161
|
+
|
|
162
|
+
_classPrivateFieldGet(_this, _setHidden)[attribute] = (_classPrivateFieldGet4 = _classPrivateFieldGet(_this, _setHidden)[attribute]) !== null && _classPrivateFieldGet4 !== void 0 ? _classPrivateFieldGet4 : value;
|
|
118
163
|
});
|
|
119
164
|
|
|
120
165
|
_defineProperty(this, "toJSON", function () {
|
|
@@ -153,6 +198,8 @@ var BasicObj = /*#__PURE__*/_createClass(function BasicObj(values, model) {
|
|
|
153
198
|
_defineProperty(this, "update", function () {
|
|
154
199
|
return Promise.resolve();
|
|
155
200
|
});
|
|
201
|
+
|
|
202
|
+
_classPrivateFieldSet(this, _model, model);
|
|
156
203
|
});
|
|
157
204
|
|
|
158
205
|
exports.BasicObj = BasicObj;
|
package/dist/Model.js
CHANGED
|
@@ -93,22 +93,29 @@ var _addRelationByFilter = /*#__PURE__*/new WeakMap();
|
|
|
93
93
|
|
|
94
94
|
var _removeHiddenFields = /*#__PURE__*/new WeakMap();
|
|
95
95
|
|
|
96
|
-
var _bulkOperation = /*#__PURE__*/new WeakMap();
|
|
97
|
-
|
|
98
96
|
var _toArray = /*#__PURE__*/new WeakMap();
|
|
99
97
|
|
|
100
98
|
var _unWrap = /*#__PURE__*/new WeakMap();
|
|
101
99
|
|
|
102
100
|
var _insertObjects = /*#__PURE__*/new WeakMap();
|
|
103
101
|
|
|
102
|
+
var _assignId = /*#__PURE__*/new WeakMap();
|
|
103
|
+
|
|
104
104
|
var _updateObjects = /*#__PURE__*/new WeakMap();
|
|
105
105
|
|
|
106
106
|
var _deleteObjects = /*#__PURE__*/new WeakMap();
|
|
107
107
|
|
|
108
|
+
var _hanldeApiError = /*#__PURE__*/new WeakMap();
|
|
109
|
+
|
|
110
|
+
var _cleanApiError = /*#__PURE__*/new WeakMap();
|
|
111
|
+
|
|
112
|
+
var _removeFromStoreSilentlyAfterFailure = /*#__PURE__*/new WeakMap();
|
|
113
|
+
|
|
108
114
|
var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
109
115
|
var _this = this,
|
|
110
116
|
_options$deep,
|
|
111
|
-
_options$parseMoment
|
|
117
|
+
_options$parseMoment,
|
|
118
|
+
_options$validate;
|
|
112
119
|
|
|
113
120
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
114
121
|
|
|
@@ -176,6 +183,31 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
176
183
|
value: void 0
|
|
177
184
|
});
|
|
178
185
|
|
|
186
|
+
_defineProperty(this, "validateObjectAttribute", function (object, key) {
|
|
187
|
+
var validate = _this.options.validate;
|
|
188
|
+
|
|
189
|
+
if (validate && validate[key]) {
|
|
190
|
+
try {
|
|
191
|
+
validate[key](object);
|
|
192
|
+
object.setError(false, key);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
object.setError(error.message, key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
_defineProperty(this, "isObjectValid", function (object) {
|
|
200
|
+
for (var key in object) {
|
|
201
|
+
if (typeof object[key] !== "function") {
|
|
202
|
+
if (object.getError(key)) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
});
|
|
210
|
+
|
|
179
211
|
_defineProperty(this, "getStore", function () {
|
|
180
212
|
return _classPrivateFieldGet(_this, _store);
|
|
181
213
|
});
|
|
@@ -270,15 +302,15 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
270
302
|
});
|
|
271
303
|
|
|
272
304
|
_defineProperty(this, "insertObjects", function (objects) {
|
|
273
|
-
return objects.length ? _classPrivateFieldGet(_this,
|
|
305
|
+
return objects.length ? _classPrivateFieldGet(_this, _insertObjects).call(_this, objects) : Promise.resolve();
|
|
274
306
|
});
|
|
275
307
|
|
|
276
308
|
_defineProperty(this, "updateObjects", function (objects) {
|
|
277
|
-
return objects.length ? _classPrivateFieldGet(_this,
|
|
309
|
+
return objects.length ? _classPrivateFieldGet(_this, _updateObjects).call(_this, objects) : Promise.resolve();
|
|
278
310
|
});
|
|
279
311
|
|
|
280
312
|
_defineProperty(this, "deleteObjects", function (objects) {
|
|
281
|
-
return objects.length ? _classPrivateFieldGet(_this,
|
|
313
|
+
return objects.length ? _classPrivateFieldGet(_this, _deleteObjects).call(_this, objects) : Promise.resolve();
|
|
282
314
|
});
|
|
283
315
|
|
|
284
316
|
_defineProperty(this, "factory", function (params) {
|
|
@@ -337,15 +369,6 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
337
369
|
}
|
|
338
370
|
});
|
|
339
371
|
|
|
340
|
-
_classPrivateFieldInitSpec(this, _bulkOperation, {
|
|
341
|
-
writable: true,
|
|
342
|
-
value: function value(objects, action) {
|
|
343
|
-
return action(objects.map(function (i) {
|
|
344
|
-
return _classPrivateFieldGet(_this, _removeHiddenFields).call(_this, i.toJSON());
|
|
345
|
-
}));
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
|
|
349
372
|
_classPrivateFieldInitSpec(this, _toArray, {
|
|
350
373
|
writable: true,
|
|
351
374
|
value: function value(data) {
|
|
@@ -373,7 +396,11 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
373
396
|
|
|
374
397
|
_classPrivateFieldInitSpec(this, _unWrap, {
|
|
375
398
|
writable: true,
|
|
376
|
-
value: function value(
|
|
399
|
+
value: function value(objects) {
|
|
400
|
+
var data = Object.values(objects).map(function (object) {
|
|
401
|
+
return _classPrivateFieldGet(_this, _removeHiddenFields).call(_this, object.toJSON());
|
|
402
|
+
});
|
|
403
|
+
|
|
377
404
|
if (data.value != null && Object.keys(data).length === 1) {
|
|
378
405
|
return data.value;
|
|
379
406
|
} else if (Array.isArray(data) && data.length === 1 && data[0].value != null && Object.keys(data[0]).length === 1) {
|
|
@@ -386,22 +413,109 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
386
413
|
|
|
387
414
|
_classPrivateFieldInitSpec(this, _insertObjects, {
|
|
388
415
|
writable: true,
|
|
389
|
-
value: function value(
|
|
390
|
-
|
|
416
|
+
value: function value(objects) {
|
|
417
|
+
var operation = "insert";
|
|
418
|
+
return (0, _modelHooksUtils.executeHook)(operation, _classPrivateFieldGet(_this, _insertHook), _classPrivateFieldGet(_this, _unWrap).call(_this, objects), _classPrivateFieldGet(_this, _axios)).then(function (data) {
|
|
419
|
+
if (data) _classPrivateFieldGet(_this, _assignId).call(_this, data, objects);
|
|
420
|
+
|
|
421
|
+
_classPrivateFieldGet(_this, _cleanApiError).call(_this, objects);
|
|
422
|
+
|
|
423
|
+
return data;
|
|
424
|
+
}).then(_classPrivateFieldGet(_this, _toArray))["catch"](function (error) {
|
|
425
|
+
_classPrivateFieldGet(_this, _removeFromStoreSilentlyAfterFailure).call(_this, objects);
|
|
426
|
+
|
|
427
|
+
return _classPrivateFieldGet(_this, _hanldeApiError).call(_this, error, objects, operation);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
_classPrivateFieldInitSpec(this, _assignId, {
|
|
433
|
+
writable: true,
|
|
434
|
+
value: function value(data, objects) {
|
|
435
|
+
if (data.length === 1) {
|
|
436
|
+
var newId = data[0].id;
|
|
437
|
+
objects[0].setId(newId);
|
|
438
|
+
delete objects[0].setId;
|
|
439
|
+
}
|
|
391
440
|
}
|
|
392
441
|
});
|
|
393
442
|
|
|
394
443
|
_classPrivateFieldInitSpec(this, _updateObjects, {
|
|
395
444
|
writable: true,
|
|
396
|
-
value: function value(
|
|
397
|
-
|
|
445
|
+
value: function value(objects) {
|
|
446
|
+
var operation = "update";
|
|
447
|
+
return (0, _modelHooksUtils.executeHook)(operation, _classPrivateFieldGet(_this, _updateHook), _classPrivateFieldGet(_this, _unWrap).call(_this, objects), _classPrivateFieldGet(_this, _axios)).then(function (data) {
|
|
448
|
+
_classPrivateFieldGet(_this, _cleanApiError).call(_this, objects);
|
|
449
|
+
|
|
450
|
+
return data;
|
|
451
|
+
}).then(_classPrivateFieldGet(_this, _toArray))["catch"](function (error) {
|
|
452
|
+
return _classPrivateFieldGet(_this, _hanldeApiError).call(_this, error, objects, operation);
|
|
453
|
+
});
|
|
398
454
|
}
|
|
399
455
|
});
|
|
400
456
|
|
|
401
457
|
_classPrivateFieldInitSpec(this, _deleteObjects, {
|
|
402
458
|
writable: true,
|
|
403
|
-
value: function value(
|
|
404
|
-
|
|
459
|
+
value: function value(objects) {
|
|
460
|
+
var operation = "delete";
|
|
461
|
+
return (0, _modelHooksUtils.executeHook)(operation, _classPrivateFieldGet(_this, _deleteHook), _classPrivateFieldGet(_this, _unWrap).call(_this, objects), _classPrivateFieldGet(_this, _axios)).then(function (data) {
|
|
462
|
+
_classPrivateFieldGet(_this, _cleanApiError).call(_this, objects);
|
|
463
|
+
|
|
464
|
+
return data;
|
|
465
|
+
}).then(_classPrivateFieldGet(_this, _toArray))["catch"](function (error) {
|
|
466
|
+
return _classPrivateFieldGet(_this, _hanldeApiError).call(_this, error, objects, operation);
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
_classPrivateFieldInitSpec(this, _hanldeApiError, {
|
|
472
|
+
writable: true,
|
|
473
|
+
value: function value(error, objects, operation) {
|
|
474
|
+
var _error$response$data, _error3, _error3$response, _ref, _error$message, _error4, _error5;
|
|
475
|
+
|
|
476
|
+
error = (_error$response$data = (_error3 = error) === null || _error3 === void 0 ? void 0 : (_error3$response = _error3.response) === null || _error3$response === void 0 ? void 0 : _error3$response.data) !== null && _error$response$data !== void 0 ? _error$response$data : error;
|
|
477
|
+
var targets = objects.map(function (object) {
|
|
478
|
+
return object.getId();
|
|
479
|
+
}); // Set errors
|
|
480
|
+
|
|
481
|
+
var strError = (_ref = (_error$message = (_error4 = error) === null || _error4 === void 0 ? void 0 : _error4.message) !== null && _error$message !== void 0 ? _error$message : (_error5 = error) === null || _error5 === void 0 ? void 0 : _error5.error) !== null && _ref !== void 0 ? _ref : error;
|
|
482
|
+
Object.values(objects).map(function (object) {
|
|
483
|
+
return object.setError(strError);
|
|
484
|
+
});
|
|
485
|
+
return Promise.reject(_objectSpread(_objectSpread({}, error), {}, {
|
|
486
|
+
targets: targets,
|
|
487
|
+
operation: operation
|
|
488
|
+
}));
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
_classPrivateFieldInitSpec(this, _cleanApiError, {
|
|
493
|
+
writable: true,
|
|
494
|
+
value: function value(objects) {
|
|
495
|
+
Object.values(objects).map(function (object) {
|
|
496
|
+
return object.setError(false);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
_classPrivateFieldInitSpec(this, _removeFromStoreSilentlyAfterFailure, {
|
|
502
|
+
writable: true,
|
|
503
|
+
value: function value(objects) {
|
|
504
|
+
var _iterator2 = _createForOfIteratorHelper(objects.map(function (object) {
|
|
505
|
+
return object.getId();
|
|
506
|
+
})),
|
|
507
|
+
_step2;
|
|
508
|
+
|
|
509
|
+
try {
|
|
510
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
511
|
+
var target = _step2.value;
|
|
512
|
+
delete _this.getStore().models[_this.getType()].storedObjects[target];
|
|
513
|
+
}
|
|
514
|
+
} catch (err) {
|
|
515
|
+
_iterator2.e(err);
|
|
516
|
+
} finally {
|
|
517
|
+
_iterator2.f();
|
|
518
|
+
}
|
|
405
519
|
}
|
|
406
520
|
});
|
|
407
521
|
|
|
@@ -410,7 +524,8 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
410
524
|
this.options = _objectSpread(_objectSpread({}, options), {}, {
|
|
411
525
|
deep: (_options$deep = options.deep) !== null && _options$deep !== void 0 ? _options$deep : true,
|
|
412
526
|
parseMoment: (_options$parseMoment = options.parseMoment) !== null && _options$parseMoment !== void 0 ? _options$parseMoment : false,
|
|
413
|
-
lazyLoad: options.lazyLoad
|
|
527
|
+
lazyLoad: options.lazyLoad,
|
|
528
|
+
validate: (_options$validate = options.validate) !== null && _options$validate !== void 0 ? _options$validate : {}
|
|
414
529
|
});
|
|
415
530
|
|
|
416
531
|
_classPrivateFieldSet(this, _store, null);
|
|
@@ -431,12 +546,12 @@ var Model = /*#__PURE__*/_createClass(function Model(name) {
|
|
|
431
546
|
throw new Error("The load option must be a function");
|
|
432
547
|
}
|
|
433
548
|
|
|
434
|
-
var
|
|
435
|
-
|
|
436
|
-
retrieveHook =
|
|
437
|
-
insertHook =
|
|
438
|
-
updateHook =
|
|
439
|
-
deleteHook =
|
|
549
|
+
var _ref2 = _typeof(options) === "object" ? (0, _modelHooksUtils.getHooksFromOptions)(options) : (0, _modelHooksUtils.getHooksFromUrl)(options),
|
|
550
|
+
_ref3 = _slicedToArray(_ref2, 4),
|
|
551
|
+
retrieveHook = _ref3[0],
|
|
552
|
+
insertHook = _ref3[1],
|
|
553
|
+
updateHook = _ref3[2],
|
|
554
|
+
deleteHook = _ref3[3];
|
|
440
555
|
|
|
441
556
|
_classPrivateFieldSet(this, _retrieveHook, retrieveHook);
|
|
442
557
|
|