@epam/uui-db 4.9.2 → 4.10.0-rc.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/index.js CHANGED
@@ -1,126 +1,157 @@
1
- module.exports =
2
- /******/ (function(modules) { // webpackBootstrap
3
- /******/ // The module cache
4
- /******/ var installedModules = {};
5
- /******/
6
- /******/ // The require function
7
- /******/ function __webpack_require__(moduleId) {
8
- /******/
9
- /******/ // Check if module is in cache
10
- /******/ if(installedModules[moduleId]) {
11
- /******/ return installedModules[moduleId].exports;
12
- /******/ }
13
- /******/ // Create a new module (and put it into the cache)
14
- /******/ var module = installedModules[moduleId] = {
15
- /******/ i: moduleId,
16
- /******/ l: false,
17
- /******/ exports: {}
18
- /******/ };
19
- /******/
20
- /******/ // Execute the module function
21
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
22
- /******/
23
- /******/ // Flag the module as loaded
24
- /******/ module.l = true;
25
- /******/
26
- /******/ // Return the exports of the module
27
- /******/ return module.exports;
28
- /******/ }
29
- /******/
30
- /******/
31
- /******/ // expose the modules object (__webpack_modules__)
32
- /******/ __webpack_require__.m = modules;
33
- /******/
34
- /******/ // expose the module cache
35
- /******/ __webpack_require__.c = installedModules;
36
- /******/
37
- /******/ // define getter function for harmony exports
38
- /******/ __webpack_require__.d = function(exports, name, getter) {
39
- /******/ if(!__webpack_require__.o(exports, name)) {
40
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
41
- /******/ }
42
- /******/ };
43
- /******/
44
- /******/ // define __esModule on exports
45
- /******/ __webpack_require__.r = function(exports) {
46
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
47
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
48
- /******/ }
49
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
50
- /******/ };
51
- /******/
52
- /******/ // create a fake namespace object
53
- /******/ // mode & 1: value is a module id, require it
54
- /******/ // mode & 2: merge all properties of value into the ns
55
- /******/ // mode & 4: return value when already ns object
56
- /******/ // mode & 8|1: behave like require
57
- /******/ __webpack_require__.t = function(value, mode) {
58
- /******/ if(mode & 1) value = __webpack_require__(value);
59
- /******/ if(mode & 8) return value;
60
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
61
- /******/ var ns = Object.create(null);
62
- /******/ __webpack_require__.r(ns);
63
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
64
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
65
- /******/ return ns;
66
- /******/ };
67
- /******/
68
- /******/ // getDefaultExport function for compatibility with non-harmony modules
69
- /******/ __webpack_require__.n = function(module) {
70
- /******/ var getter = module && module.__esModule ?
71
- /******/ function getDefault() { return module['default']; } :
72
- /******/ function getModuleExports() { return module; };
73
- /******/ __webpack_require__.d(getter, 'a', getter);
74
- /******/ return getter;
75
- /******/ };
76
- /******/
77
- /******/ // Object.prototype.hasOwnProperty.call
78
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
79
- /******/
80
- /******/ // __webpack_public_path__
81
- /******/ __webpack_require__.p = "/";
82
- /******/
83
- /******/
84
- /******/ // Load entry module and return exports
85
- /******/ return __webpack_require__(__webpack_require__.s = 0);
86
- /******/ })
87
- /************************************************************************/
88
- /******/ ({
1
+ 'use strict';
2
+
3
+ var shallowEqual = require('shallowequal');
4
+ var zip = require('lodash.zip');
5
+ var transform = require('lodash.transform');
6
+ var isEqual = require('lodash.isequal');
7
+ var I = require('immutable');
8
+ var uuiCore = require('@epam/uui-core');
9
+ var groupBy = require('lodash.groupby');
10
+ var map = require('lodash.map');
11
+ var merge = require('lodash.merge');
12
+ var countBy = require('lodash.countby');
13
+ var filter = require('lodash.filter');
14
+ var forEach = require('lodash.foreach');
15
+ var pick = require('lodash.pick');
16
+ var isEmpty = require('lodash.isempty');
17
+ var react = require('react');
18
+
19
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
+
21
+ function _interopNamespace(e) {
22
+ if (e && e.__esModule) return e;
23
+ var n = Object.create(null);
24
+ if (e) {
25
+ Object.keys(e).forEach(function (k) {
26
+ if (k !== 'default') {
27
+ var d = Object.getOwnPropertyDescriptor(e, k);
28
+ Object.defineProperty(n, k, d.get ? d : {
29
+ enumerable: true,
30
+ get: function () { return e[k]; }
31
+ });
32
+ }
33
+ });
34
+ }
35
+ n.default = e;
36
+ return Object.freeze(n);
37
+ }
38
+
39
+ var shallowEqual__default = /*#__PURE__*/_interopDefault(shallowEqual);
40
+ var zip__default = /*#__PURE__*/_interopDefault(zip);
41
+ var transform__default = /*#__PURE__*/_interopDefault(transform);
42
+ var isEqual__default = /*#__PURE__*/_interopDefault(isEqual);
43
+ var I__namespace = /*#__PURE__*/_interopNamespace(I);
44
+ var groupBy__default = /*#__PURE__*/_interopDefault(groupBy);
45
+ var map__default = /*#__PURE__*/_interopDefault(map);
46
+ var merge__default = /*#__PURE__*/_interopDefault(merge);
47
+ var countBy__default = /*#__PURE__*/_interopDefault(countBy);
48
+ var filter__default = /*#__PURE__*/_interopDefault(filter);
49
+ var forEach__default = /*#__PURE__*/_interopDefault(forEach);
50
+ var pick__default = /*#__PURE__*/_interopDefault(pick);
51
+ var isEmpty__default = /*#__PURE__*/_interopDefault(isEmpty);
52
+
53
+ exports.DbRelationType = void 0;
54
+ (function (DbRelationType) {
55
+ DbRelationType[DbRelationType["Aggregation"] = 0] = "Aggregation";
56
+ DbRelationType[DbRelationType["Association"] = 1] = "Association";
57
+ })(exports.DbRelationType || (exports.DbRelationType = {}));
58
+
59
+ // TBD: New typescript would contain better typing for this. Remove this hack after update.
60
+ let objectKeys = Object.keys;
61
+ function defaultCompareViewDependencies(prev, next) {
62
+ if (Array.isArray(prev) && Array.isArray(next)) {
63
+ if (prev.length === next.length) {
64
+ return zip__default.default(prev, next).every(([p, n]) => shallowEqual__default.default(p, n));
65
+ }
66
+ return false;
67
+ }
68
+ return shallowEqual__default.default(prev, next);
69
+ }
70
+ /**
71
+ * Deep diff between two object, using lodash
72
+ * @param {Object} object Object compared
73
+ * @param {Object} base Object to compare with
74
+ * @return {Object} Return a new object who represent the diff
75
+ */
76
+ function difference(object, base) {
77
+ function changes(object, base) {
78
+ return transform__default.default(object, function (result, value, key) {
79
+ if (!isEqual__default.default(value, base[key])) {
80
+ result[key] = (typeof value === "object" && typeof base[key] === "object") ? changes(value, base[key]) : value;
81
+ }
82
+ });
83
+ }
84
+ return changes(object, base);
85
+ }
86
+
87
+ class Db {
88
+ constructor(tables, reusedCache) {
89
+ this.tables = tables;
90
+ this.viewCache = new Map();
91
+ /* Views (cached db projections) */
92
+ this.valueAbsent = Symbol("ValueAbsent");
93
+ if (reusedCache) {
94
+ this.viewCache = new Map(reusedCache);
95
+ }
96
+ else {
97
+ this.viewCache = new Map();
98
+ }
99
+ }
100
+ update(mutate) {
101
+ const clone = new this.constructor(this.tables, this.viewCache);
102
+ clone.tables = Object.assign({}, this.tables);
103
+ mutate(clone);
104
+ return clone;
105
+ }
106
+ with(patch) {
107
+ return this.update(db => {
108
+ objectKeys(db.tables).forEach(entityName => {
109
+ if (patch[entityName]) {
110
+ db.tables[entityName] = db.tables[entityName].with(patch[entityName]);
111
+ }
112
+ });
113
+ });
114
+ }
115
+ runView(view, params) {
116
+ let cache = this.viewCache.get(view);
117
+ if (!cache) {
118
+ cache = new Map();
119
+ this.viewCache.set(view, cache);
120
+ }
121
+ const key = view.getKey ? view.getKey(params) : JSON.stringify(params);
122
+ let cacheItem = cache.get(key);
123
+ if (!cacheItem) {
124
+ cacheItem = {
125
+ dependencies: this.valueAbsent,
126
+ currentValue: this.valueAbsent,
127
+ computedOnDb: this.valueAbsent,
128
+ };
129
+ cache.set(key, cacheItem);
130
+ }
131
+ let shouldUpdate = this !== cacheItem.computedOnDb;
132
+ let dependencies = this.valueAbsent;
133
+ if (view.getDependencies) {
134
+ const compare = view.compareDependencies || defaultCompareViewDependencies;
135
+ dependencies = view.getDependencies(this, params);
136
+ shouldUpdate = !compare(cacheItem.dependencies, dependencies);
137
+ }
138
+ let previousValue = cacheItem.currentValue;
139
+ if (shouldUpdate) {
140
+ cacheItem.dependencies = dependencies;
141
+ let newValue = view.compute(this, params, dependencies);
142
+ cacheItem.computedOnDb = this;
143
+ let compareResults = view.compareResults || isEqual__default.default;
144
+ if (!compareResults(previousValue, newValue)) {
145
+ if (view.traceDiff) {
146
+ console.debug(difference(previousValue, newValue));
147
+ }
148
+ cacheItem.currentValue = newValue;
149
+ }
150
+ }
151
+ return cacheItem.currentValue;
152
+ }
153
+ }
89
154
 
90
- /***/ "../node_modules/tslib/tslib.es6.js":
91
- /*!******************************************!*\
92
- !*** ../node_modules/tslib/tslib.es6.js ***!
93
- \******************************************/
94
- /*! exports provided: __extends, __assign, __rest, __decorate, __param, __metadata, __awaiter, __generator, __createBinding, __exportStar, __values, __read, __spread, __spreadArrays, __spreadArray, __await, __asyncGenerator, __asyncDelegator, __asyncValues, __makeTemplateObject, __importStar, __importDefault, __classPrivateFieldGet, __classPrivateFieldSet, __classPrivateFieldIn */
95
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
96
-
97
- "use strict";
98
- __webpack_require__.r(__webpack_exports__);
99
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__extends", function() { return __extends; });
100
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__assign", function() { return __assign; });
101
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__rest", function() { return __rest; });
102
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__decorate", function() { return __decorate; });
103
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__param", function() { return __param; });
104
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__metadata", function() { return __metadata; });
105
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__awaiter", function() { return __awaiter; });
106
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__generator", function() { return __generator; });
107
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__createBinding", function() { return __createBinding; });
108
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__exportStar", function() { return __exportStar; });
109
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__values", function() { return __values; });
110
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__read", function() { return __read; });
111
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spread", function() { return __spread; });
112
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spreadArrays", function() { return __spreadArrays; });
113
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spreadArray", function() { return __spreadArray; });
114
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__await", function() { return __await; });
115
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncGenerator", function() { return __asyncGenerator; });
116
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncDelegator", function() { return __asyncDelegator; });
117
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncValues", function() { return __asyncValues; });
118
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__makeTemplateObject", function() { return __makeTemplateObject; });
119
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importStar", function() { return __importStar; });
120
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importDefault", function() { return __importDefault; });
121
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__classPrivateFieldGet", function() { return __classPrivateFieldGet; });
122
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__classPrivateFieldSet", function() { return __classPrivateFieldSet; });
123
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__classPrivateFieldIn", function() { return __classPrivateFieldIn; });
124
155
  /******************************************************************************
125
156
  Copyright (c) Microsoft Corporation.
126
157
 
@@ -135,33 +166,6 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
135
166
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
136
167
  PERFORMANCE OF THIS SOFTWARE.
137
168
  ***************************************************************************** */
138
- /* global Reflect, Promise */
139
-
140
- var extendStatics = function(d, b) {
141
- extendStatics = Object.setPrototypeOf ||
142
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
143
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
144
- return extendStatics(d, b);
145
- };
146
-
147
- function __extends(d, b) {
148
- if (typeof b !== "function" && b !== null)
149
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
150
- extendStatics(d, b);
151
- function __() { this.constructor = d; }
152
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
153
- }
154
-
155
- var __assign = function() {
156
- __assign = Object.assign || function __assign(t) {
157
- for (var s, i = 1, n = arguments.length; i < n; i++) {
158
- s = arguments[i];
159
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
160
- }
161
- return t;
162
- }
163
- return __assign.apply(this, arguments);
164
- }
165
169
 
166
170
  function __rest(s, e) {
167
171
  var t = {};
@@ -175,21 +179,6 @@ function __rest(s, e) {
175
179
  return t;
176
180
  }
177
181
 
178
- function __decorate(decorators, target, key, desc) {
179
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
180
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
181
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
182
- return c > 3 && r && Object.defineProperty(target, key, r), r;
183
- }
184
-
185
- function __param(paramIndex, decorator) {
186
- return function (target, key) { decorator(target, key, paramIndex); }
187
- }
188
-
189
- function __metadata(metadataKey, metadataValue) {
190
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
191
- }
192
-
193
182
  function __awaiter(thisArg, _arguments, P, generator) {
194
183
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
195
184
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -198,1614 +187,932 @@ function __awaiter(thisArg, _arguments, P, generator) {
198
187
  function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
199
188
  step((generator = generator.apply(thisArg, _arguments || [])).next());
200
189
  });
201
- }
202
-
203
- function __generator(thisArg, body) {
204
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
205
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
206
- function verb(n) { return function (v) { return step([n, v]); }; }
207
- function step(op) {
208
- if (f) throw new TypeError("Generator is already executing.");
209
- while (_) try {
210
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
211
- if (y = 0, t) op = [op[0] & 2, t.value];
212
- switch (op[0]) {
213
- case 0: case 1: t = op; break;
214
- case 4: _.label++; return { value: op[1], done: false };
215
- case 5: _.label++; y = op[1]; op = [0]; continue;
216
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
217
- default:
218
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
219
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
220
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
221
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
222
- if (t[2]) _.ops.pop();
223
- _.trys.pop(); continue;
224
- }
225
- op = body.call(thisArg, _);
226
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
227
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
228
- }
229
- }
230
-
231
- var __createBinding = Object.create ? (function(o, m, k, k2) {
232
- if (k2 === undefined) k2 = k;
233
- var desc = Object.getOwnPropertyDescriptor(m, k);
234
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
235
- desc = { enumerable: true, get: function() { return m[k]; } };
236
- }
237
- Object.defineProperty(o, k2, desc);
238
- }) : (function(o, m, k, k2) {
239
- if (k2 === undefined) k2 = k;
240
- o[k2] = m[k];
241
- });
242
-
243
- function __exportStar(m, o) {
244
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
245
- }
246
-
247
- function __values(o) {
248
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
249
- if (m) return m.call(o);
250
- if (o && typeof o.length === "number") return {
251
- next: function () {
252
- if (o && i >= o.length) o = void 0;
253
- return { value: o && o[i++], done: !o };
254
- }
255
- };
256
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
257
- }
258
-
259
- function __read(o, n) {
260
- var m = typeof Symbol === "function" && o[Symbol.iterator];
261
- if (!m) return o;
262
- var i = m.call(o), r, ar = [], e;
263
- try {
264
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
265
- }
266
- catch (error) { e = { error: error }; }
267
- finally {
268
- try {
269
- if (r && !r.done && (m = i["return"])) m.call(i);
270
- }
271
- finally { if (e) throw e.error; }
272
- }
273
- return ar;
274
- }
275
-
276
- /** @deprecated */
277
- function __spread() {
278
- for (var ar = [], i = 0; i < arguments.length; i++)
279
- ar = ar.concat(__read(arguments[i]));
280
- return ar;
281
- }
282
-
283
- /** @deprecated */
284
- function __spreadArrays() {
285
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
286
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
287
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
288
- r[k] = a[j];
289
- return r;
290
- }
291
-
292
- function __spreadArray(to, from, pack) {
293
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
294
- if (ar || !(i in from)) {
295
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
296
- ar[i] = from[i];
297
- }
298
- }
299
- return to.concat(ar || Array.prototype.slice.call(from));
300
- }
301
-
302
- function __await(v) {
303
- return this instanceof __await ? (this.v = v, this) : new __await(v);
304
- }
305
-
306
- function __asyncGenerator(thisArg, _arguments, generator) {
307
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
308
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
309
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
310
- function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
311
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
312
- function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
313
- function fulfill(value) { resume("next", value); }
314
- function reject(value) { resume("throw", value); }
315
- function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
316
- }
317
-
318
- function __asyncDelegator(o) {
319
- var i, p;
320
- return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
321
- function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
322
- }
323
-
324
- function __asyncValues(o) {
325
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
326
- var m = o[Symbol.asyncIterator], i;
327
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
328
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
329
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
330
- }
331
-
332
- function __makeTemplateObject(cooked, raw) {
333
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
334
- return cooked;
335
- };
336
-
337
- var __setModuleDefault = Object.create ? (function(o, v) {
338
- Object.defineProperty(o, "default", { enumerable: true, value: v });
339
- }) : function(o, v) {
340
- o["default"] = v;
341
- };
342
-
343
- function __importStar(mod) {
344
- if (mod && mod.__esModule) return mod;
345
- var result = {};
346
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
347
- __setModuleDefault(result, mod);
348
- return result;
349
- }
350
-
351
- function __importDefault(mod) {
352
- return (mod && mod.__esModule) ? mod : { default: mod };
353
- }
354
-
355
- function __classPrivateFieldGet(receiver, state, kind, f) {
356
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
357
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
358
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
359
- }
360
-
361
- function __classPrivateFieldSet(receiver, state, value, kind, f) {
362
- if (kind === "m") throw new TypeError("Private method is not writable");
363
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
364
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
365
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
366
- }
367
-
368
- function __classPrivateFieldIn(state, receiver) {
369
- if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
370
- return typeof state === "function" ? receiver === state : state.has(receiver);
371
- }
372
-
373
-
374
- /***/ }),
375
-
376
- /***/ "./index.tsx":
377
- /*!*******************!*\
378
- !*** ./index.tsx ***!
379
- \*******************/
380
- /*! no static exports found */
381
- /***/ (function(module, exports, __webpack_require__) {
382
-
383
- "use strict";
384
-
385
- Object.defineProperty(exports, "__esModule", { value: true });
386
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
387
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./src */ "./src/index.ts"), exports);
388
-
389
-
390
- /***/ }),
391
-
392
- /***/ "./src/Db.ts":
393
- /*!*******************!*\
394
- !*** ./src/Db.ts ***!
395
- \*******************/
396
- /*! no static exports found */
397
- /***/ (function(module, exports, __webpack_require__) {
398
-
399
- "use strict";
400
-
401
- Object.defineProperty(exports, "__esModule", { value: true });
402
- exports.Db = void 0;
403
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
404
- const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
405
- const lodash_isequal_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.isequal */ "lodash.isequal"));
406
- class Db {
407
- constructor(tables, reusedCache) {
408
- this.tables = tables;
409
- this.viewCache = new Map();
410
- /* Views (cached db projections) */
411
- this.valueAbsent = Symbol("ValueAbsent");
412
- if (reusedCache) {
413
- this.viewCache = new Map(reusedCache);
414
- }
415
- else {
416
- this.viewCache = new Map();
417
- }
418
- }
419
- update(mutate) {
420
- const clone = new this.constructor(this.tables, this.viewCache);
421
- clone.tables = Object.assign({}, this.tables);
422
- mutate(clone);
423
- return clone;
424
- }
425
- with(patch) {
426
- return this.update(db => {
427
- (0, utils_1.objectKeys)(db.tables).forEach(entityName => {
428
- if (patch[entityName]) {
429
- db.tables[entityName] = db.tables[entityName].with(patch[entityName]);
430
- }
431
- });
432
- });
433
- }
434
- runView(view, params) {
435
- let cache = this.viewCache.get(view);
436
- if (!cache) {
437
- cache = new Map();
438
- this.viewCache.set(view, cache);
439
- }
440
- const key = view.getKey ? view.getKey(params) : JSON.stringify(params);
441
- let cacheItem = cache.get(key);
442
- if (!cacheItem) {
443
- cacheItem = {
444
- dependencies: this.valueAbsent,
445
- currentValue: this.valueAbsent,
446
- computedOnDb: this.valueAbsent,
447
- };
448
- cache.set(key, cacheItem);
449
- }
450
- let shouldUpdate = this !== cacheItem.computedOnDb;
451
- let dependencies = this.valueAbsent;
452
- if (view.getDependencies) {
453
- const compare = view.compareDependencies || utils_1.defaultCompareViewDependencies;
454
- dependencies = view.getDependencies(this, params);
455
- shouldUpdate = !compare(cacheItem.dependencies, dependencies);
456
- }
457
- let previousValue = cacheItem.currentValue;
458
- if (shouldUpdate) {
459
- cacheItem.dependencies = dependencies;
460
- let newValue = view.compute(this, params, dependencies);
461
- cacheItem.computedOnDb = this;
462
- let compareResults = view.compareResults || lodash_isequal_1.default;
463
- if (!compareResults(previousValue, newValue)) {
464
- if (view.traceDiff) {
465
- console.debug((0, utils_1.difference)(previousValue, newValue));
466
- }
467
- cacheItem.currentValue = newValue;
468
- }
469
- }
470
- return cacheItem.currentValue;
471
- }
472
- }
473
- exports.Db = Db;
474
-
475
-
476
- /***/ }),
477
-
478
- /***/ "./src/DbRef.ts":
479
- /*!**********************!*\
480
- !*** ./src/DbRef.ts ***!
481
- \**********************/
482
- /*! no static exports found */
483
- /***/ (function(module, exports, __webpack_require__) {
484
-
485
- "use strict";
486
-
487
- Object.defineProperty(exports, "__esModule", { value: true });
488
- exports.DbRef = void 0;
489
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
490
- const patchHelpers_1 = __webpack_require__(/*! ./patchHelpers */ "./src/patchHelpers.ts");
491
- const tempIds_1 = __webpack_require__(/*! ./tempIds */ "./src/tempIds.tsx");
492
- const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
493
- const lodash_isempty_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.isempty */ "lodash.isempty"));
494
- const Loader_1 = __webpack_require__(/*! ./Loader */ "./src/Loader.ts");
495
- const uui_core_1 = __webpack_require__(/*! @epam/uui-core */ "@epam/uui-core");
496
- const SimpleLoadingTracker_1 = __webpack_require__(/*! ./SimpleLoadingTracker */ "./src/SimpleLoadingTracker.ts");
497
- const ListLoadingTracker_1 = __webpack_require__(/*! ./ListLoadingTracker */ "./src/ListLoadingTracker.ts");
498
- class DbRef {
499
- constructor(blank) {
500
- this.blank = blank;
501
- this.log = [];
502
- this.autoSave = true;
503
- this.savedPoint = 0;
504
- this.throttleSaveMs = 1000;
505
- /* Update subscriptions (aka live views) */
506
- this.lastSubscriptionId = 1;
507
- this.subscriptions = new Map();
508
- this.updateHandlers = [];
509
- /* Error Subscriptions */
510
- this.saveErrorHandlers = [];
511
- /* Save scheduling */
512
- this.enqueueSave = (0, uui_core_1.batch)(() => (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
513
- const cumulativePatch = this.makeCumulativePatch();
514
- const lastLogEntry = this.log.length;
515
- if ((0, lodash_isempty_1.default)(cumulativePatch)) {
516
- return;
517
- }
518
- try {
519
- const response = yield this.savePatch(cumulativePatch);
520
- this.applyResponse(response, lastLogEntry);
521
- this.update();
522
- }
523
- catch (error) {
524
- this.saveError(cumulativePatch, error);
525
- this.update();
526
- throw error;
527
- }
528
- }));
529
- this.handleBeforeUnload = (e) => {
530
- if (this.enqueueSave.isBusy) {
531
- e.returnValue = false;
532
- return false;
533
- }
534
- };
535
- this.loaders = [];
536
- this.db = blank;
537
- this.base = blank;
538
- this.tempIdMap = new tempIds_1.TempIdMap(blank);
539
- this.idMap = this.tempIdMap;
540
- window.addEventListener('beforeunload', this.handleBeforeUnload);
541
- }
542
- /** Saves all committed patches. Useful only if autoSave is off. */
543
- save() {
544
- return this.enqueueSave();
545
- }
546
- getAutoSave() {
547
- return this.autoSave;
548
- }
549
- setAutoSave(val) {
550
- if (this.autoSave != val) {
551
- this.autoSave = val;
552
- this.autoSave && this.enqueueSave();
553
- this.update();
554
- }
555
- }
556
- revert() {
557
- this.db = this.base;
558
- this.log = this.log.slice(0, this.savedPoint);
559
- this.update();
560
- }
561
- /** Concrete DbRef instances should override and implement their save logic in this method */
562
- savePatch(patch) {
563
- return Promise.resolve({ submit: {} });
564
- }
565
- /* Db Update logic */
566
- commit(patch) {
567
- const dbBeforeUpdate = this.db.with(patch);
568
- patch = this.beforeUpdate(patch, dbBeforeUpdate.tables, this.db.tables);
569
- patch = (0, patchHelpers_1.mergeEntityPatches)(this.db.tables, patch);
570
- this.log.push({ patch });
571
- this.db = this.db.with(patch);
572
- this.autoSave && this.enqueueSave(null, { throttleMs: this.throttleSaveMs });
573
- this.update();
574
- }
575
- beforeUpdate(patch, tables, prevTables) {
576
- let patchAndDependencies = {};
577
- (0, utils_1.objectKeys)(tables).filter(entityName => patch[entityName] && !tables[entityName].schema.beforeUpdate).forEach(entityName => {
578
- patchAndDependencies[entityName] = patch[entityName];
579
- });
580
- (0, utils_1.objectKeys)(tables).filter(entityName => patch[entityName] && tables[entityName].schema.beforeUpdate).forEach(entityName => {
581
- const schema = tables[entityName].schema;
582
- const { beforeUpdate } = schema;
583
- let context = {
584
- clientIdsMap: this.tempIdMap,
585
- schema,
586
- tables,
587
- prevTables,
588
- };
589
- const results = patch[entityName].map(e => beforeUpdate(e, context));
590
- const updatedPatch = { [entityName]: results.map(result => result.entity) };
591
- const dependentEntityPatchesForUpdate = (0, patchHelpers_1.unionPatches)(results.filter(result => result.dependentEntities).map(result => result.dependentEntities));
592
- const dependentEntityPatches = this.beforeUpdate(dependentEntityPatchesForUpdate, tables, prevTables);
593
- patchAndDependencies = (0, patchHelpers_1.mergeEntityPatches)(tables, (0, patchHelpers_1.unionPatches)([patchAndDependencies, updatedPatch, dependentEntityPatches]));
594
- });
595
- return patchAndDependencies;
596
- }
597
- commitFetch(patch) {
598
- patch = this.tempIdMap.serverToClientPatch(patch);
599
- this.rebase(this.base.with(patch));
600
- this.update();
601
- }
602
- rebase(newBase) {
603
- this.base = newBase;
604
- this.db = newBase;
605
- for (let n = this.savedPoint; n < this.log.length; n++) {
606
- this.db = this.db.with(this.log[n].patch);
607
- }
608
- }
609
- makeCumulativePatch() {
610
- const lastLogEntry = this.log.length;
611
- const logEntriesToSave = this.log.slice(this.savedPoint, lastLogEntry);
612
- let cumulativePatch = (0, patchHelpers_1.makeCumulativePatch)(this.db, logEntriesToSave.map(t => t.patch), this.tempIdMap);
613
- cumulativePatch = this.tempIdMap.clientToServerPatch(cumulativePatch);
614
- return cumulativePatch;
615
- }
616
- applyResponse(response, newSavedPoint) {
617
- this.tempIdMap.appendServerMapping(response);
618
- let serverPatch = (0, patchHelpers_1.flattenResponse)(response.submit, this.db.tables);
619
- serverPatch = (0, patchHelpers_1.mergeEntityPatches)(this.db.tables, serverPatch);
620
- this.savedPoint = newSavedPoint;
621
- this.base = this.db;
622
- this.commitFetch(serverPatch);
623
- }
624
- subscribe(view, params, onUpdate) {
625
- const id = this.lastSubscriptionId++;
626
- const subscription = {
627
- update: (params) => {
628
- subscription.currentParams = params;
629
- subscription.currentValue = this.db.runView(view, params);
630
- return subscription.currentValue;
631
- },
632
- currentParams: null,
633
- currentValue: null,
634
- onUpdate,
635
- unsubscribe: () => { this.subscriptions.delete(id); },
636
- };
637
- subscription.update(params);
638
- this.subscriptions.set(id, subscription);
639
- return subscription;
640
- }
641
- onUpdate(handler) {
642
- this.subscribe({
643
- compute: db => db,
644
- compareResults: (a, b) => a === b,
645
- }, null, handler);
646
- }
647
- update() {
648
- this.subscriptions.forEach(subscription => {
649
- const previousValue = subscription.currentValue;
650
- subscription.update(subscription.currentParams);
651
- if (subscription.currentValue !== previousValue && subscription.onUpdate) {
652
- subscription.onUpdate(subscription.currentValue);
653
- }
654
- });
655
- }
656
- onSaveError(handler) {
657
- this.saveErrorHandlers.push(handler);
658
- }
659
- saveError(request, error) {
660
- this.saveErrorHandlers.forEach(handler => handler(request, error));
661
- }
662
- makeLoader(options) {
663
- const loader = new Loader_1.Loader(this, () => new SimpleLoadingTracker_1.SimpleLoadingTracker(), options);
664
- this.loaders.push(loader);
665
- return loader;
666
- }
667
- makeListLoader(options) {
668
- const loader = new Loader_1.Loader(this, () => new ListLoadingTracker_1.ListLoadingTracker(), options);
669
- this.loaders.push(loader);
670
- return loader;
671
- }
672
- reload() {
673
- this.loaders = [];
674
- }
675
- }
676
- exports.DbRef = DbRef;
677
-
678
-
679
- /***/ }),
680
-
681
- /***/ "./src/DbTable.ts":
682
- /*!************************!*\
683
- !*** ./src/DbTable.ts ***!
684
- \************************/
685
- /*! no static exports found */
686
- /***/ (function(module, exports, __webpack_require__) {
687
-
688
- "use strict";
689
-
690
- Object.defineProperty(exports, "__esModule", { value: true });
691
- exports.DbTable = void 0;
692
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
693
- const I = (0, tslib_1.__importStar)(__webpack_require__(/*! immutable */ "immutable"));
694
- const uui_core_1 = __webpack_require__(/*! @epam/uui-core */ "@epam/uui-core");
695
- const immutable_1 = __webpack_require__(/*! immutable */ "immutable");
696
- class DbTable {
697
- constructor(schema, state, q) {
698
- this.schema = schema;
699
- this.state = state;
700
- this.q = q;
701
- if (!state) {
702
- const indexes = (schema.indexes || []).map(indexDef => {
703
- return {
704
- field: indexDef,
705
- map: I.Map(),
706
- };
707
- });
708
- this.state = { pk: I.Map(), indexes };
709
- }
710
- if (!q) {
711
- this.q = {};
712
- }
713
- }
714
- keyToImmutable(id) {
715
- if (Array.isArray(id)) {
716
- return I.List(id);
717
- }
718
- else {
719
- return id;
720
- }
721
- }
722
- byId(id) {
723
- return this.state.pk.get(this.keyToImmutable(id));
724
- }
725
- getId(entity) {
726
- if (Array.isArray(this.schema.primaryKey)) {
727
- return this.schema.primaryKey.map((key) => entity[key]);
728
- }
729
- return entity[this.schema.primaryKey];
730
- }
731
- update(mutate) {
732
- const clone = new this.constructor(this.schema, this.state, this.q);
733
- mutate(clone);
734
- return clone;
735
- }
736
- /* Mutation */
737
- with(patch) {
738
- const updates = patch.map(entityPatch => {
739
- const id = this.getId(entityPatch);
740
- const immId = this.keyToImmutable(id);
741
- const existing = this.state.pk.get(immId);
742
- let isDeleted = false;
743
- let updated = entityPatch;
744
- if (existing) {
745
- updated = Object.assign(Object.assign({}, existing), entityPatch);
746
- if (this.schema.deleteFlag) {
747
- isDeleted = updated[this.schema.deleteFlag] === true;
748
- }
749
- }
750
- return { id, immId, patch: entityPatch, existing, updated, isNew: !existing, isDeleted };
751
- });
752
- const idVal = immutable_1.Seq.Keyed(updates.map(entity => [entity.immId, entity.updated]));
753
- let newPk = this.state.pk.merge(idVal);
754
- // TBD: replace with deleteAll after migrating to immutable 4
755
- updates.filter(u => u.isDeleted).forEach(u => {
756
- newPk = newPk.delete(u.immId);
757
- });
758
- const newIndexes = this.state.indexes.map(index => {
759
- let newMap = index.map;
760
- for (let n = 0; n < updates.length; n++) {
761
- let update = updates[n];
762
- const newKey = update.updated[index.field];
763
- if (update.existing) {
764
- const oldKey = update.existing[index.field];
765
- if (oldKey !== newKey || update.isDeleted) {
766
- newMap = newMap.update(oldKey, set => set.remove(update.immId));
767
- }
768
- }
769
- if (!update.isDeleted) {
770
- newMap = newMap.update(newKey, I.Set(), set => set.add(update.immId));
771
- }
772
- }
773
- return Object.assign(Object.assign({}, index), { map: newMap });
774
- });
775
- const newState = { pk: newPk, indexes: newIndexes };
776
- return this.update(t => t.state = newState);
777
- }
778
- /* Query */
779
- find(filter) {
780
- return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { filter: Object.assign(Object.assign({}, this.q.filter), filter) }));
781
- }
782
- order(order) {
783
- return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: order }));
784
- }
785
- orderBy(field, direction = 'asc') {
786
- return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [{ field, direction }] }));
787
- }
788
- thenBy(field, direction) {
789
- return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [...t.q.sorting, { field, direction }] }));
790
- }
791
- search(text) {
792
- if (!this.schema.searchBy) {
793
- throw new Error(`Can't search in the ${this.schema.typeName} table - searchBy is not defined in the schema.`);
794
- }
795
- return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { search: text }));
796
- }
797
- /* Materializing */
798
- range(from, count) {
799
- return this.runQuery(Object.assign(Object.assign({}, this.q), { range: { from, count } }));
800
- }
801
- count() {
802
- return this.runQuery(this.q).length;
803
- }
804
- one() {
805
- return this.runQuery(this.q)[0] || null;
806
- }
807
- toArray() {
808
- return this.runQuery(this.q);
809
- }
810
- map(fn) {
811
- return this.toArray().map(fn);
812
- }
813
- /* Query implementation */
814
- runQuery(q) {
815
- let result = null;
816
- let filter = q.filter;
817
- if (filter) {
818
- let indexes = this.state.indexes;
819
- // Try to use indexes to fulfill filter conditions
820
- for (let n = 0; n < indexes.length; n++) {
821
- const index = indexes[n];
822
- if (index.field in filter) {
823
- const _a = filter, _b = index.field, condition = _a[_b], rest = (0, tslib_1.__rest)(_a, [typeof _b === "symbol" ? _b : _b + ""]);
824
- let conditionValues = null;
825
- if (condition != null && typeof condition === "object") {
826
- // Attempt to use index for 'in' and 'isNull' criteria.
827
- // We need to be very conservative here, indexed field should work the same way as getPatternPredicate. So
828
- // - it's better to leave corner cases to getPatternPredicate
829
- const _c = condition, { in: inCriteria, isNull: nullCriteria } = _c, restCriteria = (0, tslib_1.__rest)(_c, ["in", "isNull"]);
830
- if (inCriteria && Array.isArray(inCriteria)) {
831
- conditionValues = inCriteria;
832
- }
833
- else {
834
- restCriteria.in = inCriteria;
835
- }
836
- // Conditions in getPatternPredicate are composed with 'and' logic,
837
- // For now, let's not attempt to handle tricky cases like { in: [1,2] isNull: true }, or { in: [1, null] isNull: false }
838
- // - just leave this to getPatternPredicate.
839
- // Let's just handle the a most common case { isNull: true } - find all null and undefined
840
- if (nullCriteria === true && !conditionValues) {
841
- conditionValues = [null, undefined];
842
- }
843
- else {
844
- restCriteria.in = inCriteria;
845
- }
846
- // Keep other conditions, e.g. { in: [1,2,3], isNull: true } - in works via index, isNull - via filter
847
- if (Object.keys(restCriteria).length > 0) {
848
- rest[index.field] = restCriteria;
849
- }
850
- }
851
- else {
852
- conditionValues = [condition];
853
- }
854
- if (conditionValues) {
855
- result = [];
856
- for (let i = 0; i < conditionValues.length; i++) {
857
- const idsSet = index.map.get(conditionValues[i]);
858
- if (idsSet) {
859
- const idsArray = idsSet.toArray();
860
- for (let j = 0; j < idsArray.length; j++) {
861
- const item = this.state.pk.get(idsArray[j]);
862
- result.push(item);
863
- }
864
- }
865
- }
866
- filter = Object.keys(rest).length > 0 ? rest : null;
867
- break;
868
- }
869
- }
870
- }
871
- }
872
- if (!result) {
873
- result = this.state.pk.toArray();
874
- }
875
- if (filter) {
876
- let predicate = (0, uui_core_1.getFilterPredicate)(q.filter);
877
- result = result.filter(predicate);
878
- }
879
- if (q.search) {
880
- let searchFilter = (0, uui_core_1.getSearchFilter)(q.search);
881
- result = result.filter(item => searchFilter(this.schema.searchBy.map(field => item[field])));
882
- }
883
- if (q.sorting) {
884
- let comparer = (0, uui_core_1.getOrderComparer)(q.sorting);
885
- result = result.sort(comparer);
886
- }
887
- if (q.range) {
888
- result = result.slice(q.range.from, q.range.from + q.range.count);
889
- }
890
- return result;
891
- }
892
- }
893
- exports.DbTable = DbTable;
894
-
895
-
896
- /***/ }),
897
-
898
- /***/ "./src/ListLoadingTracker.ts":
899
- /*!***********************************!*\
900
- !*** ./src/ListLoadingTracker.ts ***!
901
- \***********************************/
902
- /*! no static exports found */
903
- /***/ (function(module, exports, __webpack_require__) {
904
-
905
- "use strict";
906
-
907
- Object.defineProperty(exports, "__esModule", { value: true });
908
- exports.ListLoadingTracker = void 0;
909
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
910
- class ListLoadingTracker {
911
- constructor(options) {
912
- this.options = options;
913
- this.cache = new Map();
914
- this.extractList = (options === null || options === void 0 ? void 0 : options.extractList) || ((r) => r);
915
- }
916
- prepare(request) {
917
- const { filter, sorting, search, range } = request, unknownFields = (0, tslib_1.__rest)(request, ["filter", "sorting", "search", "range"]);
918
- const options = {};
919
- if (filter) {
920
- options.filter = filter;
921
- }
922
- if (sorting) {
923
- options.sorting = sorting;
924
- }
925
- if (search) {
926
- options.search = search;
927
- }
928
- let keyObject = Object.assign(Object.assign({}, options), unknownFields);
929
- const key = JSON.stringify(keyObject);
930
- let entry = this.cache.get(key);
931
- if (!entry) {
932
- entry = { options, count: 0, maxCount: null, isComplete: false };
933
- this.cache.set(key, entry);
934
- }
935
- return { options, range, unknownFields, entry };
936
- }
937
- diff(request) {
938
- const { options, range, unknownFields, entry } = this.prepare(request);
939
- if (entry.isComplete) {
940
- return null;
941
- }
942
- if (!request.range) {
943
- return request;
944
- }
945
- else {
946
- const requestedMax = request.range.from + request.range.count;
947
- let missingCount = requestedMax - entry.count;
948
- if (entry.maxCount) {
949
- missingCount = Math.min(missingCount, entry.maxCount);
950
- }
951
- if (missingCount > 0) {
952
- return Object.assign(Object.assign(Object.assign({}, options), unknownFields), { range: { from: entry.count, count: requestedMax - entry.count } });
953
- }
954
- else {
955
- return null;
956
- }
957
- }
958
- }
959
- count(request) {
960
- const { entry } = this.prepare(request);
961
- return { knownCount: Math.max(entry.count, entry.maxCount), exactCount: entry.maxCount };
962
- }
963
- append(request, response) {
964
- const { options, range, unknownFields, entry } = this.prepare(request);
965
- if (response) {
966
- const list = this.extractList(response);
967
- if (list.count) {
968
- entry.maxCount = list.count;
969
- }
970
- if (!range) {
971
- entry.count = list.items.length;
972
- entry.maxCount = list.items.length;
973
- entry.isComplete = true;
974
- }
975
- else {
976
- const from = (list.from == null) ? range.from : list.from;
977
- if (list.items.length > 0) {
978
- entry.count = Math.max(entry.count, from + list.items.length);
979
- }
980
- if (list.items.length < range.count) {
981
- entry.maxCount = from + list.items.length;
982
- entry.count = entry.maxCount;
983
- entry.isComplete = true;
984
- }
985
- }
986
- }
987
- else {
988
- if (range) {
989
- entry.count = Math.max(entry.count, request.range.from + request.range.count);
990
- }
991
- else {
992
- entry.isComplete = true;
993
- }
994
- }
995
- }
996
- }
997
- exports.ListLoadingTracker = ListLoadingTracker;
998
-
999
-
1000
- /***/ }),
1001
-
1002
- /***/ "./src/Loader.ts":
1003
- /*!***********************!*\
1004
- !*** ./src/Loader.ts ***!
1005
- \***********************/
1006
- /*! no static exports found */
1007
- /***/ (function(module, exports, __webpack_require__) {
1008
-
1009
- "use strict";
1010
-
1011
- Object.defineProperty(exports, "__esModule", { value: true });
1012
- exports.Loader = void 0;
1013
- class Loader {
1014
- constructor(dbRef, getTracker, options) {
1015
- this.dbRef = dbRef;
1016
- this.getTracker = getTracker;
1017
- this.options = options;
1018
- this.currentRequests = new Set();
1019
- this.load = (inputRequest) => {
1020
- const result = {
1021
- isComplete: this.loaded.diff(inputRequest) == null,
1022
- isLoading: false,
1023
- request: inputRequest,
1024
- missing: this.loadedAndLoading.diff(inputRequest),
1025
- promise: null,
1026
- reload: null,
1027
- };
1028
- result.reload = () => {
1029
- result.missing = inputRequest;
1030
- this.loadImpl(result);
1031
- };
1032
- if (result.isComplete) {
1033
- // Everything requested is already loaded
1034
- result.isComplete = true;
1035
- result.isLoading = false;
1036
- result.promise = Promise.resolve();
1037
- return result;
1038
- }
1039
- else {
1040
- if (result.missing == null) {
1041
- // Everything requested is either loaded already, or being loaded
1042
- result.isComplete = false;
1043
- result.isLoading = true;
1044
- // There's no good way to tell which of current requests is querying requested data - there actually can be 2 of them.
1045
- // So we track all running requests, and await all of them in such case.
1046
- result.promise = Promise.all(this.currentRequests.entries()).then(() => { });
1047
- return result;
1048
- }
1049
- else {
1050
- // Something requested is not loaded, nor being loaded. Need to perform a new request.
1051
- this.loadImpl(result);
1052
- return result;
1053
- }
1054
- }
1055
- };
1056
- this.loaded = getTracker();
1057
- this.loadedAndLoading = getTracker();
1058
- }
1059
- loadImpl(state) {
1060
- this.loadedAndLoading.append(state.missing);
1061
- state.isLoading = true;
1062
- let serverRequest = state.missing;
1063
- if (this.options.clientToServerRequest) {
1064
- serverRequest = this.options.clientToServerRequest(serverRequest);
1065
- }
1066
- state.promise = this.options.api(serverRequest).then(result => {
1067
- this.loaded.append(state.missing, result);
1068
- this.loadedAndLoading.append(state.missing, result);
1069
- state.missing = null;
1070
- state.isLoading = false;
1071
- state.isComplete = true;
1072
- state.promise = Promise.resolve();
1073
- const flatten = this.options.convertToPatch(result);
1074
- this.options.postProcess && this.options.postProcess(flatten);
1075
- this.dbRef.commitFetch(flatten);
1076
- });
1077
- this.currentRequests.add(state.promise);
1078
- state.promise.finally(() => {
1079
- this.currentRequests.delete(state.promise);
1080
- });
1081
- return state.promise;
1082
- }
1083
- }
1084
- exports.Loader = Loader;
1085
-
1086
-
1087
- /***/ }),
1088
-
1089
- /***/ "./src/SimpleLoadingTracker.ts":
1090
- /*!*************************************!*\
1091
- !*** ./src/SimpleLoadingTracker.ts ***!
1092
- \*************************************/
1093
- /*! no static exports found */
1094
- /***/ (function(module, exports, __webpack_require__) {
1095
-
1096
- "use strict";
1097
-
1098
- Object.defineProperty(exports, "__esModule", { value: true });
1099
- exports.SimpleLoadingTracker = void 0;
1100
- class SimpleLoadingTracker {
1101
- constructor() {
1102
- this.set = new Set();
1103
- }
1104
- getKey(request) {
1105
- return JSON.stringify(request);
1106
- }
1107
- diff(request) {
1108
- return this.set.has(this.getKey(request)) ? null : request;
1109
- }
1110
- append(request, result) {
1111
- this.set.add(this.getKey(request));
1112
- }
1113
- }
1114
- exports.SimpleLoadingTracker = SimpleLoadingTracker;
1115
-
1116
-
1117
- /***/ }),
1118
-
1119
- /***/ "./src/index.ts":
1120
- /*!**********************!*\
1121
- !*** ./src/index.ts ***!
1122
- \**********************/
1123
- /*! no static exports found */
1124
- /***/ (function(module, exports, __webpack_require__) {
1125
-
1126
- "use strict";
1127
-
1128
- Object.defineProperty(exports, "__esModule", { value: true });
1129
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
1130
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./types */ "./src/types.ts"), exports);
1131
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./Db */ "./src/Db.ts"), exports);
1132
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./DbTable */ "./src/DbTable.ts"), exports);
1133
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./DbRef */ "./src/DbRef.ts"), exports);
1134
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./tempIds */ "./src/tempIds.tsx"), exports);
1135
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./utils */ "./src/utils.ts"), exports);
1136
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./patchHelpers */ "./src/patchHelpers.ts"), exports);
1137
- (0, tslib_1.__exportStar)(__webpack_require__(/*! ./reactHooks */ "./src/reactHooks.ts"), exports);
1138
-
1139
-
1140
- /***/ }),
1141
-
1142
- /***/ "./src/patchHelpers.ts":
1143
- /*!*****************************!*\
1144
- !*** ./src/patchHelpers.ts ***!
1145
- \*****************************/
1146
- /*! no static exports found */
1147
- /***/ (function(module, exports, __webpack_require__) {
1148
-
1149
- "use strict";
1150
-
1151
- Object.defineProperty(exports, "__esModule", { value: true });
1152
- exports.getEntityParentDependencies = exports.getParentEntities = exports.hasServerFields = exports.isNew = exports.getId = exports.isClientOnly = exports.makeCumulativePatch = exports.isPatchBlank = exports.flattenResponse = exports.mergeEntityPatches = exports.unionPatches = void 0;
1153
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
1154
- const types_1 = __webpack_require__(/*! ./types */ "./src/types.ts");
1155
- const I = (0, tslib_1.__importStar)(__webpack_require__(/*! immutable */ "immutable"));
1156
- const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
1157
- const lodash_groupby_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.groupby */ "lodash.groupby"));
1158
- const lodash_map_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.map */ "lodash.map"));
1159
- const lodash_merge_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.merge */ "lodash.merge"));
1160
- const lodash_countby_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.countby */ "lodash.countby"));
1161
- const lodash_filter_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.filter */ "lodash.filter"));
1162
- const lodash_foreach_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.foreach */ "lodash.foreach"));
1163
- const lodash_pick_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.pick */ "lodash.pick"));
1164
- function unionPatches(patches) {
1165
- const result = {};
1166
- patches.forEach(patch => {
1167
- (0, utils_1.objectKeys)(patch).forEach(tableName => {
1168
- result[tableName] = result[tableName] ? [...result[tableName], ...patch[tableName]] : patch[tableName];
1169
- });
1170
- });
1171
- return result;
1172
- }
1173
- exports.unionPatches = unionPatches;
1174
- function mergeEntityPatches(tables, patch) {
1175
- const result = {};
1176
- (0, utils_1.objectKeys)(patch).forEach(key => {
1177
- const table = tables[key];
1178
- const groupedEntities = (0, lodash_groupby_1.default)(patch[key], item => table.getId(item));
1179
- const tablePatch = (0, lodash_map_1.default)(groupedEntities, entities => {
1180
- const result = (0, lodash_merge_1.default)({}, ...entities);
1181
- if (true) {
1182
- const props = (0, utils_1.objectKeys)(result).filter(prop => Object.keys((0, lodash_countby_1.default)(entities.filter(entity => entity[prop] !== undefined), entity => entity[prop])).length > 1);
1183
- if (props.length) {
1184
- console.warn('mergeEntityPatches: Different property values found for the same entity.\nProperty names:\n', props, '\nEntities:\n', ...entities);
1185
- }
1186
- }
1187
- return result;
1188
- });
1189
- result[key] = tablePatch;
1190
- });
1191
- return result;
1192
- }
1193
- exports.mergeEntityPatches = mergeEntityPatches;
1194
- function flattenResponseHelper(result, object, tablesByTypeName) {
1195
- if (Array.isArray(object)) {
1196
- object.forEach(item => flattenResponseHelper(result, item, tablesByTypeName));
1197
- }
1198
- else if (typeof object === 'object') {
1199
- const clone = {};
1200
- let tableKey;
1201
- let fields = {};
1202
- if ('__typename' in object) {
1203
- const table = tablesByTypeName[object.__typename];
1204
- if (table) {
1205
- tableKey = table.schema.tableName;
1206
- fields = table.schema.fields;
1207
- }
1208
- }
1209
- for (let key in object) {
1210
- const value = object[key];
1211
- const field = fields[key];
1212
- if ((field && !!field.disableFlatten)
1213
- || typeof value !== 'object'
1214
- || value === null
1215
- || (Array.isArray(value) && value.every(item => typeof item !== 'object'))) {
1216
- clone[key] = value;
1217
- }
1218
- else {
1219
- flattenResponseHelper(result, value, tablesByTypeName);
1220
- }
1221
- }
1222
- if (tableKey) {
1223
- result[tableKey].push(clone);
1224
- }
1225
- }
1226
- }
1227
- function flattenResponse(response, tables) {
1228
- const result = {};
1229
- let tablesByTypeName = {};
1230
- Object.values(tables).forEach(table => tablesByTypeName[table.schema.typeName] = table);
1231
- (0, utils_1.objectKeys)(tables).forEach(tableName => tablesByTypeName);
1232
- (0, utils_1.objectKeys)(tables).forEach(key => result[key] = []);
1233
- flattenResponseHelper(result, response, tablesByTypeName);
1234
- return result;
1235
- }
1236
- exports.flattenResponse = flattenResponse;
1237
- function isPatchBlank(patch) {
1238
- return !(0, utils_1.objectKeys)(patch).some(key => patch[key].length > 0);
1239
- }
1240
- exports.isPatchBlank = isPatchBlank;
1241
- /**
1242
- * Given several patches, creates a new single patch with all fields from all entities in all patches.
1243
- */
1244
- function makeCumulativePatch(updatedDb, patches, clientIdsMap) {
1245
- const result = {};
1246
- (0, utils_1.objectKeys)(updatedDb.tables).forEach(entityName => {
1247
- const table = updatedDb.tables[entityName];
1248
- const schema = table.schema;
1249
- let ids = I.Set();
1250
- patches.forEach(patch => {
1251
- let filteredPatch = (patch[entityName] || []).filter(entity => hasServerFields(entity, schema, clientIdsMap, updatedDb.tables));
1252
- ids = ids.union(filteredPatch.map(e => table.getId(e)));
1253
- });
1254
- const entities = ids
1255
- .map(id => table.byId(id))
1256
- .filter(e => !isClientOnly(e, schema))
1257
- .toArray();
1258
- if (entities.length > 0) {
1259
- result[entityName] = entities;
1260
- }
1261
- });
1262
- return result;
1263
- }
1264
- exports.makeCumulativePatch = makeCumulativePatch;
1265
- function isClientOnly(entity, schema) {
1266
- if (typeof schema.isClientOnly === 'function') {
1267
- return schema.isClientOnly(entity);
1268
- }
1269
- return !!schema.isClientOnly;
1270
- }
1271
- exports.isClientOnly = isClientOnly;
1272
- function getId(entity, schema) {
1273
- if (typeof schema.primaryKey == 'string') {
1274
- return entity[schema.primaryKey];
1275
- }
1276
- const result = [];
1277
- (0, lodash_foreach_1.default)((0, lodash_pick_1.default)(entity, schema.primaryKey), (value) => {
1278
- result.push(value);
1279
- });
1280
- return result;
1281
- }
1282
- exports.getId = getId;
1283
- function isNew(entity, schema, clientIdsMap) {
1284
- const id = getId(entity, schema);
1285
- return !clientIdsMap.clientToServer(id);
1286
- }
1287
- exports.isNew = isNew;
1288
- function hasServerFields(entity, schema, clientIdsMap, tables) {
1289
- const fullEntity = Object.assign(Object.assign({}, tables[schema.tableName].byId(entity.id) || {}), entity);
1290
- if (isClientOnly(fullEntity, schema)) {
1291
- return false;
1292
- }
1293
- return (0, utils_1.objectKeys)(entity).some(fieldName => {
1294
- const fieldSchema = schema.fields[fieldName];
1295
- return !fieldSchema || !(fieldSchema.isClientOnly || fieldSchema.isReadOnly || (fieldSchema.isGenerated && !isNew(entity, schema, clientIdsMap)));
1296
- });
1297
- }
1298
- exports.hasServerFields = hasServerFields;
1299
- function getParentEntities(patch, tables) {
1300
- const dependenciesPatch = {};
1301
- (0, utils_1.objectKeys)(patch).forEach(key => {
1302
- const table = tables[key];
1303
- const tableSchema = table.schema;
1304
- const fields = (0, lodash_filter_1.default)((0, lodash_map_1.default)(tableSchema.fields, (field, name) => (Object.assign(Object.assign({}, field), { name }))), field => field.fk && field.fk.relationType == types_1.DbRelationType.Aggregation);
1305
- const tablePatch = patch[key];
1306
- fields.forEach(field => {
1307
- const { fk: { tableName }, name } = field;
1308
- tablePatch.forEach(entity => {
1309
- const actualTableName = (typeof tableName == 'function' ? tableName(entity) : tableName);
1310
- const dbEntity = table.byId(table.getId(entity));
1311
- const parentEntity = tables[actualTableName].byId(dbEntity[name]);
1312
- const idFields = (0, lodash_pick_1.default)(parentEntity, tables[actualTableName].schema.primaryKey);
1313
- if (parentEntity) {
1314
- dependenciesPatch[actualTableName] = dependenciesPatch[actualTableName] || [];
1315
- dependenciesPatch[actualTableName].push(idFields);
1316
- }
1317
- });
1318
- });
1319
- });
1320
- return dependenciesPatch;
1321
- }
1322
- exports.getParentEntities = getParentEntities;
1323
- function getEntityParentDependencies(entity, entityName, tables) {
1324
- let patch = { [entityName]: [entity] };
1325
- const resultPatches = [];
1326
- while (true) {
1327
- let parents = getParentEntities(patch, tables);
1328
- if (isPatchBlank(parents)) {
1329
- break;
1330
- }
1331
- resultPatches.push(parents);
1332
- patch = parents;
1333
- }
1334
- let result = unionPatches([patch, ...resultPatches]);
1335
- result = mergeEntityPatches(tables, result);
1336
- return result;
1337
- }
1338
- exports.getEntityParentDependencies = getEntityParentDependencies;
1339
-
1340
-
1341
- /***/ }),
1342
-
1343
- /***/ "./src/reactHooks.ts":
1344
- /*!***************************!*\
1345
- !*** ./src/reactHooks.ts ***!
1346
- \***************************/
1347
- /*! no static exports found */
1348
- /***/ (function(module, exports, __webpack_require__) {
1349
-
1350
- "use strict";
1351
-
1352
- Object.defineProperty(exports, "__esModule", { value: true });
1353
- exports.useDbView = exports.useDbRef = exports.DbContext = void 0;
1354
- const react_1 = __webpack_require__(/*! react */ "react");
1355
- exports.DbContext = (0, react_1.createContext)(null);
1356
- function useDbRef() {
1357
- return (0, react_1.useContext)(exports.DbContext);
1358
- }
1359
- exports.useDbRef = useDbRef;
1360
- function useDbView(fn, params, options) {
1361
- const dbRef = useDbRef();
1362
- const [state, setState] = (0, react_1.useState)();
1363
- const subscription = (0, react_1.useMemo)(() => dbRef.subscribe(Object.assign({ compute: fn }, options), params, setState), []);
1364
- subscription.update(params);
1365
- (0, react_1.useEffect)(() => {
1366
- return () => subscription.unsubscribe();
1367
- }, []);
1368
- return subscription.currentValue;
1369
- }
1370
- exports.useDbView = useDbView;
1371
-
1372
-
1373
- /***/ }),
1374
-
1375
- /***/ "./src/tempIds.tsx":
1376
- /*!*************************!*\
1377
- !*** ./src/tempIds.tsx ***!
1378
- \*************************/
1379
- /*! no static exports found */
1380
- /***/ (function(module, exports, __webpack_require__) {
1381
-
1382
- "use strict";
1383
-
1384
- Object.defineProperty(exports, "__esModule", { value: true });
1385
- exports.TempIdMap = exports.isTempId = exports.getTempId = void 0;
1386
- const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
1387
- let lastTempId = -1;
1388
- function getTempId() {
1389
- return --lastTempId;
1390
- }
1391
- exports.getTempId = getTempId;
1392
- function isTempId(val) {
1393
- return typeof val === 'number' && val < 0;
1394
- }
1395
- exports.isTempId = isTempId;
1396
- class TempIdMap {
1397
- constructor(db) {
1398
- this.db = db;
1399
- this.serverToClientIds = new Map();
1400
- this.clientToServerIds = new Map();
1401
- this.clientToServer = (id) => this.clientToServerIds.get(id);
1402
- this.serverToClient = (tableName, id) => this.getServerToClientMap(tableName).get(id);
1403
- this.clientToServerRequest = (request) => {
1404
- request = Object.assign({}, request);
1405
- if (request.filter) {
1406
- request.filter = this.clientToServerDataFilter(request.filter);
1407
- }
1408
- return request;
1409
- };
1410
- this.clientToServerDataFilter = (filter) => {
1411
- filter = Object.assign({}, filter);
1412
- const keys = Object.keys(filter);
1413
- // I hope that we can rely that there won't be any negative numbers, which are not IDs, in queries.
1414
- // We need to invent better heuristics or a schema otherwise.
1415
- const clientToServer = (id) => {
1416
- const found = this.clientToServer(id);
1417
- if (found) {
1418
- return found;
1419
- }
1420
- else {
1421
- return id;
1422
- }
1423
- };
1424
- for (let n = 0; n < keys.length; n++) {
1425
- const key = keys[n];
1426
- let condition = filter[key];
1427
- if (condition != null && typeof condition === "object") {
1428
- condition = Object.assign({}, condition);
1429
- if ('in' in condition && Array.isArray(condition.in) && condition.in.length) {
1430
- condition.in = condition.in.map(clientToServer);
1431
- }
1432
- }
1433
- else {
1434
- condition = clientToServer(condition);
1435
- }
1436
- filter[key] = condition;
1437
- }
1438
- return filter;
1439
- };
1440
- }
1441
- copyPatch(patch) {
1442
- const newPatch = Object.assign({}, patch);
1443
- (0, utils_1.objectKeys)(patch).forEach(tableName => {
1444
- let tablePatch = patch[tableName].map(entityPatch => (Object.assign({}, entityPatch)));
1445
- newPatch[tableName] = tablePatch;
1446
- });
1447
- return newPatch;
1448
- }
1449
- // Iterate thru every field in every patch for every table, matching certain field criteria. The patch is mutated!
1450
- mapFields(patch, filter, callback) {
1451
- (0, utils_1.objectKeys)(patch).forEach(tableName => {
1452
- const schema = this.db.tables[tableName].schema;
1453
- const fields = (0, utils_1.objectKeys)(schema.fields || [])
1454
- .map(fieldName => {
1455
- const fieldSchema = schema.fields[fieldName];
1456
- if (filter(fieldSchema, fieldName)) {
1457
- return { name: fieldName, schema: fieldSchema };
1458
- }
1459
- })
1460
- .filter(f => !!f);
1461
- if (!fields.length) {
1462
- return;
1463
- }
1464
- patch[tableName].forEach(entityPatch => {
1465
- for (let n = 0; n < fields.length; n++) {
1466
- const field = fields[n];
1467
- const fieldValue = entityPatch[field.name];
1468
- callback(field.name, field.schema, fieldValue, entityPatch, tableName);
1469
- }
1470
- });
1471
- });
1472
- }
1473
- getServerToClientMap(tableName) {
1474
- const existing = this.serverToClientIds.get(tableName);
1475
- if (existing) {
1476
- return existing;
1477
- }
1478
- else {
1479
- const newMap = new Map();
1480
- this.serverToClientIds.set(tableName, newMap);
1481
- return newMap;
1482
- }
1483
- }
1484
- serverToClientPatch(patch) {
1485
- patch = this.copyPatch(patch);
1486
- // We map PK in a separate pass, as we need to remap all PKs before re-mapping FKs
1487
- this.mapFields(patch, f => f.isGenerated, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
1488
- let clientId = this.getServerToClientMap(tableName).get(fieldValue);
1489
- if (!clientId) {
1490
- clientId = getTempId();
1491
- this.clientToServerIds.set(clientId, fieldValue);
1492
- this.getServerToClientMap(tableName).set(fieldValue, clientId);
1493
- }
1494
- entityPatch[fieldName] = clientId;
1495
- });
1496
- this.mapFields(patch, f => !!(f.fk || (f.default != null) || f.toClient), (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
1497
- let isUndefined = typeof (fieldValue) === 'undefined';
1498
- if (fieldSchema.default != null && fieldValue == null) {
1499
- fieldValue = fieldSchema.default;
1500
- isUndefined = false;
1501
- }
1502
- if (fieldSchema.fk && fieldValue != null) {
1503
- const fkTableName = typeof fieldSchema.fk.tableName === 'function' ? fieldSchema.fk.tableName(entityPatch) : fieldSchema.fk.tableName;
1504
- let clientId = this.getServerToClientMap(fkTableName).get(fieldValue);
1505
- if (!clientId) {
1506
- clientId = getTempId();
1507
- this.clientToServerIds.set(clientId, fieldValue);
1508
- this.getServerToClientMap(fkTableName).set(fieldValue, clientId);
1509
- }
1510
- fieldValue = clientId;
1511
- }
1512
- if (!isUndefined && fieldSchema.toClient) {
1513
- fieldValue = fieldSchema.toClient(fieldValue);
1514
- }
1515
- if (!isUndefined) {
1516
- entityPatch[fieldName] = fieldValue;
1517
- }
1518
- });
1519
- return patch;
1520
- }
1521
- clientToServerPatch(patch) {
1522
- patch = this.copyPatch(patch);
1523
- this.mapFields(patch, f => f.isGenerated || !!f.fk, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
1524
- if (fieldValue != null) {
1525
- const existingId = this.clientToServerIds.get(fieldValue);
1526
- if (existingId) {
1527
- entityPatch[fieldName] = existingId;
1528
- }
1529
- }
1530
- });
1531
- this.mapFields(patch, f => !(f.isClientOnly || f.isReadOnly) && !!f.toServer, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
1532
- entityPatch[fieldName] = fieldSchema.toServer(entityPatch[fieldName]);
1533
- });
1534
- this.mapFields(patch, meta => meta.isClientOnly || meta.isReadOnly, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
1535
- delete entityPatch[fieldName];
1536
- });
1537
- return patch;
1538
- }
1539
- appendServerMapping(response) {
1540
- (0, utils_1.objectKeys)(response.submit).forEach(tableName => {
1541
- if (this.db.tables[tableName]) {
1542
- const tablePatch = response.submit[tableName];
1543
- if (tablePatch) {
1544
- const serverToClientIds = this.getServerToClientMap(tableName);
1545
- const table = this.db.tables[tableName];
1546
- tablePatch.forEach(patch => {
1547
- if (isTempId(patch.id)) {
1548
- const clientId = patch.id;
1549
- const serverId = table.getId(patch.payload);
1550
- serverToClientIds.set(serverId, clientId);
1551
- this.clientToServerIds.set(clientId, serverId);
1552
- }
1553
- });
1554
- }
1555
- }
1556
- });
1557
- }
1558
- }
1559
- exports.TempIdMap = TempIdMap;
1560
-
1561
-
1562
- /***/ }),
1563
-
1564
- /***/ "./src/types.ts":
1565
- /*!**********************!*\
1566
- !*** ./src/types.ts ***!
1567
- \**********************/
1568
- /*! no static exports found */
1569
- /***/ (function(module, exports, __webpack_require__) {
1570
-
1571
- "use strict";
1572
-
1573
- Object.defineProperty(exports, "__esModule", { value: true });
1574
- exports.DbRelationType = void 0;
1575
- var DbRelationType;
1576
- (function (DbRelationType) {
1577
- DbRelationType[DbRelationType["Aggregation"] = 0] = "Aggregation";
1578
- DbRelationType[DbRelationType["Association"] = 1] = "Association";
1579
- })(DbRelationType = exports.DbRelationType || (exports.DbRelationType = {}));
1580
-
1581
-
1582
- /***/ }),
1583
-
1584
- /***/ "./src/utils.ts":
1585
- /*!**********************!*\
1586
- !*** ./src/utils.ts ***!
1587
- \**********************/
1588
- /*! no static exports found */
1589
- /***/ (function(module, exports, __webpack_require__) {
1590
-
1591
- "use strict";
1592
-
1593
- Object.defineProperty(exports, "__esModule", { value: true });
1594
- exports.difference = exports.defaultCompareViewDependencies = exports.objectKeys = void 0;
1595
- const tslib_1 = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
1596
- const shallowequal_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! shallowequal */ "shallowequal"));
1597
- const lodash_zip_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.zip */ "lodash.zip"));
1598
- const lodash_transform_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.transform */ "lodash.transform"));
1599
- const lodash_isequal_1 = (0, tslib_1.__importDefault)(__webpack_require__(/*! lodash.isequal */ "lodash.isequal"));
1600
- // TBD: New typescript would contain better typing for this. Remove this hack after update.
1601
- exports.objectKeys = Object.keys;
1602
- function defaultCompareViewDependencies(prev, next) {
1603
- if (Array.isArray(prev) && Array.isArray(next)) {
1604
- if (prev.length === next.length) {
1605
- return (0, lodash_zip_1.default)(prev, next).every(([p, n]) => (0, shallowequal_1.default)(p, n));
1606
- }
1607
- return false;
1608
- }
1609
- return (0, shallowequal_1.default)(prev, next);
1610
- }
1611
- exports.defaultCompareViewDependencies = defaultCompareViewDependencies;
1612
- /**
1613
- * Deep diff between two object, using lodash
1614
- * @param {Object} object Object compared
1615
- * @param {Object} base Object to compare with
1616
- * @return {Object} Return a new object who represent the diff
1617
- */
1618
- function difference(object, base) {
1619
- function changes(object, base) {
1620
- return (0, lodash_transform_1.default)(object, function (result, value, key) {
1621
- if (!(0, lodash_isequal_1.default)(value, base[key])) {
1622
- result[key] = (typeof value === "object" && typeof base[key] === "object") ? changes(value, base[key]) : value;
1623
- }
1624
- });
1625
- }
1626
- return changes(object, base);
1627
- }
1628
- exports.difference = difference;
1629
-
1630
-
1631
- /***/ }),
1632
-
1633
- /***/ 0:
1634
- /*!*************************!*\
1635
- !*** multi ./index.tsx ***!
1636
- \*************************/
1637
- /*! no static exports found */
1638
- /***/ (function(module, exports, __webpack_require__) {
1639
-
1640
- module.exports = __webpack_require__(/*! D:\dev\UUI-main\uui-db\index.tsx */"./index.tsx");
1641
-
1642
-
1643
- /***/ }),
1644
-
1645
- /***/ "@epam/uui-core":
1646
- /*!*********************************!*\
1647
- !*** external "@epam/uui-core" ***!
1648
- \*********************************/
1649
- /*! no static exports found */
1650
- /***/ (function(module, exports) {
1651
-
1652
- module.exports = require("@epam/uui-core");
1653
-
1654
- /***/ }),
1655
-
1656
- /***/ "immutable":
1657
- /*!****************************!*\
1658
- !*** external "immutable" ***!
1659
- \****************************/
1660
- /*! no static exports found */
1661
- /***/ (function(module, exports) {
1662
-
1663
- module.exports = require("immutable");
1664
-
1665
- /***/ }),
1666
-
1667
- /***/ "lodash.countby":
1668
- /*!*********************************!*\
1669
- !*** external "lodash.countby" ***!
1670
- \*********************************/
1671
- /*! no static exports found */
1672
- /***/ (function(module, exports) {
1673
-
1674
- module.exports = require("lodash.countby");
1675
-
1676
- /***/ }),
1677
-
1678
- /***/ "lodash.filter":
1679
- /*!********************************!*\
1680
- !*** external "lodash.filter" ***!
1681
- \********************************/
1682
- /*! no static exports found */
1683
- /***/ (function(module, exports) {
1684
-
1685
- module.exports = require("lodash.filter");
1686
-
1687
- /***/ }),
1688
-
1689
- /***/ "lodash.foreach":
1690
- /*!*********************************!*\
1691
- !*** external "lodash.foreach" ***!
1692
- \*********************************/
1693
- /*! no static exports found */
1694
- /***/ (function(module, exports) {
1695
-
1696
- module.exports = require("lodash.foreach");
1697
-
1698
- /***/ }),
1699
-
1700
- /***/ "lodash.groupby":
1701
- /*!*********************************!*\
1702
- !*** external "lodash.groupby" ***!
1703
- \*********************************/
1704
- /*! no static exports found */
1705
- /***/ (function(module, exports) {
1706
-
1707
- module.exports = require("lodash.groupby");
1708
-
1709
- /***/ }),
1710
-
1711
- /***/ "lodash.isempty":
1712
- /*!*********************************!*\
1713
- !*** external "lodash.isempty" ***!
1714
- \*********************************/
1715
- /*! no static exports found */
1716
- /***/ (function(module, exports) {
1717
-
1718
- module.exports = require("lodash.isempty");
1719
-
1720
- /***/ }),
1721
-
1722
- /***/ "lodash.isequal":
1723
- /*!*********************************!*\
1724
- !*** external "lodash.isequal" ***!
1725
- \*********************************/
1726
- /*! no static exports found */
1727
- /***/ (function(module, exports) {
1728
-
1729
- module.exports = require("lodash.isequal");
1730
-
1731
- /***/ }),
1732
-
1733
- /***/ "lodash.map":
1734
- /*!*****************************!*\
1735
- !*** external "lodash.map" ***!
1736
- \*****************************/
1737
- /*! no static exports found */
1738
- /***/ (function(module, exports) {
1739
-
1740
- module.exports = require("lodash.map");
1741
-
1742
- /***/ }),
1743
-
1744
- /***/ "lodash.merge":
1745
- /*!*******************************!*\
1746
- !*** external "lodash.merge" ***!
1747
- \*******************************/
1748
- /*! no static exports found */
1749
- /***/ (function(module, exports) {
1750
-
1751
- module.exports = require("lodash.merge");
1752
-
1753
- /***/ }),
1754
-
1755
- /***/ "lodash.pick":
1756
- /*!******************************!*\
1757
- !*** external "lodash.pick" ***!
1758
- \******************************/
1759
- /*! no static exports found */
1760
- /***/ (function(module, exports) {
1761
-
1762
- module.exports = require("lodash.pick");
1763
-
1764
- /***/ }),
1765
-
1766
- /***/ "lodash.transform":
1767
- /*!***********************************!*\
1768
- !*** external "lodash.transform" ***!
1769
- \***********************************/
1770
- /*! no static exports found */
1771
- /***/ (function(module, exports) {
1772
-
1773
- module.exports = require("lodash.transform");
1774
-
1775
- /***/ }),
1776
-
1777
- /***/ "lodash.zip":
1778
- /*!*****************************!*\
1779
- !*** external "lodash.zip" ***!
1780
- \*****************************/
1781
- /*! no static exports found */
1782
- /***/ (function(module, exports) {
1783
-
1784
- module.exports = require("lodash.zip");
1785
-
1786
- /***/ }),
1787
-
1788
- /***/ "react":
1789
- /*!************************!*\
1790
- !*** external "react" ***!
1791
- \************************/
1792
- /*! no static exports found */
1793
- /***/ (function(module, exports) {
1794
-
1795
- module.exports = require("react");
1796
-
1797
- /***/ }),
1798
-
1799
- /***/ "shallowequal":
1800
- /*!*******************************!*\
1801
- !*** external "shallowequal" ***!
1802
- \*******************************/
1803
- /*! no static exports found */
1804
- /***/ (function(module, exports) {
1805
-
1806
- module.exports = require("shallowequal");
1807
-
1808
- /***/ })
1809
-
1810
- /******/ });
1811
- //# sourceMappingURL=index.js.map
190
+ }
191
+
192
+ class DbTable {
193
+ constructor(schema, state, q) {
194
+ this.schema = schema;
195
+ this.state = state;
196
+ this.q = q;
197
+ if (!state) {
198
+ const indexes = (schema.indexes || []).map(indexDef => {
199
+ return {
200
+ field: indexDef,
201
+ map: I__namespace.Map(),
202
+ };
203
+ });
204
+ this.state = { pk: I__namespace.Map(), indexes };
205
+ }
206
+ if (!q) {
207
+ this.q = {};
208
+ }
209
+ }
210
+ keyToImmutable(id) {
211
+ if (Array.isArray(id)) {
212
+ return I__namespace.List(id);
213
+ }
214
+ else {
215
+ return id;
216
+ }
217
+ }
218
+ byId(id) {
219
+ return this.state.pk.get(this.keyToImmutable(id));
220
+ }
221
+ getId(entity) {
222
+ if (Array.isArray(this.schema.primaryKey)) {
223
+ return this.schema.primaryKey.map((key) => entity[key]);
224
+ }
225
+ return entity[this.schema.primaryKey];
226
+ }
227
+ update(mutate) {
228
+ const clone = new this.constructor(this.schema, this.state, this.q);
229
+ mutate(clone);
230
+ return clone;
231
+ }
232
+ /* Mutation */
233
+ with(patch) {
234
+ const updates = patch.map(entityPatch => {
235
+ const id = this.getId(entityPatch);
236
+ const immId = this.keyToImmutable(id);
237
+ const existing = this.state.pk.get(immId);
238
+ let isDeleted = false;
239
+ let updated = entityPatch;
240
+ if (existing) {
241
+ updated = Object.assign(Object.assign({}, existing), entityPatch);
242
+ if (this.schema.deleteFlag) {
243
+ isDeleted = updated[this.schema.deleteFlag] === true;
244
+ }
245
+ }
246
+ return { id, immId, patch: entityPatch, existing, updated, isNew: !existing, isDeleted };
247
+ });
248
+ const idVal = I.Seq.Keyed(updates.map(entity => [entity.immId, entity.updated]));
249
+ let newPk = this.state.pk.merge(idVal);
250
+ // TBD: replace with deleteAll after migrating to immutable 4
251
+ updates.filter(u => u.isDeleted).forEach(u => {
252
+ newPk = newPk.delete(u.immId);
253
+ });
254
+ const newIndexes = this.state.indexes.map(index => {
255
+ let newMap = index.map;
256
+ for (let n = 0; n < updates.length; n++) {
257
+ let update = updates[n];
258
+ const newKey = update.updated[index.field];
259
+ if (update.existing) {
260
+ const oldKey = update.existing[index.field];
261
+ if (oldKey !== newKey || update.isDeleted) {
262
+ newMap = newMap.update(oldKey, set => set.remove(update.immId));
263
+ }
264
+ }
265
+ if (!update.isDeleted) {
266
+ newMap = newMap.update(newKey, I__namespace.Set(), set => set.add(update.immId));
267
+ }
268
+ }
269
+ return Object.assign(Object.assign({}, index), { map: newMap });
270
+ });
271
+ const newState = { pk: newPk, indexes: newIndexes };
272
+ return this.update(t => t.state = newState);
273
+ }
274
+ /* Query */
275
+ find(filter) {
276
+ return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { filter: Object.assign(Object.assign({}, this.q.filter), filter) }));
277
+ }
278
+ order(order) {
279
+ return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: order }));
280
+ }
281
+ orderBy(field, direction = 'asc') {
282
+ return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [{ field, direction }] }));
283
+ }
284
+ thenBy(field, direction) {
285
+ return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [...t.q.sorting, { field, direction }] }));
286
+ }
287
+ search(text) {
288
+ if (!this.schema.searchBy) {
289
+ throw new Error(`Can't search in the ${this.schema.typeName} table - searchBy is not defined in the schema.`);
290
+ }
291
+ return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { search: text }));
292
+ }
293
+ /* Materializing */
294
+ range(from, count) {
295
+ return this.runQuery(Object.assign(Object.assign({}, this.q), { range: { from, count } }));
296
+ }
297
+ count() {
298
+ return this.runQuery(this.q).length;
299
+ }
300
+ one() {
301
+ return this.runQuery(this.q)[0] || null;
302
+ }
303
+ toArray() {
304
+ return this.runQuery(this.q);
305
+ }
306
+ map(fn) {
307
+ return this.toArray().map(fn);
308
+ }
309
+ /* Query implementation */
310
+ runQuery(q) {
311
+ let result = null;
312
+ let filter = q.filter;
313
+ if (filter) {
314
+ let indexes = this.state.indexes;
315
+ // Try to use indexes to fulfill filter conditions
316
+ for (let n = 0; n < indexes.length; n++) {
317
+ const index = indexes[n];
318
+ if (index.field in filter) {
319
+ const _a = filter, _b = index.field, condition = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
320
+ let conditionValues = null;
321
+ if (condition != null && typeof condition === "object") {
322
+ // Attempt to use index for 'in' and 'isNull' criteria.
323
+ // We need to be very conservative here, indexed field should work the same way as getPatternPredicate. So
324
+ // - it's better to leave corner cases to getPatternPredicate
325
+ const _c = condition, { in: inCriteria, isNull: nullCriteria } = _c, restCriteria = __rest(_c, ["in", "isNull"]);
326
+ if (inCriteria && Array.isArray(inCriteria)) {
327
+ conditionValues = inCriteria;
328
+ }
329
+ else {
330
+ restCriteria.in = inCriteria;
331
+ }
332
+ // Conditions in getPatternPredicate are composed with 'and' logic,
333
+ // For now, let's not attempt to handle tricky cases like { in: [1,2] isNull: true }, or { in: [1, null] isNull: false }
334
+ // - just leave this to getPatternPredicate.
335
+ // Let's just handle the a most common case { isNull: true } - find all null and undefined
336
+ if (nullCriteria === true && !conditionValues) {
337
+ conditionValues = [null, undefined];
338
+ }
339
+ else {
340
+ restCriteria.in = inCriteria;
341
+ }
342
+ // Keep other conditions, e.g. { in: [1,2,3], isNull: true } - in works via index, isNull - via filter
343
+ if (Object.keys(restCriteria).length > 0) {
344
+ rest[index.field] = restCriteria;
345
+ }
346
+ }
347
+ else {
348
+ conditionValues = [condition];
349
+ }
350
+ if (conditionValues) {
351
+ result = [];
352
+ for (let i = 0; i < conditionValues.length; i++) {
353
+ const idsSet = index.map.get(conditionValues[i]);
354
+ if (idsSet) {
355
+ const idsArray = idsSet.toArray();
356
+ for (let j = 0; j < idsArray.length; j++) {
357
+ const item = this.state.pk.get(idsArray[j]);
358
+ result.push(item);
359
+ }
360
+ }
361
+ }
362
+ filter = Object.keys(rest).length > 0 ? rest : null;
363
+ break;
364
+ }
365
+ }
366
+ }
367
+ }
368
+ if (!result) {
369
+ result = this.state.pk.toArray();
370
+ }
371
+ if (filter) {
372
+ let predicate = uuiCore.getFilterPredicate(q.filter);
373
+ result = result.filter(predicate);
374
+ }
375
+ if (q.search) {
376
+ let searchFilter = uuiCore.getSearchFilter(q.search);
377
+ result = result.filter(item => searchFilter(this.schema.searchBy.map(field => item[field])));
378
+ }
379
+ if (q.sorting) {
380
+ let comparer = uuiCore.getOrderComparer(q.sorting);
381
+ result = result.sort(comparer);
382
+ }
383
+ if (q.range) {
384
+ result = result.slice(q.range.from, q.range.from + q.range.count);
385
+ }
386
+ return result;
387
+ }
388
+ }
389
+
390
+ function unionPatches(patches) {
391
+ const result = {};
392
+ patches.forEach(patch => {
393
+ objectKeys(patch).forEach(tableName => {
394
+ result[tableName] = result[tableName] ? [...result[tableName], ...patch[tableName]] : patch[tableName];
395
+ });
396
+ });
397
+ return result;
398
+ }
399
+ function mergeEntityPatches(tables, patch) {
400
+ const result = {};
401
+ objectKeys(patch).forEach(key => {
402
+ const table = tables[key];
403
+ const groupedEntities = groupBy__default.default(patch[key], item => table.getId(item));
404
+ const tablePatch = map__default.default(groupedEntities, entities => {
405
+ const result = merge__default.default({}, ...entities);
406
+ if (process.env.NODE_ENV !== 'production') {
407
+ const props = objectKeys(result).filter(prop => Object.keys(countBy__default.default(entities.filter(entity => entity[prop] !== undefined), entity => entity[prop])).length > 1);
408
+ if (props.length) {
409
+ console.warn('mergeEntityPatches: Different property values found for the same entity.\nProperty names:\n', props, '\nEntities:\n', ...entities);
410
+ }
411
+ }
412
+ return result;
413
+ });
414
+ result[key] = tablePatch;
415
+ });
416
+ return result;
417
+ }
418
+ function flattenResponseHelper(result, object, tablesByTypeName) {
419
+ if (Array.isArray(object)) {
420
+ object.forEach(item => flattenResponseHelper(result, item, tablesByTypeName));
421
+ }
422
+ else if (typeof object === 'object') {
423
+ const clone = {};
424
+ let tableKey;
425
+ let fields = {};
426
+ if ('__typename' in object) {
427
+ const table = tablesByTypeName[object.__typename];
428
+ if (table) {
429
+ tableKey = table.schema.tableName;
430
+ fields = table.schema.fields;
431
+ }
432
+ }
433
+ for (let key in object) {
434
+ const value = object[key];
435
+ const field = fields[key];
436
+ if ((field && !!field.disableFlatten)
437
+ || typeof value !== 'object'
438
+ || value === null
439
+ || (Array.isArray(value) && value.every(item => typeof item !== 'object'))) {
440
+ clone[key] = value;
441
+ }
442
+ else {
443
+ flattenResponseHelper(result, value, tablesByTypeName);
444
+ }
445
+ }
446
+ if (tableKey) {
447
+ result[tableKey].push(clone);
448
+ }
449
+ }
450
+ }
451
+ function flattenResponse(response, tables) {
452
+ const result = {};
453
+ let tablesByTypeName = {};
454
+ Object.values(tables).forEach(table => tablesByTypeName[table.schema.typeName] = table);
455
+ objectKeys(tables).forEach(tableName => tablesByTypeName);
456
+ objectKeys(tables).forEach(key => result[key] = []);
457
+ flattenResponseHelper(result, response, tablesByTypeName);
458
+ return result;
459
+ }
460
+ function isPatchBlank(patch) {
461
+ return !objectKeys(patch).some(key => patch[key].length > 0);
462
+ }
463
+ /**
464
+ * Given several patches, creates a new single patch with all fields from all entities in all patches.
465
+ */
466
+ function makeCumulativePatch(updatedDb, patches, clientIdsMap) {
467
+ const result = {};
468
+ objectKeys(updatedDb.tables).forEach(entityName => {
469
+ const table = updatedDb.tables[entityName];
470
+ const schema = table.schema;
471
+ let ids = I__namespace.Set();
472
+ patches.forEach(patch => {
473
+ let filteredPatch = (patch[entityName] || []).filter(entity => hasServerFields(entity, schema, clientIdsMap, updatedDb.tables));
474
+ ids = ids.union(filteredPatch.map(e => table.getId(e)));
475
+ });
476
+ const entities = ids
477
+ .map(id => table.byId(id))
478
+ .filter(e => !isClientOnly(e, schema))
479
+ .toArray();
480
+ if (entities.length > 0) {
481
+ result[entityName] = entities;
482
+ }
483
+ });
484
+ return result;
485
+ }
486
+ function isClientOnly(entity, schema) {
487
+ if (typeof schema.isClientOnly === 'function') {
488
+ return schema.isClientOnly(entity);
489
+ }
490
+ return !!schema.isClientOnly;
491
+ }
492
+ function getId(entity, schema) {
493
+ if (typeof schema.primaryKey == 'string') {
494
+ return entity[schema.primaryKey];
495
+ }
496
+ const result = [];
497
+ forEach__default.default(pick__default.default(entity, schema.primaryKey), (value) => {
498
+ result.push(value);
499
+ });
500
+ return result;
501
+ }
502
+ function isNew(entity, schema, clientIdsMap) {
503
+ const id = getId(entity, schema);
504
+ return !clientIdsMap.clientToServer(id);
505
+ }
506
+ function hasServerFields(entity, schema, clientIdsMap, tables) {
507
+ const fullEntity = Object.assign(Object.assign({}, tables[schema.tableName].byId(entity.id) || {}), entity);
508
+ if (isClientOnly(fullEntity, schema)) {
509
+ return false;
510
+ }
511
+ return objectKeys(entity).some(fieldName => {
512
+ const fieldSchema = schema.fields[fieldName];
513
+ return !fieldSchema || !(fieldSchema.isClientOnly || fieldSchema.isReadOnly || (fieldSchema.isGenerated && !isNew(entity, schema, clientIdsMap)));
514
+ });
515
+ }
516
+ function getParentEntities(patch, tables) {
517
+ const dependenciesPatch = {};
518
+ objectKeys(patch).forEach(key => {
519
+ const table = tables[key];
520
+ const tableSchema = table.schema;
521
+ const fields = filter__default.default(map__default.default(tableSchema.fields, (field, name) => (Object.assign(Object.assign({}, field), { name }))), field => field.fk && field.fk.relationType == exports.DbRelationType.Aggregation);
522
+ const tablePatch = patch[key];
523
+ fields.forEach(field => {
524
+ const { fk: { tableName }, name } = field;
525
+ tablePatch.forEach(entity => {
526
+ const actualTableName = (typeof tableName == 'function' ? tableName(entity) : tableName);
527
+ const dbEntity = table.byId(table.getId(entity));
528
+ const parentEntity = tables[actualTableName].byId(dbEntity[name]);
529
+ const idFields = pick__default.default(parentEntity, tables[actualTableName].schema.primaryKey);
530
+ if (parentEntity) {
531
+ dependenciesPatch[actualTableName] = dependenciesPatch[actualTableName] || [];
532
+ dependenciesPatch[actualTableName].push(idFields);
533
+ }
534
+ });
535
+ });
536
+ });
537
+ return dependenciesPatch;
538
+ }
539
+ function getEntityParentDependencies(entity, entityName, tables) {
540
+ let patch = { [entityName]: [entity] };
541
+ const resultPatches = [];
542
+ while (true) {
543
+ let parents = getParentEntities(patch, tables);
544
+ if (isPatchBlank(parents)) {
545
+ break;
546
+ }
547
+ resultPatches.push(parents);
548
+ patch = parents;
549
+ }
550
+ let result = unionPatches([patch, ...resultPatches]);
551
+ result = mergeEntityPatches(tables, result);
552
+ return result;
553
+ }
554
+
555
+ let lastTempId = -1;
556
+ function getTempId() {
557
+ return --lastTempId;
558
+ }
559
+ function isTempId(val) {
560
+ return typeof val === 'number' && val < 0;
561
+ }
562
+ class TempIdMap {
563
+ constructor(db) {
564
+ this.db = db;
565
+ this.serverToClientIds = new Map();
566
+ this.clientToServerIds = new Map();
567
+ this.clientToServer = (id) => this.clientToServerIds.get(id);
568
+ this.serverToClient = (tableName, id) => this.getServerToClientMap(tableName).get(id);
569
+ this.clientToServerRequest = (request) => {
570
+ request = Object.assign({}, request);
571
+ if (request.filter) {
572
+ request.filter = this.clientToServerDataFilter(request.filter);
573
+ }
574
+ return request;
575
+ };
576
+ this.clientToServerDataFilter = (filter) => {
577
+ filter = Object.assign({}, filter);
578
+ const keys = Object.keys(filter);
579
+ // I hope that we can rely that there won't be any negative numbers, which are not IDs, in queries.
580
+ // We need to invent better heuristics or a schema otherwise.
581
+ const clientToServer = (id) => {
582
+ const found = this.clientToServer(id);
583
+ if (found) {
584
+ return found;
585
+ }
586
+ else {
587
+ return id;
588
+ }
589
+ };
590
+ for (let n = 0; n < keys.length; n++) {
591
+ const key = keys[n];
592
+ let condition = filter[key];
593
+ if (condition != null && typeof condition === "object") {
594
+ condition = Object.assign({}, condition);
595
+ if ('in' in condition && Array.isArray(condition.in) && condition.in.length) {
596
+ condition.in = condition.in.map(clientToServer);
597
+ }
598
+ }
599
+ else {
600
+ condition = clientToServer(condition);
601
+ }
602
+ filter[key] = condition;
603
+ }
604
+ return filter;
605
+ };
606
+ }
607
+ copyPatch(patch) {
608
+ const newPatch = Object.assign({}, patch);
609
+ objectKeys(patch).forEach(tableName => {
610
+ let tablePatch = patch[tableName].map(entityPatch => (Object.assign({}, entityPatch)));
611
+ newPatch[tableName] = tablePatch;
612
+ });
613
+ return newPatch;
614
+ }
615
+ // Iterate thru every field in every patch for every table, matching certain field criteria. The patch is mutated!
616
+ mapFields(patch, filter, callback) {
617
+ objectKeys(patch).forEach(tableName => {
618
+ const schema = this.db.tables[tableName].schema;
619
+ const fields = objectKeys(schema.fields || [])
620
+ .map(fieldName => {
621
+ const fieldSchema = schema.fields[fieldName];
622
+ if (filter(fieldSchema, fieldName)) {
623
+ return { name: fieldName, schema: fieldSchema };
624
+ }
625
+ })
626
+ .filter(f => !!f);
627
+ if (!fields.length) {
628
+ return;
629
+ }
630
+ patch[tableName].forEach(entityPatch => {
631
+ for (let n = 0; n < fields.length; n++) {
632
+ const field = fields[n];
633
+ const fieldValue = entityPatch[field.name];
634
+ callback(field.name, field.schema, fieldValue, entityPatch, tableName);
635
+ }
636
+ });
637
+ });
638
+ }
639
+ getServerToClientMap(tableName) {
640
+ const existing = this.serverToClientIds.get(tableName);
641
+ if (existing) {
642
+ return existing;
643
+ }
644
+ else {
645
+ const newMap = new Map();
646
+ this.serverToClientIds.set(tableName, newMap);
647
+ return newMap;
648
+ }
649
+ }
650
+ serverToClientPatch(patch) {
651
+ patch = this.copyPatch(patch);
652
+ // We map PK in a separate pass, as we need to remap all PKs before re-mapping FKs
653
+ this.mapFields(patch, f => f.isGenerated, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
654
+ let clientId = this.getServerToClientMap(tableName).get(fieldValue);
655
+ if (!clientId) {
656
+ clientId = getTempId();
657
+ this.clientToServerIds.set(clientId, fieldValue);
658
+ this.getServerToClientMap(tableName).set(fieldValue, clientId);
659
+ }
660
+ entityPatch[fieldName] = clientId;
661
+ });
662
+ this.mapFields(patch, f => !!(f.fk || (f.default != null) || f.toClient), (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
663
+ let isUndefined = typeof (fieldValue) === 'undefined';
664
+ if (fieldSchema.default != null && fieldValue == null) {
665
+ fieldValue = fieldSchema.default;
666
+ isUndefined = false;
667
+ }
668
+ if (fieldSchema.fk && fieldValue != null) {
669
+ const fkTableName = typeof fieldSchema.fk.tableName === 'function' ? fieldSchema.fk.tableName(entityPatch) : fieldSchema.fk.tableName;
670
+ let clientId = this.getServerToClientMap(fkTableName).get(fieldValue);
671
+ if (!clientId) {
672
+ clientId = getTempId();
673
+ this.clientToServerIds.set(clientId, fieldValue);
674
+ this.getServerToClientMap(fkTableName).set(fieldValue, clientId);
675
+ }
676
+ fieldValue = clientId;
677
+ }
678
+ if (!isUndefined && fieldSchema.toClient) {
679
+ fieldValue = fieldSchema.toClient(fieldValue);
680
+ }
681
+ if (!isUndefined) {
682
+ entityPatch[fieldName] = fieldValue;
683
+ }
684
+ });
685
+ return patch;
686
+ }
687
+ clientToServerPatch(patch) {
688
+ patch = this.copyPatch(patch);
689
+ this.mapFields(patch, f => f.isGenerated || !!f.fk, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
690
+ if (fieldValue != null) {
691
+ const existingId = this.clientToServerIds.get(fieldValue);
692
+ if (existingId) {
693
+ entityPatch[fieldName] = existingId;
694
+ }
695
+ }
696
+ });
697
+ this.mapFields(patch, f => !(f.isClientOnly || f.isReadOnly) && !!f.toServer, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
698
+ entityPatch[fieldName] = fieldSchema.toServer(entityPatch[fieldName]);
699
+ });
700
+ this.mapFields(patch, meta => meta.isClientOnly || meta.isReadOnly, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
701
+ delete entityPatch[fieldName];
702
+ });
703
+ return patch;
704
+ }
705
+ appendServerMapping(response) {
706
+ objectKeys(response.submit).forEach(tableName => {
707
+ if (this.db.tables[tableName]) {
708
+ const tablePatch = response.submit[tableName];
709
+ if (tablePatch) {
710
+ const serverToClientIds = this.getServerToClientMap(tableName);
711
+ const table = this.db.tables[tableName];
712
+ tablePatch.forEach(patch => {
713
+ if (isTempId(patch.id)) {
714
+ const clientId = patch.id;
715
+ const serverId = table.getId(patch.payload);
716
+ serverToClientIds.set(serverId, clientId);
717
+ this.clientToServerIds.set(clientId, serverId);
718
+ }
719
+ });
720
+ }
721
+ }
722
+ });
723
+ }
724
+ }
725
+
726
+ class Loader {
727
+ constructor(dbRef, getTracker, options) {
728
+ this.dbRef = dbRef;
729
+ this.getTracker = getTracker;
730
+ this.options = options;
731
+ this.currentRequests = new Set();
732
+ this.load = (inputRequest) => {
733
+ const result = {
734
+ isComplete: this.loaded.diff(inputRequest) == null,
735
+ isLoading: false,
736
+ request: inputRequest,
737
+ missing: this.loadedAndLoading.diff(inputRequest),
738
+ promise: null,
739
+ reload: null,
740
+ };
741
+ result.reload = () => {
742
+ result.missing = inputRequest;
743
+ this.loadImpl(result);
744
+ };
745
+ if (result.isComplete) {
746
+ // Everything requested is already loaded
747
+ result.isComplete = true;
748
+ result.isLoading = false;
749
+ result.promise = Promise.resolve();
750
+ return result;
751
+ }
752
+ else {
753
+ if (result.missing == null) {
754
+ // Everything requested is either loaded already, or being loaded
755
+ result.isComplete = false;
756
+ result.isLoading = true;
757
+ // There's no good way to tell which of current requests is querying requested data - there actually can be 2 of them.
758
+ // So we track all running requests, and await all of them in such case.
759
+ result.promise = Promise.all(this.currentRequests.entries()).then(() => { });
760
+ return result;
761
+ }
762
+ else {
763
+ // Something requested is not loaded, nor being loaded. Need to perform a new request.
764
+ this.loadImpl(result);
765
+ return result;
766
+ }
767
+ }
768
+ };
769
+ this.loaded = getTracker();
770
+ this.loadedAndLoading = getTracker();
771
+ }
772
+ loadImpl(state) {
773
+ this.loadedAndLoading.append(state.missing);
774
+ state.isLoading = true;
775
+ let serverRequest = state.missing;
776
+ if (this.options.clientToServerRequest) {
777
+ serverRequest = this.options.clientToServerRequest(serverRequest);
778
+ }
779
+ state.promise = this.options.api(serverRequest).then(result => {
780
+ this.loaded.append(state.missing, result);
781
+ this.loadedAndLoading.append(state.missing, result);
782
+ state.missing = null;
783
+ state.isLoading = false;
784
+ state.isComplete = true;
785
+ state.promise = Promise.resolve();
786
+ const flatten = this.options.convertToPatch(result);
787
+ this.options.postProcess && this.options.postProcess(flatten);
788
+ this.dbRef.commitFetch(flatten);
789
+ });
790
+ this.currentRequests.add(state.promise);
791
+ state.promise.finally(() => {
792
+ this.currentRequests.delete(state.promise);
793
+ });
794
+ return state.promise;
795
+ }
796
+ }
797
+
798
+ class SimpleLoadingTracker {
799
+ constructor() {
800
+ this.set = new Set();
801
+ }
802
+ getKey(request) {
803
+ return JSON.stringify(request);
804
+ }
805
+ diff(request) {
806
+ return this.set.has(this.getKey(request)) ? null : request;
807
+ }
808
+ append(request, result) {
809
+ this.set.add(this.getKey(request));
810
+ }
811
+ }
812
+
813
+ class ListLoadingTracker {
814
+ constructor(options) {
815
+ this.options = options;
816
+ this.cache = new Map();
817
+ this.extractList = (options === null || options === void 0 ? void 0 : options.extractList) || ((r) => r);
818
+ }
819
+ prepare(request) {
820
+ const { filter, sorting, search, range } = request, unknownFields = __rest(request, ["filter", "sorting", "search", "range"]);
821
+ const options = {};
822
+ if (filter) {
823
+ options.filter = filter;
824
+ }
825
+ if (sorting) {
826
+ options.sorting = sorting;
827
+ }
828
+ if (search) {
829
+ options.search = search;
830
+ }
831
+ let keyObject = Object.assign(Object.assign({}, options), unknownFields);
832
+ const key = JSON.stringify(keyObject);
833
+ let entry = this.cache.get(key);
834
+ if (!entry) {
835
+ entry = { options, count: 0, maxCount: null, isComplete: false };
836
+ this.cache.set(key, entry);
837
+ }
838
+ return { options, range, unknownFields, entry };
839
+ }
840
+ diff(request) {
841
+ const { options, range, unknownFields, entry } = this.prepare(request);
842
+ if (entry.isComplete) {
843
+ return null;
844
+ }
845
+ if (!request.range) {
846
+ return request;
847
+ }
848
+ else {
849
+ const requestedMax = request.range.from + request.range.count;
850
+ let missingCount = requestedMax - entry.count;
851
+ if (entry.maxCount) {
852
+ missingCount = Math.min(missingCount, entry.maxCount);
853
+ }
854
+ if (missingCount > 0) {
855
+ return Object.assign(Object.assign(Object.assign({}, options), unknownFields), { range: { from: entry.count, count: requestedMax - entry.count } });
856
+ }
857
+ else {
858
+ return null;
859
+ }
860
+ }
861
+ }
862
+ count(request) {
863
+ const { entry } = this.prepare(request);
864
+ return { knownCount: Math.max(entry.count, entry.maxCount), exactCount: entry.maxCount };
865
+ }
866
+ append(request, response) {
867
+ const { options, range, unknownFields, entry } = this.prepare(request);
868
+ if (response) {
869
+ const list = this.extractList(response);
870
+ if (list.count) {
871
+ entry.maxCount = list.count;
872
+ }
873
+ if (!range) {
874
+ entry.count = list.items.length;
875
+ entry.maxCount = list.items.length;
876
+ entry.isComplete = true;
877
+ }
878
+ else {
879
+ const from = (list.from == null) ? range.from : list.from;
880
+ if (list.items.length > 0) {
881
+ entry.count = Math.max(entry.count, from + list.items.length);
882
+ }
883
+ if (list.items.length < range.count) {
884
+ entry.maxCount = from + list.items.length;
885
+ entry.count = entry.maxCount;
886
+ entry.isComplete = true;
887
+ }
888
+ }
889
+ }
890
+ else {
891
+ if (range) {
892
+ entry.count = Math.max(entry.count, request.range.from + request.range.count);
893
+ }
894
+ else {
895
+ entry.isComplete = true;
896
+ }
897
+ }
898
+ }
899
+ }
900
+
901
+ class DbRef {
902
+ constructor(blank) {
903
+ this.blank = blank;
904
+ this.log = [];
905
+ this.autoSave = true;
906
+ this.savedPoint = 0;
907
+ this.throttleSaveMs = 1000;
908
+ /* Update subscriptions (aka live views) */
909
+ this.lastSubscriptionId = 1;
910
+ this.subscriptions = new Map();
911
+ this.updateHandlers = [];
912
+ /* Error Subscriptions */
913
+ this.saveErrorHandlers = [];
914
+ /* Save scheduling */
915
+ this.enqueueSave = uuiCore.batch(() => __awaiter(this, void 0, void 0, function* () {
916
+ const cumulativePatch = this.makeCumulativePatch();
917
+ const lastLogEntry = this.log.length;
918
+ if (isEmpty__default.default(cumulativePatch)) {
919
+ return;
920
+ }
921
+ try {
922
+ const response = yield this.savePatch(cumulativePatch);
923
+ this.applyResponse(response, lastLogEntry);
924
+ this.update();
925
+ }
926
+ catch (error) {
927
+ this.saveError(cumulativePatch, error);
928
+ this.update();
929
+ throw error;
930
+ }
931
+ }));
932
+ this.handleBeforeUnload = (e) => {
933
+ if (this.enqueueSave.isBusy) {
934
+ e.returnValue = false;
935
+ return false;
936
+ }
937
+ };
938
+ this.loaders = [];
939
+ this.db = blank;
940
+ this.base = blank;
941
+ this.tempIdMap = new TempIdMap(blank);
942
+ this.idMap = this.tempIdMap;
943
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
944
+ }
945
+ /** Saves all committed patches. Useful only if autoSave is off. */
946
+ save() {
947
+ return this.enqueueSave();
948
+ }
949
+ getAutoSave() {
950
+ return this.autoSave;
951
+ }
952
+ setAutoSave(val) {
953
+ if (this.autoSave != val) {
954
+ this.autoSave = val;
955
+ this.autoSave && this.enqueueSave();
956
+ this.update();
957
+ }
958
+ }
959
+ revert() {
960
+ this.db = this.base;
961
+ this.log = this.log.slice(0, this.savedPoint);
962
+ this.update();
963
+ }
964
+ /** Concrete DbRef instances should override and implement their save logic in this method */
965
+ savePatch(patch) {
966
+ return Promise.resolve({ submit: {} });
967
+ }
968
+ /* Db Update logic */
969
+ commit(patch) {
970
+ const dbBeforeUpdate = this.db.with(patch);
971
+ patch = this.beforeUpdate(patch, dbBeforeUpdate.tables, this.db.tables);
972
+ patch = mergeEntityPatches(this.db.tables, patch);
973
+ this.log.push({ patch });
974
+ this.db = this.db.with(patch);
975
+ this.autoSave && this.enqueueSave(null, { throttleMs: this.throttleSaveMs });
976
+ this.update();
977
+ }
978
+ beforeUpdate(patch, tables, prevTables) {
979
+ let patchAndDependencies = {};
980
+ objectKeys(tables).filter(entityName => patch[entityName] && !tables[entityName].schema.beforeUpdate).forEach(entityName => {
981
+ patchAndDependencies[entityName] = patch[entityName];
982
+ });
983
+ objectKeys(tables).filter(entityName => patch[entityName] && tables[entityName].schema.beforeUpdate).forEach(entityName => {
984
+ const schema = tables[entityName].schema;
985
+ const { beforeUpdate } = schema;
986
+ let context = {
987
+ clientIdsMap: this.tempIdMap,
988
+ schema,
989
+ tables,
990
+ prevTables,
991
+ };
992
+ const results = patch[entityName].map(e => beforeUpdate(e, context));
993
+ const updatedPatch = { [entityName]: results.map(result => result.entity) };
994
+ const dependentEntityPatchesForUpdate = unionPatches(results.filter(result => result.dependentEntities).map(result => result.dependentEntities));
995
+ const dependentEntityPatches = this.beforeUpdate(dependentEntityPatchesForUpdate, tables, prevTables);
996
+ patchAndDependencies = mergeEntityPatches(tables, unionPatches([patchAndDependencies, updatedPatch, dependentEntityPatches]));
997
+ });
998
+ return patchAndDependencies;
999
+ }
1000
+ commitFetch(patch) {
1001
+ patch = this.tempIdMap.serverToClientPatch(patch);
1002
+ this.rebase(this.base.with(patch));
1003
+ this.update();
1004
+ }
1005
+ rebase(newBase) {
1006
+ this.base = newBase;
1007
+ this.db = newBase;
1008
+ for (let n = this.savedPoint; n < this.log.length; n++) {
1009
+ this.db = this.db.with(this.log[n].patch);
1010
+ }
1011
+ }
1012
+ makeCumulativePatch() {
1013
+ const lastLogEntry = this.log.length;
1014
+ const logEntriesToSave = this.log.slice(this.savedPoint, lastLogEntry);
1015
+ let cumulativePatch = makeCumulativePatch(this.db, logEntriesToSave.map(t => t.patch), this.tempIdMap);
1016
+ cumulativePatch = this.tempIdMap.clientToServerPatch(cumulativePatch);
1017
+ return cumulativePatch;
1018
+ }
1019
+ applyResponse(response, newSavedPoint) {
1020
+ this.tempIdMap.appendServerMapping(response);
1021
+ let serverPatch = flattenResponse(response.submit, this.db.tables);
1022
+ serverPatch = mergeEntityPatches(this.db.tables, serverPatch);
1023
+ this.savedPoint = newSavedPoint;
1024
+ this.base = this.db;
1025
+ this.commitFetch(serverPatch);
1026
+ }
1027
+ subscribe(view, params, onUpdate) {
1028
+ const id = this.lastSubscriptionId++;
1029
+ const subscription = {
1030
+ update: (params) => {
1031
+ subscription.currentParams = params;
1032
+ subscription.currentValue = this.db.runView(view, params);
1033
+ return subscription.currentValue;
1034
+ },
1035
+ currentParams: null,
1036
+ currentValue: null,
1037
+ onUpdate,
1038
+ unsubscribe: () => { this.subscriptions.delete(id); },
1039
+ };
1040
+ subscription.update(params);
1041
+ this.subscriptions.set(id, subscription);
1042
+ return subscription;
1043
+ }
1044
+ onUpdate(handler) {
1045
+ this.subscribe({
1046
+ compute: db => db,
1047
+ compareResults: (a, b) => a === b,
1048
+ }, null, handler);
1049
+ }
1050
+ update() {
1051
+ this.subscriptions.forEach(subscription => {
1052
+ const previousValue = subscription.currentValue;
1053
+ subscription.update(subscription.currentParams);
1054
+ if (subscription.currentValue !== previousValue && subscription.onUpdate) {
1055
+ subscription.onUpdate(subscription.currentValue);
1056
+ }
1057
+ });
1058
+ }
1059
+ onSaveError(handler) {
1060
+ this.saveErrorHandlers.push(handler);
1061
+ }
1062
+ saveError(request, error) {
1063
+ this.saveErrorHandlers.forEach(handler => handler(request, error));
1064
+ }
1065
+ makeLoader(options) {
1066
+ const loader = new Loader(this, () => new SimpleLoadingTracker(), options);
1067
+ this.loaders.push(loader);
1068
+ return loader;
1069
+ }
1070
+ makeListLoader(options) {
1071
+ const loader = new Loader(this, () => new ListLoadingTracker(), options);
1072
+ this.loaders.push(loader);
1073
+ return loader;
1074
+ }
1075
+ reload() {
1076
+ this.loaders = [];
1077
+ }
1078
+ }
1079
+
1080
+ const DbContext = react.createContext(null);
1081
+ function useDbRef() {
1082
+ return react.useContext(DbContext);
1083
+ }
1084
+ function useDbView(fn, params, options) {
1085
+ const dbRef = useDbRef();
1086
+ const [state, setState] = react.useState();
1087
+ const subscription = react.useMemo(() => dbRef.subscribe(Object.assign({ compute: fn }, options), params, setState), []);
1088
+ subscription.update(params);
1089
+ react.useEffect(() => {
1090
+ return () => subscription.unsubscribe();
1091
+ }, []);
1092
+ return subscription.currentValue;
1093
+ }
1094
+
1095
+ exports.Db = Db;
1096
+ exports.DbContext = DbContext;
1097
+ exports.DbRef = DbRef;
1098
+ exports.DbTable = DbTable;
1099
+ exports.TempIdMap = TempIdMap;
1100
+ exports.defaultCompareViewDependencies = defaultCompareViewDependencies;
1101
+ exports.difference = difference;
1102
+ exports.flattenResponse = flattenResponse;
1103
+ exports.getEntityParentDependencies = getEntityParentDependencies;
1104
+ exports.getId = getId;
1105
+ exports.getParentEntities = getParentEntities;
1106
+ exports.getTempId = getTempId;
1107
+ exports.hasServerFields = hasServerFields;
1108
+ exports.isClientOnly = isClientOnly;
1109
+ exports.isNew = isNew;
1110
+ exports.isPatchBlank = isPatchBlank;
1111
+ exports.isTempId = isTempId;
1112
+ exports.makeCumulativePatch = makeCumulativePatch;
1113
+ exports.mergeEntityPatches = mergeEntityPatches;
1114
+ exports.objectKeys = objectKeys;
1115
+ exports.unionPatches = unionPatches;
1116
+ exports.useDbRef = useDbRef;
1117
+ exports.useDbView = useDbView;
1118
+ //# sourceMappingURL=index.js.map