dataflux 1.1.0 → 1.2.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 CHANGED
@@ -48,7 +48,7 @@ export default store;
48
48
 
49
49
  The store can be initialized with [various options](#configuration). You need only one store for the entire application, that's why you should declare it in its own file and import it in multiple places.
50
50
 
51
- The creation of a model requires at least a name and an url. GET, POST, PUT, and DELETE operations are going to be performed against the same url. [Models can be created with considerably more advanced options.](#models-creation)
51
+ The creation of a model requires at least a name and a url. GET, POST, PUT, and DELETE operations are going to be performed against the same url. [Models can be created with considerably more advanced options.](#models-creation)
52
52
 
53
53
  A JS object is automatically created for each item returned by the API, for each model. The object has the same properties of the JSON item plus some high-level method (see [objects methods](#objects-methods)).
54
54
  **All the objects are indexed in the store.**
@@ -219,39 +219,78 @@ A model can be simply created with:
219
219
  const book = new Model("book", `https://rest.example.net/api/v1/books`);
220
220
  ```
221
221
 
222
- However, in many cases more complex APIs require different settings for the various operations.
222
+ However, sometimes you may want to define a more complex interaction with the API. In such cases you can pass options to perform more elaborated model's initializations.
223
223
 
224
- Instead of an url, you can pass options to perform more elaborated Model's initializations.
224
+ ```js
225
+ const book = new Model("book", options);
226
+ ```
227
+
228
+ All the possible options for a model creation are (they are all optional):
229
+
230
+ | Name | Description | Default |
231
+ |----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|
232
+ | 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"}` |
233
+ | 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"}` |
234
+ | update | Describes the operation to update objects of the collection. It can be an operation object or a function. See [operations](#operations). | `{method: "put"}` |
235
+ | delete | Describes the operation to remove objects from the collection. It can be an operation object or a function. See [operations](#operations). | `{method: "delete"}` |
236
+ | 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 |
237
+ | headers | A dictionary of headers for the HTTP request. E.g., `{"Authorization": "bearer XXXX"}`. | No headers |
238
+ | 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). |
239
+ | 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 |
240
+
241
+
242
+ ### Operations
243
+ 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.
244
+
245
+ #### Operation object
246
+
247
+ An operation object is an object like follows:
248
+
249
+ ```json
250
+ {
251
+ "method": "get",
252
+ "url": "https://api.example.com",
253
+ "headers": {"Authorization": "bearer XXXX"}
254
+ }
255
+ ```
256
+
257
+ Usage example:
225
258
 
226
259
  ```js
227
260
  const options = {
261
+
228
262
  retrieve: {
229
263
  method: "get",
230
- url: "https://rest.example.net/api/v1/books"
264
+ url: "https://rest.example.net/api/v1/books",
265
+ headers: {} // Headers can be define per operation or globally
231
266
  },
267
+
232
268
  insert: {
233
269
  method: "post",
234
270
  url: "https://rest.example.net/api/v1/books"
235
271
  },
272
+
236
273
  update: {
237
274
  method: "put",
238
275
  url: "https://rest.example.net/api/v1/books"
239
276
  },
277
+
240
278
  delete: {
241
279
  method: "delete",
242
280
  url: "https://rest.example.net/api/v1/books"
243
- }
281
+ },
282
+
283
+ headers: {"Authorization": "bearer XXXX"} // Globally defined headers
244
284
  };
245
285
 
246
286
  const book = new Model("book", options);
247
287
  ```
248
- You don't necessarily need to specify a url for each operation. If a url is not specified for an operation, the url defined for the `GET` operation is used.
288
+ You don't need to specify all the attributes for each operation, only the ones you want to variate from the defaults (see table above). If a url is not specified for an operation, the url defined for the `GET` operation is used.
249
289
 
250
- For example, if you want to perform both inserts and updates with `PUT`, you can do:
290
+ For example, if you are ok with the default behaviour except you want to perform both inserts and updates with `PUT` (instead of post/put), you can do:
251
291
  ```js
252
292
  const options = {
253
293
  retrieve: {
254
- method: "get",
255
294
  url: "https://rest.example.net/api/v1/books"
256
295
  },
257
296
  insert: {
@@ -262,7 +301,9 @@ const options = {
262
301
  const book = new Model("book", options);
263
302
  ```
264
303
 
265
- Or, even more flexible, you can pass functions and handle yourself the operations. The functions MUST return promises.
304
+ #### Operation function
305
+
306
+ To be even more flexible, you can pass functions and handle yourself the operations. An operation function must return a promise, the promise must return an array of JSON objects when these are ready.
266
307
 
267
308
 
268
309
  ```js
@@ -276,7 +317,7 @@ const options = {
276
317
  insert: (data) => {
277
318
  // 1) recieve the data from the store
278
319
  // 2) transform the data however you like
279
- // 3) send data to server
320
+ // 3) send data to server and resolve empty
280
321
  return Promise.resolve();
281
322
  }
282
323
  };
@@ -284,6 +325,50 @@ const options = {
284
325
  const book = new Model("book", options);
285
326
  ```
286
327
 
328
+ #### Object enrichment
329
+
330
+ DataFlux objects can have a `load()` method which enables you to load extra attributes of an object.
331
+
332
+ Example of usage of `load()`:
333
+
334
+ ```js
335
+ console.log(book);
336
+ // {title: "The little prince"}
337
+
338
+ book.load();
339
+ // The book object will be updated and it will contain
340
+ // {id: 23, title: "The little prince", price: 9.99, year: 1943}
341
+ //
342
+ // If you are using React, book.load() will automatically update your state
343
+ ```
344
+
345
+
346
+
347
+ To enable such a method, you have to define the `load` option during model creation. The load option accepts a function that returns the complete object of a url. The function receives in input the current JSON object.
348
+
349
+ Example of creation of a model with `load` support:
350
+ ```js
351
+ const book = new Model("book", {
352
+ retrieve: {
353
+ url: "https://rest.example.net/api/v1/books/"
354
+ },
355
+ fields: ["title"], // By default the books will contain only the title
356
+ load: (object) => { // "object" contains the current object to be enriched
357
+
358
+ // Return the url where to retrieve the object
359
+ return "https://rest.example.net/api/v1/books/" + object.id;
360
+ }
361
+ });
362
+ ```
363
+ Alternatively, the `load` function can return directly the enriched object.
364
+ ```js
365
+ const book = new Model("book", {
366
+ load: (object) => {
367
+ return axios({...}).then(raw => raw.data);
368
+ }
369
+ });
370
+ ```
371
+
287
372
  ### Model relations
288
373
 
289
374
  Optionally, you can create relations among models.
package/dist/Model.js CHANGED
@@ -9,6 +9,8 @@ var _modelHooksUtils = require("./modelHooksUtils");
9
9
 
10
10
  var _batchPromises = _interopRequireDefault(require("batch-promises"));
11
11
 
12
+ var _axios2 = _interopRequireDefault(require("axios"));
13
+
12
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
15
 
14
16
  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); }
@@ -65,6 +67,10 @@ var _singleItemQuery = /*#__PURE__*/new WeakMap();
65
67
 
66
68
  var _batchSize = /*#__PURE__*/new WeakMap();
67
69
 
70
+ var _axios = /*#__PURE__*/new WeakMap();
71
+
72
+ var _loadFunction = /*#__PURE__*/new WeakMap();
73
+
68
74
  var _addRelationByField = /*#__PURE__*/new WeakMap();
69
75
 
70
76
  var _addRelationByFilter = /*#__PURE__*/new WeakMap();
@@ -79,9 +85,11 @@ var _updateObjects = /*#__PURE__*/new WeakMap();
79
85
 
80
86
  var _deleteObjects = /*#__PURE__*/new WeakMap();
81
87
 
82
- var Model = /*#__PURE__*/_createClass(function Model(name, options) {
88
+ var Model = /*#__PURE__*/_createClass(function Model(name) {
83
89
  var _this = this;
84
90
 
91
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
92
+
85
93
  _classCallCheck(this, Model);
86
94
 
87
95
  _classPrivateFieldInitSpec(this, _type, {
@@ -129,6 +137,16 @@ var Model = /*#__PURE__*/_createClass(function Model(name, options) {
129
137
  value: void 0
130
138
  });
131
139
 
140
+ _classPrivateFieldInitSpec(this, _axios, {
141
+ writable: true,
142
+ value: void 0
143
+ });
144
+
145
+ _classPrivateFieldInitSpec(this, _loadFunction, {
146
+ writable: true,
147
+ value: void 0
148
+ });
149
+
132
150
  _defineProperty(this, "getStore", function () {
133
151
  return _classPrivateFieldGet(_this, _store);
134
152
  });
@@ -141,6 +159,38 @@ var Model = /*#__PURE__*/_createClass(function Model(name, options) {
141
159
  }
142
160
  });
143
161
 
162
+ _defineProperty(this, "load", function (obj) {
163
+ return new Promise(function (resolve, reject) {
164
+ var applyData = function applyData(data) {
165
+ for (var att in data) {
166
+ if (att !== "id" || obj.id === undefined || att === "id" && obj.id === data.id) {
167
+ obj[att] = data[att];
168
+ } else {
169
+ return Promise.reject("The loading function cannot change the id of the object.");
170
+ }
171
+ }
172
+ };
173
+
174
+ if (_classPrivateFieldGet(_this, _loadFunction)) {
175
+ var res = _classPrivateFieldGet(_this, _loadFunction).call(_this, obj.toJson());
176
+
177
+ if (typeof res === "string") {
178
+ _classPrivateFieldGet(_this, _axios).call(_this, {
179
+ method: "get",
180
+ url: res,
181
+ responseType: "json"
182
+ }).then(function (data) {
183
+ return applyData(data.data);
184
+ }).then(resolve);
185
+ } else {
186
+ res.then(applyData).then(resolve);
187
+ }
188
+ } else {
189
+ reject("You must define a loading function in the model to enable load().");
190
+ }
191
+ });
192
+ });
193
+
144
194
  _defineProperty(this, "addRelation", function (model, param2, param3) {
145
195
  if (model) {
146
196
  _this.getStore().validateModel(model);
@@ -185,7 +235,7 @@ var Model = /*#__PURE__*/_createClass(function Model(name, options) {
185
235
  });
186
236
 
187
237
  _defineProperty(this, "retrieveAll", function () {
188
- return (0, _modelHooksUtils.executeHook)("retrieve", _classPrivateFieldGet(_this, _retrieveHook), null, _this.getStore().axios).then(_classPrivateFieldGet(_this, _toArray));
238
+ return (0, _modelHooksUtils.executeHook)("retrieve", _classPrivateFieldGet(_this, _retrieveHook), null, _classPrivateFieldGet(_this, _axios)).then(_classPrivateFieldGet(_this, _toArray));
189
239
  });
190
240
 
191
241
  _defineProperty(this, "insertObjects", function (objects) {
@@ -248,21 +298,21 @@ var Model = /*#__PURE__*/_createClass(function Model(name, options) {
248
298
  _classPrivateFieldInitSpec(this, _insertObjects, {
249
299
  writable: true,
250
300
  value: function value(data) {
251
- return (0, _modelHooksUtils.executeHook)("insert", _classPrivateFieldGet(_this, _insertHook), data, _this.getStore().axios).then(_classPrivateFieldGet(_this, _toArray));
301
+ return (0, _modelHooksUtils.executeHook)("insert", _classPrivateFieldGet(_this, _insertHook), data, _classPrivateFieldGet(_this, _axios)).then(_classPrivateFieldGet(_this, _toArray));
252
302
  }
253
303
  });
254
304
 
255
305
  _classPrivateFieldInitSpec(this, _updateObjects, {
256
306
  writable: true,
257
307
  value: function value(data) {
258
- return (0, _modelHooksUtils.executeHook)("update", _classPrivateFieldGet(_this, _updateHook), data, _this.getStore().axios).then(_classPrivateFieldGet(_this, _toArray));
308
+ return (0, _modelHooksUtils.executeHook)("update", _classPrivateFieldGet(_this, _updateHook), data, _classPrivateFieldGet(_this, _axios)).then(_classPrivateFieldGet(_this, _toArray));
259
309
  }
260
310
  });
261
311
 
262
312
  _classPrivateFieldInitSpec(this, _deleteObjects, {
263
313
  writable: true,
264
314
  value: function value(data) {
265
- return (0, _modelHooksUtils.executeHook)("delete", _classPrivateFieldGet(_this, _deleteHook), data, _this.getStore().axios).then(_classPrivateFieldGet(_this, _toArray));
315
+ return (0, _modelHooksUtils.executeHook)("delete", _classPrivateFieldGet(_this, _deleteHook), data, _classPrivateFieldGet(_this, _axios)).then(_classPrivateFieldGet(_this, _toArray));
266
316
  }
267
317
  });
268
318
 
@@ -272,10 +322,18 @@ var Model = /*#__PURE__*/_createClass(function Model(name, options) {
272
322
 
273
323
  _classPrivateFieldSet(this, _includes, {});
274
324
 
325
+ _classPrivateFieldSet(this, _axios, options.axios || _axios2["default"]);
326
+
327
+ _classPrivateFieldSet(this, _loadFunction, options.load || null);
328
+
275
329
  if (!name || !options) {
276
330
  throw new Error("A Model requires at least a name and a hook");
277
331
  }
278
332
 
333
+ if (_classPrivateFieldGet(this, _loadFunction) && typeof _classPrivateFieldGet(this, _loadFunction) !== "function") {
334
+ throw new Error("The load option must be a function");
335
+ }
336
+
279
337
  var _ref = _typeof(options) === "object" ? (0, _modelHooksUtils.getHooksFromOptions)(options) : (0, _modelHooksUtils.getHooksFromUrl)(options),
280
338
  _ref2 = _slicedToArray(_ref, 4),
281
339
  retrieveHook = _ref2[0],
@@ -9,8 +9,6 @@ exports["default"] = void 0;
9
9
 
10
10
  var _Store2 = _interopRequireDefault(require("./Store"));
11
11
 
12
- var _axios = _interopRequireDefault(require("axios"));
13
-
14
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
13
 
16
14
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -113,7 +111,6 @@ var PersistentStore = /*#__PURE__*/function (_Store) {
113
111
  }
114
112
  });
115
113
 
116
- _this.axios = options.axios || _axios["default"];
117
114
  _this._busy = false;
118
115
  _this._delayedSaveTimer = null;
119
116
 
@@ -39,6 +39,12 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.g
39
39
 
40
40
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
41
41
 
42
+ function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
43
+
44
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
45
+
46
+ function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
47
+
42
48
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
43
49
 
44
50
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -73,6 +79,8 @@ var addSubscriptionToContext = function addSubscriptionToContext(context, subKey
73
79
  };
74
80
  };
75
81
 
82
+ var _fixState = /*#__PURE__*/new WeakSet();
83
+
76
84
  var ReactStore = /*#__PURE__*/function (_ObserverStore) {
77
85
  _inherits(ReactStore, _ObserverStore);
78
86
 
@@ -85,6 +93,8 @@ var ReactStore = /*#__PURE__*/function (_ObserverStore) {
85
93
 
86
94
  _this2 = _super.call(this, options);
87
95
 
96
+ _classPrivateMethodInitSpec(_assertThisInitialized(_this2), _fixState);
97
+
88
98
  _defineProperty(_assertThisInitialized(_this2), "handleChange", function (object, name) {
89
99
  return function (event, rawValue) {
90
100
  var value = event ? event.target.type === "checkbox" ? event.target.checked : event.target.value : "";
@@ -98,14 +108,18 @@ var ReactStore = /*#__PURE__*/function (_ObserverStore) {
98
108
  _createClass(ReactStore, [{
99
109
  key: "findAll",
100
110
  value: function findAll(type, stateAttribute, context, filterFunction) {
111
+ _classPrivateMethodGet(this, _fixState, _fixState2).call(this, stateAttribute, context, false);
112
+
101
113
  var subKey = this.subscribe(type, function (data) {
102
- context.setState(_objectSpread(_objectSpread({}, context.state), {}, _defineProperty({}, stateAttribute, data)));
114
+ context.setState(_objectSpread(_objectSpread({}, context.state), {}, _defineProperty({}, stateAttribute, data || [])));
103
115
  }, filterFunction);
104
116
  addSubscriptionToContext(context, subKey);
105
117
  }
106
118
  }, {
107
119
  key: "findOne",
108
120
  value: function findOne(type, stateAttribute, context, filterFunction) {
121
+ _classPrivateMethodGet(this, _fixState, _fixState2).call(this, stateAttribute, context, true);
122
+
109
123
  var subKey = this.subscribe(type, function (data) {
110
124
  context.setState(_objectSpread(_objectSpread({}, context.state), {}, _defineProperty({}, stateAttribute, data && data.length ? data[0] : null)));
111
125
  }, filterFunction);
@@ -116,4 +130,10 @@ var ReactStore = /*#__PURE__*/function (_ObserverStore) {
116
130
  return ReactStore;
117
131
  }(_ObserverStore2["default"]);
118
132
 
119
- exports["default"] = ReactStore;
133
+ exports["default"] = ReactStore;
134
+
135
+ function _fixState2(stateAttribute, context, one) {
136
+ if (!context[stateAttribute]) {
137
+ context[stateAttribute] = one ? null : []; // side effect on state
138
+ }
139
+ }
package/dist/Store.js CHANGED
@@ -159,6 +159,10 @@ var Store = /*#__PURE__*/function () {
159
159
  return i.object;
160
160
  });
161
161
  return filterFunction ? all.filter(filterFunction) : all;
162
+ })["catch"](function (error) {
163
+ _this4.pubSub.publish("error", error);
164
+
165
+ return Promise.reject(error);
162
166
  });
163
167
  }
164
168
  }, {
@@ -320,6 +324,10 @@ function _loadObjects2(type) {
320
324
  var _this9 = this;
321
325
 
322
326
  var item = this.models[type];
327
+ this.pubSub.publish("loading", {
328
+ status: "start",
329
+ model: type
330
+ });
323
331
  return item.promise = item.model.retrieveAll().then(function (items) {
324
332
  var _iterator4 = _createForOfIteratorHelper(items),
325
333
  _step4;
@@ -335,5 +343,10 @@ function _loadObjects2(type) {
335
343
  } finally {
336
344
  _iterator4.f();
337
345
  }
346
+
347
+ _this9.pubSub.publish("loading", {
348
+ status: "end",
349
+ model: type
350
+ });
338
351
  });
339
352
  }
@@ -19,13 +19,46 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
19
19
 
20
20
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
21
21
 
22
+ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
23
+
24
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
25
+
26
+ function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
27
+
28
+ 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; } }
29
+
30
+ function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
31
+
32
+ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
33
+
34
+ function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
35
+
36
+ var _loaded = /*#__PURE__*/new WeakMap();
37
+
22
38
  var Obj = /*#__PURE__*/_createClass(function Obj(values, model) {
23
39
  var _this = this;
24
40
 
25
41
  _classCallCheck(this, Obj);
26
42
 
43
+ _classPrivateFieldInitSpec(this, _loaded, {
44
+ writable: true,
45
+ value: false
46
+ });
47
+
48
+ _defineProperty(this, "load", function () {
49
+ if (_classPrivateFieldGet(_this, _loaded)) {
50
+ return Promise.resolve(_this);
51
+ } else {
52
+ return _this.getModel().load(_this).then(function () {
53
+ _classPrivateFieldSet(_this, _loaded, true);
54
+
55
+ return _this;
56
+ });
57
+ }
58
+ });
59
+
27
60
  _defineProperty(this, "getFingerprint", function () {
28
- return (0, _fingerprint["default"])(_this.toJson());
61
+ return (0, _fingerprint["default"])(_this.toJSON());
29
62
  });
30
63
 
31
64
  _defineProperty(this, "get", function (attribute) {
@@ -54,7 +87,7 @@ var Obj = /*#__PURE__*/_createClass(function Obj(values, model) {
54
87
  return _this.getModel().getStore()["delete"]([_this]);
55
88
  });
56
89
 
57
- _defineProperty(this, "toJson", function () {
90
+ _defineProperty(this, "toJSON", function () {
58
91
  var attrs = Object.keys(_this);
59
92
  var out = {};
60
93
 
@@ -70,7 +103,7 @@ var Obj = /*#__PURE__*/_createClass(function Obj(values, model) {
70
103
  });
71
104
 
72
105
  _defineProperty(this, "toString", function () {
73
- return JSON.stringify(_this.toJson());
106
+ return JSON.stringify(_this.toJSON());
74
107
  });
75
108
 
76
109
  this.getModel = function () {
@@ -5,10 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports["default"] = fingerprint;
7
7
 
8
- var _crc = _interopRequireDefault(require("crc/crc32"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11
-
12
8
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
13
9
 
14
10
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -17,6 +13,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
17
13
 
18
14
  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); }
19
15
 
16
+ var CRC32 = require('crc-32');
17
+
20
18
  var _getFingerprint = function _getFingerprint(object) {
21
19
  switch (_typeof(object)) {
22
20
  case "object":
@@ -61,5 +59,5 @@ var getObjectFingerprint = function getObjectFingerprint(value) {
61
59
  };
62
60
 
63
61
  function fingerprint(object) {
64
- return (0, _crc["default"])(_getFingerprint(object)).toString(16);
62
+ return CRC32.str(_getFingerprint(object)).toString(16);
65
63
  }
@@ -5,23 +5,46 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.getHooksFromUrl = exports.getHooksFromOptions = exports.executeHook = void 0;
7
7
 
8
+ var _brembo = _interopRequireDefault(require("brembo"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11
+
8
12
  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); }
9
13
 
10
- var getDataStringHook = function getDataStringHook(url) {
11
- var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "get";
12
- var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
13
- var axios = arguments.length > 3 ? arguments[3] : undefined;
14
- return axios({
15
- url: url,
16
- method: method,
14
+ var getDataStringHook = function getDataStringHook(hook) {
15
+ var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
16
+ var axios = arguments.length > 2 ? arguments[2] : undefined;
17
+ var options = {
18
+ url: hook.url,
19
+ method: hook.method || "get",
17
20
  data: data,
18
21
  reponseType: 'json'
19
- }).then(function (data) {
22
+ };
23
+
24
+ if (hook.headers) {
25
+ options.headers = hook.headers;
26
+ }
27
+
28
+ if (hook.fields) {
29
+ setFields(options, hook);
30
+ }
31
+
32
+ return axios(options).then(function (data) {
20
33
  return data.data;
21
34
  });
22
35
  };
23
36
 
24
- var createHookItem = function createHookItem(optionItem, defaultMethod, defaultUrl) {
37
+ var setFields = function setFields(options, hook) {
38
+ options.headers = options.headers || {};
39
+ options.headers['X-Fields'] = hook.fields;
40
+ options.url = _brembo["default"].build(options.url, {
41
+ params: {
42
+ fields: hook.fields.join(",")
43
+ }
44
+ });
45
+ };
46
+
47
+ var createHookItem = function createHookItem(optionItem, defaultMethod, defaultUrl, options) {
25
48
  switch (_typeof(optionItem)) {
26
49
  case "undefined":
27
50
  if (!defaultUrl) {
@@ -44,7 +67,9 @@ var createHookItem = function createHookItem(optionItem, defaultMethod, defaultU
44
67
  case "object":
45
68
  return {
46
69
  method: optionItem.method || defaultMethod,
47
- url: optionItem.url || defaultUrl
70
+ url: optionItem.url || defaultUrl,
71
+ fields: options.fields || [],
72
+ headers: optionItem.headers || options.headers || {}
48
73
  };
49
74
 
50
75
  default:
@@ -54,7 +79,7 @@ var createHookItem = function createHookItem(optionItem, defaultMethod, defaultU
54
79
 
55
80
  var getHooksFromOptions = function getHooksFromOptions(options) {
56
81
  var defaultUrl = typeof options.retrieve === "function" ? null : options.retrieve.url;
57
- return [createHookItem(options.retrieve, "get", defaultUrl), createHookItem(options.insert, "post", defaultUrl), createHookItem(options.update, "put", defaultUrl), createHookItem(options["delete"], "delete", defaultUrl)];
82
+ return [createHookItem(options.retrieve, "get", defaultUrl, options), createHookItem(options.insert, "post", defaultUrl, options), createHookItem(options.update, "put", defaultUrl, options), createHookItem(options["delete"], "delete", defaultUrl, options)];
58
83
  };
59
84
 
60
85
  exports.getHooksFromOptions = getHooksFromOptions;
@@ -82,7 +107,7 @@ var executeHook = function executeHook(type, hook, data, axios) {
82
107
 
83
108
  switch (hookType) {
84
109
  case "object":
85
- return getDataStringHook(hook.url, hook.method, data, axios);
110
+ return getDataStringHook(hook, data, axios);
86
111
 
87
112
  case "function":
88
113
  return hook(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dataflux",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "DataFlux, automatically interfaces with your REST APIs to create a 2-way-synced local data store. Transparently manages data propagation in the React state.",
5
5
  "main": "dist/index.js",
6
6
  "bin": "dist/index.js",
@@ -78,13 +78,13 @@
78
78
  },
79
79
  "devDependencies": {
80
80
  "@babel/cli": "^7.16.8",
81
- "@babel/core": "^7.16.10",
81
+ "@babel/core": "^7.16.12",
82
82
  "@babel/node": "^7.16.8",
83
83
  "@babel/plugin-proposal-class-properties": "^7.16.7",
84
84
  "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
85
85
  "@babel/plugin-transform-async-to-generator": "^7.16.8",
86
86
  "@babel/plugin-transform-runtime": "^7.16.10",
87
- "@babel/preset-env": "^7.16.10",
87
+ "@babel/preset-env": "^7.16.11",
88
88
  "@babel/preset-react": "^7.16.7",
89
89
  "dotenv-cli": "^4.1.1",
90
90
  "release-it": "^14.12.3"
@@ -92,7 +92,8 @@
92
92
  "dependencies": {
93
93
  "axios": "^0.25.0",
94
94
  "batch-promises": "^0.0.3",
95
- "crc": "^4.1.0",
95
+ "brembo": "^2.0.6",
96
+ "crc-32": "^1.2.0",
96
97
  "uuid": "^8.3.2"
97
98
  },
98
99
  "resolutions": {}