@epam/uui-db 5.0.0-alpha.0 → 5.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.esm.js +107 -91
- package/index.esm.js.map +1 -1
- package/index.js +107 -91
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/Db.d.ts.map +1 -1
- package/src/DbRef.d.ts +1 -1
- package/src/DbRef.d.ts.map +1 -1
- package/src/DbTable.d.ts +1 -1
- package/src/DbTable.d.ts.map +1 -1
- package/src/IxSet.d.ts.map +1 -1
- package/src/ListLoadingTracker.d.ts.map +1 -1
- package/src/Loader.d.ts.map +1 -1
- package/src/Scheduler.d.ts.map +1 -1
- package/src/SimpleLoadingTracker.d.ts.map +1 -1
- package/src/__benchmarks__/testData.d.ts.map +1 -1
- package/src/patchHelpers.d.ts +3 -3
- package/src/patchHelpers.d.ts.map +1 -1
- package/src/reactHooks.d.ts.map +1 -1
- package/src/tempIds.d.ts +2 -2
- package/src/tempIds.d.ts.map +1 -1
- package/src/types.d.ts +2 -2
- package/src/types.d.ts.map +1 -1
- package/src/utils.d.ts +1 -1
- package/src/utils.d.ts.map +1 -1
- package/stats.html +2462 -329
package/index.js
CHANGED
|
@@ -57,7 +57,7 @@ exports.DbRelationType = void 0;
|
|
|
57
57
|
})(exports.DbRelationType || (exports.DbRelationType = {}));
|
|
58
58
|
|
|
59
59
|
// TBD: New typescript would contain better typing for this. Remove this hack after update.
|
|
60
|
-
|
|
60
|
+
const objectKeys = Object.keys;
|
|
61
61
|
function defaultCompareViewDependencies(prev, next) {
|
|
62
62
|
if (Array.isArray(prev) && Array.isArray(next)) {
|
|
63
63
|
if (prev.length === next.length) {
|
|
@@ -77,7 +77,7 @@ function difference(object, base) {
|
|
|
77
77
|
function changes(object, base) {
|
|
78
78
|
return transform__default.default(object, function (result, value, key) {
|
|
79
79
|
if (!isEqual__default.default(value, base[key])) {
|
|
80
|
-
result[key] =
|
|
80
|
+
result[key] = typeof value === 'object' && typeof base[key] === 'object' ? changes(value, base[key]) : value;
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
83
|
}
|
|
@@ -89,7 +89,7 @@ class Db {
|
|
|
89
89
|
this.tables = tables;
|
|
90
90
|
this.viewCache = new Map();
|
|
91
91
|
/* Views (cached db projections) */
|
|
92
|
-
this.valueAbsent = Symbol(
|
|
92
|
+
this.valueAbsent = Symbol('ValueAbsent');
|
|
93
93
|
if (reusedCache) {
|
|
94
94
|
this.viewCache = new Map(reusedCache);
|
|
95
95
|
}
|
|
@@ -104,8 +104,8 @@ class Db {
|
|
|
104
104
|
return clone;
|
|
105
105
|
}
|
|
106
106
|
with(patch) {
|
|
107
|
-
return this.update(db => {
|
|
108
|
-
objectKeys(db.tables).forEach(entityName => {
|
|
107
|
+
return this.update((db) => {
|
|
108
|
+
objectKeys(db.tables).forEach((entityName) => {
|
|
109
109
|
if (patch[entityName]) {
|
|
110
110
|
db.tables[entityName] = db.tables[entityName].with(patch[entityName]);
|
|
111
111
|
}
|
|
@@ -135,12 +135,12 @@ class Db {
|
|
|
135
135
|
dependencies = view.getDependencies(this, params);
|
|
136
136
|
shouldUpdate = !compare(cacheItem.dependencies, dependencies);
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
const previousValue = cacheItem.currentValue;
|
|
139
139
|
if (shouldUpdate) {
|
|
140
140
|
cacheItem.dependencies = dependencies;
|
|
141
|
-
|
|
141
|
+
const newValue = view.compute(this, params, dependencies);
|
|
142
142
|
cacheItem.computedOnDb = this;
|
|
143
|
-
|
|
143
|
+
const compareResults = view.compareResults || isEqual__default.default;
|
|
144
144
|
if (!compareResults(previousValue, newValue)) {
|
|
145
145
|
if (view.traceDiff) {
|
|
146
146
|
console.debug(difference(previousValue, newValue));
|
|
@@ -195,7 +195,7 @@ class DbTable {
|
|
|
195
195
|
this.state = state;
|
|
196
196
|
this.q = q;
|
|
197
197
|
if (!state) {
|
|
198
|
-
const indexes = (schema.indexes || []).map(indexDef => {
|
|
198
|
+
const indexes = (schema.indexes || []).map((indexDef) => {
|
|
199
199
|
return {
|
|
200
200
|
field: indexDef,
|
|
201
201
|
map: I__namespace.Map(),
|
|
@@ -231,7 +231,7 @@ class DbTable {
|
|
|
231
231
|
}
|
|
232
232
|
/* Mutation */
|
|
233
233
|
with(patch) {
|
|
234
|
-
const updates = patch.map(entityPatch => {
|
|
234
|
+
const updates = patch.map((entityPatch) => {
|
|
235
235
|
const id = this.getId(entityPatch);
|
|
236
236
|
const immId = this.keyToImmutable(id);
|
|
237
237
|
const existing = this.state.pk.get(immId);
|
|
@@ -243,52 +243,56 @@ class DbTable {
|
|
|
243
243
|
isDeleted = updated[this.schema.deleteFlag] === true;
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
|
-
return {
|
|
246
|
+
return {
|
|
247
|
+
id, immId, patch: entityPatch, existing, updated, isNew: !existing, isDeleted,
|
|
248
|
+
};
|
|
247
249
|
});
|
|
248
|
-
const idVal = I.Seq.Keyed(updates.map(entity => [entity.immId, entity.updated]));
|
|
250
|
+
const idVal = I.Seq.Keyed(updates.map((entity) => [entity.immId, entity.updated]));
|
|
249
251
|
let newPk = this.state.pk.merge(idVal);
|
|
250
252
|
// TBD: replace with deleteAll after migrating to immutable 4
|
|
251
|
-
updates
|
|
253
|
+
updates
|
|
254
|
+
.filter((u) => u.isDeleted)
|
|
255
|
+
.forEach((u) => {
|
|
252
256
|
newPk = newPk.delete(u.immId);
|
|
253
257
|
});
|
|
254
|
-
const newIndexes = this.state.indexes.map(index => {
|
|
258
|
+
const newIndexes = this.state.indexes.map((index) => {
|
|
255
259
|
let newMap = index.map;
|
|
256
260
|
for (let n = 0; n < updates.length; n++) {
|
|
257
|
-
|
|
261
|
+
const update = updates[n];
|
|
258
262
|
const newKey = update.updated[index.field];
|
|
259
263
|
if (update.existing) {
|
|
260
264
|
const oldKey = update.existing[index.field];
|
|
261
265
|
if (oldKey !== newKey || update.isDeleted) {
|
|
262
|
-
newMap = newMap.update(oldKey, set => set.remove(update.immId));
|
|
266
|
+
newMap = newMap.update(oldKey, (set) => set.remove(update.immId));
|
|
263
267
|
}
|
|
264
268
|
}
|
|
265
269
|
if (!update.isDeleted) {
|
|
266
|
-
newMap = newMap.update(newKey, I__namespace.Set(), set => set.add(update.immId));
|
|
270
|
+
newMap = newMap.update(newKey, I__namespace.Set(), (set) => set.add(update.immId));
|
|
267
271
|
}
|
|
268
272
|
}
|
|
269
273
|
return Object.assign(Object.assign({}, index), { map: newMap });
|
|
270
274
|
});
|
|
271
275
|
const newState = { pk: newPk, indexes: newIndexes };
|
|
272
|
-
return this.update(t => t.state = newState);
|
|
276
|
+
return this.update((t) => (t.state = newState));
|
|
273
277
|
}
|
|
274
278
|
/* Query */
|
|
275
279
|
find(filter) {
|
|
276
|
-
return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { filter: Object.assign(Object.assign({}, this.q.filter), filter) }));
|
|
280
|
+
return this.update((t) => (t.q = Object.assign(Object.assign({}, t.q), { filter: Object.assign(Object.assign({}, this.q.filter), filter) })));
|
|
277
281
|
}
|
|
278
282
|
order(order) {
|
|
279
|
-
return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: order }));
|
|
283
|
+
return this.update((t) => (t.q = Object.assign(Object.assign({}, t.q), { sorting: order })));
|
|
280
284
|
}
|
|
281
285
|
orderBy(field, direction = 'asc') {
|
|
282
|
-
return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [{ field, direction }] }));
|
|
286
|
+
return this.update((t) => (t.q = Object.assign(Object.assign({}, t.q), { sorting: [{ field, direction }] })));
|
|
283
287
|
}
|
|
284
288
|
thenBy(field, direction) {
|
|
285
|
-
return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { sorting: [...t.q.sorting, { field, direction }] }));
|
|
289
|
+
return this.update((t) => (t.q = Object.assign(Object.assign({}, t.q), { sorting: [...t.q.sorting, { field, direction }] })));
|
|
286
290
|
}
|
|
287
291
|
search(text) {
|
|
288
292
|
if (!this.schema.searchBy) {
|
|
289
293
|
throw new Error(`Can't search in the ${this.schema.typeName} table - searchBy is not defined in the schema.`);
|
|
290
294
|
}
|
|
291
|
-
return this.update(t => t.q = Object.assign(Object.assign({}, t.q), { search: text }));
|
|
295
|
+
return this.update((t) => (t.q = Object.assign(Object.assign({}, t.q), { search: text })));
|
|
292
296
|
}
|
|
293
297
|
/* Materializing */
|
|
294
298
|
range(from, count) {
|
|
@@ -311,14 +315,14 @@ class DbTable {
|
|
|
311
315
|
let result = null;
|
|
312
316
|
let filter = q.filter;
|
|
313
317
|
if (filter) {
|
|
314
|
-
|
|
318
|
+
const indexes = this.state.indexes;
|
|
315
319
|
// Try to use indexes to fulfill filter conditions
|
|
316
320
|
for (let n = 0; n < indexes.length; n++) {
|
|
317
321
|
const index = indexes[n];
|
|
318
322
|
if (index.field in filter) {
|
|
319
323
|
const _a = filter, _b = index.field, condition = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
320
324
|
let conditionValues = null;
|
|
321
|
-
if (condition != null && typeof condition ===
|
|
325
|
+
if (condition != null && typeof condition === 'object') {
|
|
322
326
|
// Attempt to use index for 'in' and 'isNull' criteria.
|
|
323
327
|
// We need to be very conservative here, indexed field should work the same way as getPatternPredicate. So
|
|
324
328
|
// - it's better to leave corner cases to getPatternPredicate
|
|
@@ -369,15 +373,15 @@ class DbTable {
|
|
|
369
373
|
result = this.state.pk.toArray();
|
|
370
374
|
}
|
|
371
375
|
if (filter) {
|
|
372
|
-
|
|
376
|
+
const predicate = uuiCore.getFilterPredicate(q.filter);
|
|
373
377
|
result = result.filter(predicate);
|
|
374
378
|
}
|
|
375
379
|
if (q.search) {
|
|
376
|
-
|
|
377
|
-
result = result.filter(item => searchFilter(this.schema.searchBy.map(field => item[field])));
|
|
380
|
+
const searchFilter = uuiCore.getSearchFilter(q.search);
|
|
381
|
+
result = result.filter((item) => searchFilter(this.schema.searchBy.map((field) => item[field])));
|
|
378
382
|
}
|
|
379
383
|
if (q.sorting) {
|
|
380
|
-
|
|
384
|
+
const comparer = uuiCore.getOrderComparer(q.sorting);
|
|
381
385
|
result = result.sort(comparer);
|
|
382
386
|
}
|
|
383
387
|
if (q.range) {
|
|
@@ -389,8 +393,8 @@ class DbTable {
|
|
|
389
393
|
|
|
390
394
|
function unionPatches(patches) {
|
|
391
395
|
const result = {};
|
|
392
|
-
patches.forEach(patch => {
|
|
393
|
-
objectKeys(patch).forEach(tableName => {
|
|
396
|
+
patches.forEach((patch) => {
|
|
397
|
+
objectKeys(patch).forEach((tableName) => {
|
|
394
398
|
result[tableName] = result[tableName] ? [...result[tableName], ...patch[tableName]] : patch[tableName];
|
|
395
399
|
});
|
|
396
400
|
});
|
|
@@ -398,13 +402,13 @@ function unionPatches(patches) {
|
|
|
398
402
|
}
|
|
399
403
|
function mergeEntityPatches(tables, patch) {
|
|
400
404
|
const result = {};
|
|
401
|
-
objectKeys(patch).forEach(key => {
|
|
405
|
+
objectKeys(patch).forEach((key) => {
|
|
402
406
|
const table = tables[key];
|
|
403
|
-
const groupedEntities = groupBy__default.default(patch[key], item => table.getId(item));
|
|
404
|
-
const tablePatch = map__default.default(groupedEntities, entities => {
|
|
407
|
+
const groupedEntities = groupBy__default.default(patch[key], (item) => table.getId(item));
|
|
408
|
+
const tablePatch = map__default.default(groupedEntities, (entities) => {
|
|
405
409
|
const result = merge__default.default({}, ...entities);
|
|
406
410
|
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);
|
|
411
|
+
const props = objectKeys(result).filter((prop) => Object.keys(countBy__default.default(entities.filter((entity) => entity[prop] !== undefined), (entity) => entity[prop])).length > 1);
|
|
408
412
|
if (props.length) {
|
|
409
413
|
console.warn('mergeEntityPatches: Different property values found for the same entity.\nProperty names:\n', props, '\nEntities:\n', ...entities);
|
|
410
414
|
}
|
|
@@ -417,7 +421,7 @@ function mergeEntityPatches(tables, patch) {
|
|
|
417
421
|
}
|
|
418
422
|
function flattenResponseHelper(result, object, tablesByTypeName) {
|
|
419
423
|
if (Array.isArray(object)) {
|
|
420
|
-
object.forEach(item => flattenResponseHelper(result, item, tablesByTypeName));
|
|
424
|
+
object.forEach((item) => flattenResponseHelper(result, item, tablesByTypeName));
|
|
421
425
|
}
|
|
422
426
|
else if (typeof object === 'object') {
|
|
423
427
|
const clone = {};
|
|
@@ -430,13 +434,13 @@ function flattenResponseHelper(result, object, tablesByTypeName) {
|
|
|
430
434
|
fields = table.schema.fields;
|
|
431
435
|
}
|
|
432
436
|
}
|
|
433
|
-
for (
|
|
437
|
+
for (const key in object) {
|
|
434
438
|
const value = object[key];
|
|
435
439
|
const field = fields[key];
|
|
436
440
|
if ((field && !!field.disableFlatten)
|
|
437
441
|
|| typeof value !== 'object'
|
|
438
442
|
|| value === null
|
|
439
|
-
|| (Array.isArray(value) && value.every(item => typeof item !== 'object'))) {
|
|
443
|
+
|| (Array.isArray(value) && value.every((item) => typeof item !== 'object'))) {
|
|
440
444
|
clone[key] = value;
|
|
441
445
|
}
|
|
442
446
|
else {
|
|
@@ -450,32 +454,32 @@ function flattenResponseHelper(result, object, tablesByTypeName) {
|
|
|
450
454
|
}
|
|
451
455
|
function flattenResponse(response, tables) {
|
|
452
456
|
const result = {};
|
|
453
|
-
|
|
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
|
+
const tablesByTypeName = {};
|
|
458
|
+
Object.values(tables).forEach((table) => (tablesByTypeName[table.schema.typeName] = table));
|
|
459
|
+
objectKeys(tables).forEach((tableName) => tablesByTypeName);
|
|
460
|
+
objectKeys(tables).forEach((key) => (result[key] = []));
|
|
457
461
|
flattenResponseHelper(result, response, tablesByTypeName);
|
|
458
462
|
return result;
|
|
459
463
|
}
|
|
460
464
|
function isPatchBlank(patch) {
|
|
461
|
-
return !objectKeys(patch).some(key => patch[key].length > 0);
|
|
465
|
+
return !objectKeys(patch).some((key) => patch[key].length > 0);
|
|
462
466
|
}
|
|
463
467
|
/**
|
|
464
468
|
* Given several patches, creates a new single patch with all fields from all entities in all patches.
|
|
465
469
|
*/
|
|
466
470
|
function makeCumulativePatch(updatedDb, patches, clientIdsMap) {
|
|
467
471
|
const result = {};
|
|
468
|
-
objectKeys(updatedDb.tables).forEach(entityName => {
|
|
472
|
+
objectKeys(updatedDb.tables).forEach((entityName) => {
|
|
469
473
|
const table = updatedDb.tables[entityName];
|
|
470
474
|
const schema = table.schema;
|
|
471
475
|
let ids = I__namespace.Set();
|
|
472
|
-
patches.forEach(patch => {
|
|
473
|
-
|
|
474
|
-
ids = ids.union(filteredPatch.map(e => table.getId(e)));
|
|
476
|
+
patches.forEach((patch) => {
|
|
477
|
+
const filteredPatch = (patch[entityName] || []).filter((entity) => hasServerFields(entity, schema, clientIdsMap, updatedDb.tables));
|
|
478
|
+
ids = ids.union(filteredPatch.map((e) => table.getId(e)));
|
|
475
479
|
});
|
|
476
480
|
const entities = ids
|
|
477
|
-
.map(id => table.byId(id))
|
|
478
|
-
.filter(e => !isClientOnly(e, schema))
|
|
481
|
+
.map((id) => table.byId(id))
|
|
482
|
+
.filter((e) => !isClientOnly(e, schema))
|
|
479
483
|
.toArray();
|
|
480
484
|
if (entities.length > 0) {
|
|
481
485
|
result[entityName] = entities;
|
|
@@ -504,25 +508,25 @@ function isNew(entity, schema, clientIdsMap) {
|
|
|
504
508
|
return !clientIdsMap.clientToServer(id);
|
|
505
509
|
}
|
|
506
510
|
function hasServerFields(entity, schema, clientIdsMap, tables) {
|
|
507
|
-
const fullEntity = Object.assign(Object.assign({}, tables[schema.tableName].byId(entity.id) || {}), entity);
|
|
511
|
+
const fullEntity = Object.assign(Object.assign({}, (tables[schema.tableName].byId(entity.id) || {})), entity);
|
|
508
512
|
if (isClientOnly(fullEntity, schema)) {
|
|
509
513
|
return false;
|
|
510
514
|
}
|
|
511
|
-
return objectKeys(entity).some(fieldName => {
|
|
515
|
+
return objectKeys(entity).some((fieldName) => {
|
|
512
516
|
const fieldSchema = schema.fields[fieldName];
|
|
513
517
|
return !fieldSchema || !(fieldSchema.isClientOnly || fieldSchema.isReadOnly || (fieldSchema.isGenerated && !isNew(entity, schema, clientIdsMap)));
|
|
514
518
|
});
|
|
515
519
|
}
|
|
516
520
|
function getParentEntities(patch, tables) {
|
|
517
521
|
const dependenciesPatch = {};
|
|
518
|
-
objectKeys(patch).forEach(key => {
|
|
522
|
+
objectKeys(patch).forEach((key) => {
|
|
519
523
|
const table = tables[key];
|
|
520
524
|
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);
|
|
525
|
+
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
526
|
const tablePatch = patch[key];
|
|
523
|
-
fields.forEach(field => {
|
|
524
|
-
const { fk: { tableName }, name } = field;
|
|
525
|
-
tablePatch.forEach(entity => {
|
|
527
|
+
fields.forEach((field) => {
|
|
528
|
+
const { fk: { tableName }, name, } = field;
|
|
529
|
+
tablePatch.forEach((entity) => {
|
|
526
530
|
const actualTableName = (typeof tableName == 'function' ? tableName(entity) : tableName);
|
|
527
531
|
const dbEntity = table.byId(table.getId(entity));
|
|
528
532
|
const parentEntity = tables[actualTableName].byId(dbEntity[name]);
|
|
@@ -540,7 +544,7 @@ function getEntityParentDependencies(entity, entityName, tables) {
|
|
|
540
544
|
let patch = { [entityName]: [entity] };
|
|
541
545
|
const resultPatches = [];
|
|
542
546
|
while (true) {
|
|
543
|
-
|
|
547
|
+
const parents = getParentEntities(patch, tables);
|
|
544
548
|
if (isPatchBlank(parents)) {
|
|
545
549
|
break;
|
|
546
550
|
}
|
|
@@ -590,7 +594,7 @@ class TempIdMap {
|
|
|
590
594
|
for (let n = 0; n < keys.length; n++) {
|
|
591
595
|
const key = keys[n];
|
|
592
596
|
let condition = filter[key];
|
|
593
|
-
if (condition != null && typeof condition ===
|
|
597
|
+
if (condition != null && typeof condition === 'object') {
|
|
594
598
|
condition = Object.assign({}, condition);
|
|
595
599
|
if ('in' in condition && Array.isArray(condition.in) && condition.in.length) {
|
|
596
600
|
condition.in = condition.in.map(clientToServer);
|
|
@@ -606,28 +610,28 @@ class TempIdMap {
|
|
|
606
610
|
}
|
|
607
611
|
copyPatch(patch) {
|
|
608
612
|
const newPatch = Object.assign({}, patch);
|
|
609
|
-
objectKeys(patch).forEach(tableName => {
|
|
610
|
-
|
|
613
|
+
objectKeys(patch).forEach((tableName) => {
|
|
614
|
+
const tablePatch = patch[tableName].map((entityPatch) => (Object.assign({}, entityPatch)));
|
|
611
615
|
newPatch[tableName] = tablePatch;
|
|
612
616
|
});
|
|
613
617
|
return newPatch;
|
|
614
618
|
}
|
|
615
619
|
// Iterate thru every field in every patch for every table, matching certain field criteria. The patch is mutated!
|
|
616
620
|
mapFields(patch, filter, callback) {
|
|
617
|
-
objectKeys(patch).forEach(tableName => {
|
|
621
|
+
objectKeys(patch).forEach((tableName) => {
|
|
618
622
|
const schema = this.db.tables[tableName].schema;
|
|
619
623
|
const fields = objectKeys(schema.fields || [])
|
|
620
|
-
.map(fieldName => {
|
|
624
|
+
.map((fieldName) => {
|
|
621
625
|
const fieldSchema = schema.fields[fieldName];
|
|
622
626
|
if (filter(fieldSchema, fieldName)) {
|
|
623
627
|
return { name: fieldName, schema: fieldSchema };
|
|
624
628
|
}
|
|
625
629
|
})
|
|
626
|
-
.filter(f => !!f);
|
|
630
|
+
.filter((f) => !!f);
|
|
627
631
|
if (!fields.length) {
|
|
628
632
|
return;
|
|
629
633
|
}
|
|
630
|
-
patch[tableName].forEach(entityPatch => {
|
|
634
|
+
patch[tableName].forEach((entityPatch) => {
|
|
631
635
|
for (let n = 0; n < fields.length; n++) {
|
|
632
636
|
const field = fields[n];
|
|
633
637
|
const fieldValue = entityPatch[field.name];
|
|
@@ -650,7 +654,7 @@ class TempIdMap {
|
|
|
650
654
|
serverToClientPatch(patch) {
|
|
651
655
|
patch = this.copyPatch(patch);
|
|
652
656
|
// 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) => {
|
|
657
|
+
this.mapFields(patch, (f) => f.isGenerated, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
654
658
|
let clientId = this.getServerToClientMap(tableName).get(fieldValue);
|
|
655
659
|
if (!clientId) {
|
|
656
660
|
clientId = getTempId();
|
|
@@ -659,8 +663,8 @@ class TempIdMap {
|
|
|
659
663
|
}
|
|
660
664
|
entityPatch[fieldName] = clientId;
|
|
661
665
|
});
|
|
662
|
-
this.mapFields(patch, f => !!(f.fk ||
|
|
663
|
-
let isUndefined = typeof
|
|
666
|
+
this.mapFields(patch, (f) => !!(f.fk || f.default != null || f.toClient), (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
667
|
+
let isUndefined = typeof fieldValue === 'undefined';
|
|
664
668
|
if (fieldSchema.default != null && fieldValue == null) {
|
|
665
669
|
fieldValue = fieldSchema.default;
|
|
666
670
|
isUndefined = false;
|
|
@@ -686,7 +690,7 @@ class TempIdMap {
|
|
|
686
690
|
}
|
|
687
691
|
clientToServerPatch(patch) {
|
|
688
692
|
patch = this.copyPatch(patch);
|
|
689
|
-
this.mapFields(patch, f => f.isGenerated || !!f.fk, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
693
|
+
this.mapFields(patch, (f) => f.isGenerated || !!f.fk, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
690
694
|
if (fieldValue != null) {
|
|
691
695
|
const existingId = this.clientToServerIds.get(fieldValue);
|
|
692
696
|
if (existingId) {
|
|
@@ -694,22 +698,22 @@ class TempIdMap {
|
|
|
694
698
|
}
|
|
695
699
|
}
|
|
696
700
|
});
|
|
697
|
-
this.mapFields(patch, f => !(f.isClientOnly || f.isReadOnly) && !!f.toServer, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
701
|
+
this.mapFields(patch, (f) => !(f.isClientOnly || f.isReadOnly) && !!f.toServer, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
698
702
|
entityPatch[fieldName] = fieldSchema.toServer(entityPatch[fieldName]);
|
|
699
703
|
});
|
|
700
|
-
this.mapFields(patch, meta => meta.isClientOnly || meta.isReadOnly, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
704
|
+
this.mapFields(patch, (meta) => meta.isClientOnly || meta.isReadOnly, (fieldName, fieldSchema, fieldValue, entityPatch, tableName) => {
|
|
701
705
|
delete entityPatch[fieldName];
|
|
702
706
|
});
|
|
703
707
|
return patch;
|
|
704
708
|
}
|
|
705
709
|
appendServerMapping(response) {
|
|
706
|
-
objectKeys(response.submit).forEach(tableName => {
|
|
710
|
+
objectKeys(response.submit).forEach((tableName) => {
|
|
707
711
|
if (this.db.tables[tableName]) {
|
|
708
712
|
const tablePatch = response.submit[tableName];
|
|
709
713
|
if (tablePatch) {
|
|
710
714
|
const serverToClientIds = this.getServerToClientMap(tableName);
|
|
711
715
|
const table = this.db.tables[tableName];
|
|
712
|
-
tablePatch.forEach(patch => {
|
|
716
|
+
tablePatch.forEach((patch) => {
|
|
713
717
|
if (isTempId(patch.id)) {
|
|
714
718
|
const clientId = patch.id;
|
|
715
719
|
const serverId = table.getId(patch.payload);
|
|
@@ -776,7 +780,7 @@ class Loader {
|
|
|
776
780
|
if (this.options.clientToServerRequest) {
|
|
777
781
|
serverRequest = this.options.clientToServerRequest(serverRequest);
|
|
778
782
|
}
|
|
779
|
-
state.promise = this.options.api(serverRequest).then(result => {
|
|
783
|
+
state.promise = this.options.api(serverRequest).then((result) => {
|
|
780
784
|
this.loaded.append(state.missing, result);
|
|
781
785
|
this.loadedAndLoading.append(state.missing, result);
|
|
782
786
|
state.missing = null;
|
|
@@ -828,17 +832,21 @@ class ListLoadingTracker {
|
|
|
828
832
|
if (search) {
|
|
829
833
|
options.search = search;
|
|
830
834
|
}
|
|
831
|
-
|
|
835
|
+
const keyObject = Object.assign(Object.assign({}, options), unknownFields);
|
|
832
836
|
const key = JSON.stringify(keyObject);
|
|
833
837
|
let entry = this.cache.get(key);
|
|
834
838
|
if (!entry) {
|
|
835
|
-
entry = {
|
|
839
|
+
entry = {
|
|
840
|
+
options, count: 0, maxCount: null, isComplete: false,
|
|
841
|
+
};
|
|
836
842
|
this.cache.set(key, entry);
|
|
837
843
|
}
|
|
838
|
-
return {
|
|
844
|
+
return {
|
|
845
|
+
options, range, unknownFields, entry,
|
|
846
|
+
};
|
|
839
847
|
}
|
|
840
848
|
diff(request) {
|
|
841
|
-
const { options, range, unknownFields, entry } = this.prepare(request);
|
|
849
|
+
const { options, range, unknownFields, entry, } = this.prepare(request);
|
|
842
850
|
if (entry.isComplete) {
|
|
843
851
|
return null;
|
|
844
852
|
}
|
|
@@ -864,7 +872,7 @@ class ListLoadingTracker {
|
|
|
864
872
|
return { knownCount: Math.max(entry.count, entry.maxCount), exactCount: entry.maxCount };
|
|
865
873
|
}
|
|
866
874
|
append(request, response) {
|
|
867
|
-
const { options, range, unknownFields, entry } = this.prepare(request);
|
|
875
|
+
const { options, range, unknownFields, entry, } = this.prepare(request);
|
|
868
876
|
if (response) {
|
|
869
877
|
const list = this.extractList(response);
|
|
870
878
|
if (list.count) {
|
|
@@ -876,7 +884,7 @@ class ListLoadingTracker {
|
|
|
876
884
|
entry.isComplete = true;
|
|
877
885
|
}
|
|
878
886
|
else {
|
|
879
|
-
const from =
|
|
887
|
+
const from = list.from == null ? range.from : list.from;
|
|
880
888
|
if (list.items.length > 0) {
|
|
881
889
|
entry.count = Math.max(entry.count, from + list.items.length);
|
|
882
890
|
}
|
|
@@ -977,23 +985,29 @@ class DbRef {
|
|
|
977
985
|
}
|
|
978
986
|
beforeUpdate(patch, tables, prevTables) {
|
|
979
987
|
let patchAndDependencies = {};
|
|
980
|
-
objectKeys(tables)
|
|
988
|
+
objectKeys(tables)
|
|
989
|
+
.filter((entityName) => patch[entityName] && !tables[entityName].schema.beforeUpdate)
|
|
990
|
+
.forEach((entityName) => {
|
|
981
991
|
patchAndDependencies[entityName] = patch[entityName];
|
|
982
992
|
});
|
|
983
|
-
objectKeys(tables)
|
|
993
|
+
objectKeys(tables)
|
|
994
|
+
.filter((entityName) => patch[entityName] && tables[entityName].schema.beforeUpdate)
|
|
995
|
+
.forEach((entityName) => {
|
|
984
996
|
const schema = tables[entityName].schema;
|
|
985
997
|
const { beforeUpdate } = schema;
|
|
986
|
-
|
|
998
|
+
const context = {
|
|
987
999
|
clientIdsMap: this.tempIdMap,
|
|
988
1000
|
schema,
|
|
989
1001
|
tables,
|
|
990
1002
|
prevTables,
|
|
991
1003
|
};
|
|
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));
|
|
1004
|
+
const results = patch[entityName].map((e) => beforeUpdate(e, context));
|
|
1005
|
+
const updatedPatch = { [entityName]: results.map((result) => result.entity) };
|
|
1006
|
+
const dependentEntityPatchesForUpdate = unionPatches(results.filter((result) => result.dependentEntities).map((result) => result.dependentEntities));
|
|
995
1007
|
const dependentEntityPatches = this.beforeUpdate(dependentEntityPatchesForUpdate, tables, prevTables);
|
|
996
|
-
patchAndDependencies = mergeEntityPatches(tables, unionPatches([
|
|
1008
|
+
patchAndDependencies = mergeEntityPatches(tables, unionPatches([
|
|
1009
|
+
patchAndDependencies, updatedPatch, dependentEntityPatches,
|
|
1010
|
+
]));
|
|
997
1011
|
});
|
|
998
1012
|
return patchAndDependencies;
|
|
999
1013
|
}
|
|
@@ -1012,7 +1026,7 @@ class DbRef {
|
|
|
1012
1026
|
makeCumulativePatch() {
|
|
1013
1027
|
const lastLogEntry = this.log.length;
|
|
1014
1028
|
const logEntriesToSave = this.log.slice(this.savedPoint, lastLogEntry);
|
|
1015
|
-
let cumulativePatch = makeCumulativePatch(this.db, logEntriesToSave.map(t => t.patch), this.tempIdMap);
|
|
1029
|
+
let cumulativePatch = makeCumulativePatch(this.db, logEntriesToSave.map((t) => t.patch), this.tempIdMap);
|
|
1016
1030
|
cumulativePatch = this.tempIdMap.clientToServerPatch(cumulativePatch);
|
|
1017
1031
|
return cumulativePatch;
|
|
1018
1032
|
}
|
|
@@ -1035,7 +1049,9 @@ class DbRef {
|
|
|
1035
1049
|
currentParams: null,
|
|
1036
1050
|
currentValue: null,
|
|
1037
1051
|
onUpdate,
|
|
1038
|
-
unsubscribe: () => {
|
|
1052
|
+
unsubscribe: () => {
|
|
1053
|
+
this.subscriptions.delete(id);
|
|
1054
|
+
},
|
|
1039
1055
|
};
|
|
1040
1056
|
subscription.update(params);
|
|
1041
1057
|
this.subscriptions.set(id, subscription);
|
|
@@ -1043,12 +1059,12 @@ class DbRef {
|
|
|
1043
1059
|
}
|
|
1044
1060
|
onUpdate(handler) {
|
|
1045
1061
|
this.subscribe({
|
|
1046
|
-
compute: db => db,
|
|
1062
|
+
compute: (db) => db,
|
|
1047
1063
|
compareResults: (a, b) => a === b,
|
|
1048
1064
|
}, null, handler);
|
|
1049
1065
|
}
|
|
1050
1066
|
update() {
|
|
1051
|
-
this.subscriptions.forEach(subscription => {
|
|
1067
|
+
this.subscriptions.forEach((subscription) => {
|
|
1052
1068
|
const previousValue = subscription.currentValue;
|
|
1053
1069
|
subscription.update(subscription.currentParams);
|
|
1054
1070
|
if (subscription.currentValue !== previousValue && subscription.onUpdate) {
|
|
@@ -1060,7 +1076,7 @@ class DbRef {
|
|
|
1060
1076
|
this.saveErrorHandlers.push(handler);
|
|
1061
1077
|
}
|
|
1062
1078
|
saveError(request, error) {
|
|
1063
|
-
this.saveErrorHandlers.forEach(handler => handler(request, error));
|
|
1079
|
+
this.saveErrorHandlers.forEach((handler) => handler(request, error));
|
|
1064
1080
|
}
|
|
1065
1081
|
makeLoader(options) {
|
|
1066
1082
|
const loader = new Loader(this, () => new SimpleLoadingTracker(), options);
|