tinybase 1.3.6 → 2.0.0-beta.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/lib/checkpoints.d.ts +4 -3
- package/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/debug/checkpoints.d.ts +4 -3
- package/lib/debug/checkpoints.js +69 -56
- package/lib/debug/indexes.d.ts +4 -2
- package/lib/debug/indexes.js +106 -69
- package/lib/debug/metrics.d.ts +1 -1
- package/lib/debug/metrics.js +187 -131
- package/lib/debug/persisters.d.ts +6 -0
- package/lib/debug/persisters.js +2 -1
- package/lib/debug/queries.d.ts +3251 -0
- package/lib/debug/queries.js +900 -0
- package/lib/debug/relationships.d.ts +12 -10
- package/lib/debug/relationships.js +104 -68
- package/lib/debug/store.d.ts +415 -74
- package/lib/debug/store.js +295 -120
- package/lib/debug/tinybase.d.ts +1 -0
- package/lib/debug/tinybase.js +985 -176
- package/lib/debug/ui-react.d.ts +4325 -1754
- package/lib/debug/ui-react.js +413 -85
- package/lib/indexes.d.ts +4 -2
- package/lib/indexes.js +1 -1
- package/lib/indexes.js.gz +0 -0
- package/lib/metrics.d.ts +1 -1
- package/lib/metrics.js +1 -1
- package/lib/metrics.js.gz +0 -0
- package/lib/persisters.d.ts +6 -0
- package/lib/queries.d.ts +3251 -0
- package/lib/queries.js +1 -0
- package/lib/queries.js.gz +0 -0
- package/lib/relationships.d.ts +12 -10
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.d.ts +415 -74
- package/lib/store.js +1 -1
- package/lib/store.js.gz +0 -0
- package/lib/tinybase.d.ts +1 -0
- package/lib/tinybase.js +1 -1
- package/lib/tinybase.js.gz +0 -0
- package/lib/ui-react.d.ts +4325 -1754
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.js.gz +0 -0
- package/lib/umd/checkpoints.js +1 -1
- package/lib/umd/checkpoints.js.gz +0 -0
- package/lib/umd/indexes.js +1 -1
- package/lib/umd/indexes.js.gz +0 -0
- package/lib/umd/metrics.js +1 -1
- package/lib/umd/metrics.js.gz +0 -0
- package/lib/umd/queries.js +1 -0
- package/lib/umd/queries.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.js +1 -1
- package/lib/umd/store.js.gz +0 -0
- package/lib/umd/tinybase.js +1 -1
- package/lib/umd/tinybase.js.gz +0 -0
- package/lib/umd/ui-react.js +1 -1
- package/lib/umd/ui-react.js.gz +0 -0
- package/package.json +4 -4
- package/readme.md +2 -2
package/lib/debug/tinybase.js
CHANGED
|
@@ -15,10 +15,14 @@ const AVG = 'avg';
|
|
|
15
15
|
const MIN = 'min';
|
|
16
16
|
const MAX = 'max';
|
|
17
17
|
|
|
18
|
-
const arrayPair = (value) => [value, value];
|
|
19
18
|
const arrayHas = (array, value) => array.includes(value);
|
|
19
|
+
const arrayEvery = (array, cb) => array.every(cb);
|
|
20
|
+
const arrayIsEqual = (array1, array2) =>
|
|
21
|
+
arrayLength(array1) === arrayLength(array2) &&
|
|
22
|
+
arrayEvery(array1, (value1, index) => array2[index] === value1);
|
|
20
23
|
const arrayIsSorted = (array, sorter) =>
|
|
21
|
-
|
|
24
|
+
arrayEvery(
|
|
25
|
+
array,
|
|
22
26
|
(value, index) => index == 0 || sorter(array[index - 1], value) <= 0,
|
|
23
27
|
);
|
|
24
28
|
const arraySort = (array, sorter) => array.sort(sorter);
|
|
@@ -29,9 +33,9 @@ const arrayLength = (array) => array.length;
|
|
|
29
33
|
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
30
34
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
31
35
|
const arrayFilter = (array, cb) => array.filter(cb);
|
|
32
|
-
const
|
|
36
|
+
const arraySlice = (array, start, end) => array.slice(start, end);
|
|
33
37
|
const arrayClear = (array, to) => array.splice(0, to);
|
|
34
|
-
const arrayPush = (array,
|
|
38
|
+
const arrayPush = (array, ...values) => array.push(...values);
|
|
35
39
|
const arrayPop = (array) => array.pop();
|
|
36
40
|
|
|
37
41
|
const jsonString = (obj) =>
|
|
@@ -66,7 +70,6 @@ const collSize = (coll) => coll.size;
|
|
|
66
70
|
const collSize2 = collSizeN(collSize);
|
|
67
71
|
const collSize3 = collSizeN(collSize2);
|
|
68
72
|
const collSize4 = collSizeN(collSize3);
|
|
69
|
-
const collPairSize = (pair, func = collSize) => func(pair[0]) + func(pair[1]);
|
|
70
73
|
const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
|
|
71
74
|
const collIsEmpty = (coll) => isUndefined(coll) || collSize(coll) == 0;
|
|
72
75
|
const collValues = (coll) => [...(coll?.values() ?? [])];
|
|
@@ -75,7 +78,6 @@ const collForEach = (coll, cb) => coll?.forEach(cb);
|
|
|
75
78
|
const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
|
|
76
79
|
|
|
77
80
|
const mapNew = (entries) => new Map(entries);
|
|
78
|
-
const mapNewPair = (newFunction = mapNew) => [newFunction(), newFunction()];
|
|
79
81
|
const mapKeys = (map) => [...(map?.keys() ?? [])];
|
|
80
82
|
const mapGet = (map, key) => map?.get(key);
|
|
81
83
|
const mapForEach = (map, cb) =>
|
|
@@ -105,6 +107,27 @@ const mapClone = (map, childMapper) => {
|
|
|
105
107
|
return map2;
|
|
106
108
|
};
|
|
107
109
|
const mapClone2 = (map) => mapClone(map, mapClone);
|
|
110
|
+
const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
|
|
111
|
+
ifNotUndefined(
|
|
112
|
+
(ensureLeaf ? mapEnsure : mapGet)(
|
|
113
|
+
node,
|
|
114
|
+
path[p],
|
|
115
|
+
p > arrayLength(path) - 2 ? ensureLeaf : mapNew,
|
|
116
|
+
),
|
|
117
|
+
(nodeOrLeaf) => {
|
|
118
|
+
if (p > arrayLength(path) - 2) {
|
|
119
|
+
if (pruneLeaf?.(nodeOrLeaf)) {
|
|
120
|
+
mapSet(node, path[p]);
|
|
121
|
+
}
|
|
122
|
+
return nodeOrLeaf;
|
|
123
|
+
}
|
|
124
|
+
const leaf = visitTree(nodeOrLeaf, path, ensureLeaf, pruneLeaf, p + 1);
|
|
125
|
+
if (collIsEmpty(nodeOrLeaf)) {
|
|
126
|
+
mapSet(node, path[p]);
|
|
127
|
+
}
|
|
128
|
+
return leaf;
|
|
129
|
+
},
|
|
130
|
+
);
|
|
108
131
|
|
|
109
132
|
const setNew = (entries) => new Set(entries);
|
|
110
133
|
const setAdd = (set, value) => set?.add(value);
|
|
@@ -123,20 +146,46 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
|
|
|
123
146
|
const getTableId = (id) => mapGet(tableIds, id);
|
|
124
147
|
const getThing = (id) => mapGet(things, id);
|
|
125
148
|
const setThing = (id, thing) => mapSet(things, id, thing);
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
149
|
+
const addStoreListeners = (id, andCall, ...listenerIds) => {
|
|
150
|
+
const set = mapEnsure(storeListenerIds, id, setNew);
|
|
151
|
+
arrayForEach(
|
|
152
|
+
listenerIds,
|
|
153
|
+
(listenerId) =>
|
|
154
|
+
setAdd(set, listenerId) && andCall && store.callListener(listenerId),
|
|
155
|
+
);
|
|
156
|
+
return listenerIds;
|
|
157
|
+
};
|
|
158
|
+
const delStoreListeners = (id, ...listenerIds) =>
|
|
159
|
+
ifNotUndefined(mapGet(storeListenerIds, id), (allListenerIds) => {
|
|
160
|
+
arrayForEach(
|
|
161
|
+
arrayIsEmpty(listenerIds) ? collValues(allListenerIds) : listenerIds,
|
|
162
|
+
(listenerId) => {
|
|
163
|
+
store.delListener(listenerId);
|
|
164
|
+
collDel(allListenerIds, listenerId);
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
if (collIsEmpty(allListenerIds)) {
|
|
168
|
+
mapSet(storeListenerIds, id);
|
|
169
|
+
}
|
|
130
170
|
});
|
|
131
|
-
const setDefinition = (id, tableId
|
|
132
|
-
const changedRowValues = mapNew();
|
|
133
|
-
const changedSortKeys = mapNew();
|
|
171
|
+
const setDefinition = (id, tableId) => {
|
|
134
172
|
mapSet(tableIds, id, tableId);
|
|
135
173
|
if (!collHas(things, id)) {
|
|
136
174
|
mapSet(things, id, getDefaultThing());
|
|
137
175
|
mapSet(allRowValues, id, mapNew());
|
|
138
176
|
mapSet(allSortKeys, id, mapNew());
|
|
139
177
|
}
|
|
178
|
+
};
|
|
179
|
+
const setDefinitionAndListen = (
|
|
180
|
+
id,
|
|
181
|
+
tableId,
|
|
182
|
+
onChanged,
|
|
183
|
+
getRowValue,
|
|
184
|
+
getSortKey,
|
|
185
|
+
) => {
|
|
186
|
+
setDefinition(id, tableId);
|
|
187
|
+
const changedRowValues = mapNew();
|
|
188
|
+
const changedSortKeys = mapNew();
|
|
140
189
|
const rowValues = mapGet(allRowValues, id);
|
|
141
190
|
const sortKeys = mapGet(allSortKeys, id);
|
|
142
191
|
const processRow = (rowId) => {
|
|
@@ -186,16 +235,14 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
|
|
|
186
235
|
});
|
|
187
236
|
}
|
|
188
237
|
processTable(true);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
storeListenerIds,
|
|
238
|
+
delStoreListeners(id);
|
|
239
|
+
addStoreListeners(
|
|
192
240
|
id,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
]),
|
|
241
|
+
0,
|
|
242
|
+
store.addRowListener(tableId, null, (_store, _tableId, rowId) =>
|
|
243
|
+
processRow(rowId),
|
|
244
|
+
),
|
|
245
|
+
store.addTableListener(tableId, () => processTable()),
|
|
199
246
|
);
|
|
200
247
|
};
|
|
201
248
|
const delDefinition = (id) => {
|
|
@@ -203,7 +250,7 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
|
|
|
203
250
|
mapSet(things, id);
|
|
204
251
|
mapSet(allRowValues, id);
|
|
205
252
|
mapSet(allSortKeys, id);
|
|
206
|
-
|
|
253
|
+
delStoreListeners(id);
|
|
207
254
|
};
|
|
208
255
|
const destroy = () => mapForEach(storeListenerIds, delDefinition);
|
|
209
256
|
return [
|
|
@@ -215,8 +262,11 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
|
|
|
215
262
|
getThing,
|
|
216
263
|
setThing,
|
|
217
264
|
setDefinition,
|
|
265
|
+
setDefinitionAndListen,
|
|
218
266
|
delDefinition,
|
|
219
267
|
destroy,
|
|
268
|
+
addStoreListeners,
|
|
269
|
+
delStoreListeners,
|
|
220
270
|
];
|
|
221
271
|
};
|
|
222
272
|
const getRowCellFunction = (getRowCell, defaultCellValue) =>
|
|
@@ -233,64 +283,51 @@ const getCreateFunction = (getFunction) => {
|
|
|
233
283
|
};
|
|
234
284
|
};
|
|
235
285
|
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
);
|
|
247
|
-
const forDeepSet = (valueDo) => {
|
|
248
|
-
const deep = (deepIdSet, arg, ...ids) =>
|
|
249
|
-
ifNotUndefined(deepIdSet, (deepIdSet2) =>
|
|
250
|
-
arrayIsEmpty(ids)
|
|
251
|
-
? valueDo(deepIdSet2, arg)
|
|
252
|
-
: arrayForEach([ids[0], null], (id) =>
|
|
253
|
-
deep(mapGet(deepIdSet2, id), arg, ...arrayFromSecond(ids)),
|
|
254
|
-
),
|
|
255
|
-
);
|
|
256
|
-
return deep;
|
|
286
|
+
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
287
|
+
const leaves = [];
|
|
288
|
+
const deep = (node, p) =>
|
|
289
|
+
p == arrayLength(path)
|
|
290
|
+
? arrayPush(leaves, node)
|
|
291
|
+
: path[p] === null
|
|
292
|
+
? collForEach(node, (node2) => deep(node2, p + 1))
|
|
293
|
+
: arrayForEach([path[p], null], (id) => deep(mapGet(node, id), p + 1));
|
|
294
|
+
deep(deepIdSet, 0);
|
|
295
|
+
return leaves;
|
|
257
296
|
};
|
|
258
297
|
const getListenerFunctions = (getThing) => {
|
|
259
298
|
let thing;
|
|
260
299
|
let nextId = 0;
|
|
261
300
|
const listenerPool = [];
|
|
262
301
|
const allListeners = mapNew();
|
|
263
|
-
const addListener = (listener,
|
|
302
|
+
const addListener = (listener, idSetNode, path) => {
|
|
264
303
|
thing ??= getThing();
|
|
265
|
-
const id = arrayPop(listenerPool) ??
|
|
266
|
-
mapSet(allListeners, id, [listener,
|
|
267
|
-
|
|
304
|
+
const id = arrayPop(listenerPool) ?? EMPTY_STRING + nextId++;
|
|
305
|
+
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
306
|
+
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
268
307
|
return id;
|
|
269
308
|
};
|
|
270
|
-
const callListeners = (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
listener(thing, ...ids, ...extraArgs),
|
|
276
|
-
),
|
|
277
|
-
...ids,
|
|
309
|
+
const callListeners = (idSetNode, ids, ...extraArgs) =>
|
|
310
|
+
arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
|
|
311
|
+
collForEach(set, (id) =>
|
|
312
|
+
mapGet(allListeners, id)[0](thing, ...(ids ?? []), ...extraArgs),
|
|
313
|
+
),
|
|
278
314
|
);
|
|
279
315
|
const delListener = (id) =>
|
|
280
|
-
ifNotUndefined(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
316
|
+
ifNotUndefined(mapGet(allListeners, id), ([, idSetNode, idOrNulls]) => {
|
|
317
|
+
visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], void 0, (idSet) => {
|
|
318
|
+
collDel(idSet, id);
|
|
319
|
+
return collIsEmpty(idSet) ? 1 : 0;
|
|
320
|
+
});
|
|
321
|
+
mapSet(allListeners, id);
|
|
322
|
+
if (arrayLength(listenerPool) < 1e3) {
|
|
323
|
+
arrayPush(listenerPool, id);
|
|
324
|
+
}
|
|
325
|
+
return idOrNulls;
|
|
326
|
+
});
|
|
327
|
+
const hasListeners = (idSetNode, ids) =>
|
|
328
|
+
!arrayEvery(getWildcardedLeaves(idSetNode, ids), isUndefined);
|
|
292
329
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
|
293
|
-
ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls]) => {
|
|
330
|
+
ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls = []]) => {
|
|
294
331
|
const callWithIds = (...ids) => {
|
|
295
332
|
const index = arrayLength(ids);
|
|
296
333
|
index == arrayLength(idOrNulls)
|
|
@@ -303,7 +340,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
303
340
|
};
|
|
304
341
|
callWithIds();
|
|
305
342
|
});
|
|
306
|
-
return [addListener, callListeners, delListener, callListener];
|
|
343
|
+
return [addListener, callListeners, delListener, hasListeners, callListener];
|
|
307
344
|
};
|
|
308
345
|
|
|
309
346
|
const object = Object;
|
|
@@ -319,6 +356,17 @@ const objForEach = (obj, cb) =>
|
|
|
319
356
|
arrayForEach(object.entries(obj), ([id, value]) => cb(value, id));
|
|
320
357
|
const objIsEmpty = (obj) => arrayIsEmpty(objIds(obj));
|
|
321
358
|
|
|
359
|
+
const getCellType = (cell) => {
|
|
360
|
+
const type = getTypeOf(cell);
|
|
361
|
+
return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
|
|
362
|
+
? type
|
|
363
|
+
: void 0;
|
|
364
|
+
};
|
|
365
|
+
const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
|
|
366
|
+
isUndefined(cell)
|
|
367
|
+
? store.delCell(tableId, rowId, cellId, true)
|
|
368
|
+
: store.setCell(tableId, rowId, cellId, cell);
|
|
369
|
+
|
|
322
370
|
const createCheckpoints = getCreateFunction((store) => {
|
|
323
371
|
let backwardIdsSize = 100;
|
|
324
372
|
let currentId;
|
|
@@ -326,7 +374,7 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
326
374
|
let listening = 1;
|
|
327
375
|
let nextCheckpointId;
|
|
328
376
|
let checkpointsChanged;
|
|
329
|
-
const checkpointIdsListeners =
|
|
377
|
+
const checkpointIdsListeners = mapNew();
|
|
330
378
|
const checkpointListeners = mapNew();
|
|
331
379
|
const [addListener, callListeners, delListenerImpl] = getListenerFunctions(
|
|
332
380
|
() => checkpoints,
|
|
@@ -341,9 +389,7 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
341
389
|
collForEach(mapGet(deltas, checkpointId), (table, tableId) =>
|
|
342
390
|
collForEach(table, (row, rowId) =>
|
|
343
391
|
collForEach(row, (oldNew, cellId) =>
|
|
344
|
-
|
|
345
|
-
? store.delCell(tableId, rowId, cellId, true)
|
|
346
|
-
: store.setCell(tableId, rowId, cellId, oldNew[oldOrNew]),
|
|
392
|
+
setOrDelCell(store, tableId, rowId, cellId, oldNew[oldOrNew]),
|
|
347
393
|
),
|
|
348
394
|
),
|
|
349
395
|
),
|
|
@@ -393,9 +439,9 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
393
439
|
}
|
|
394
440
|
},
|
|
395
441
|
);
|
|
396
|
-
const addCheckpointImpl = (label =
|
|
442
|
+
const addCheckpointImpl = (label = EMPTY_STRING) => {
|
|
397
443
|
if (isUndefined(currentId)) {
|
|
398
|
-
currentId =
|
|
444
|
+
currentId = EMPTY_STRING + nextCheckpointId++;
|
|
399
445
|
mapSet(deltas, currentId, delta);
|
|
400
446
|
setCheckpoint(currentId, label);
|
|
401
447
|
delta = mapNew();
|
|
@@ -493,7 +539,7 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
493
539
|
store.delListener(listenerId);
|
|
494
540
|
};
|
|
495
541
|
const getListenerStats = () => ({
|
|
496
|
-
checkpointIds:
|
|
542
|
+
checkpointIds: collSize2(checkpointIdsListeners),
|
|
497
543
|
checkpoint: collSize2(checkpointListeners),
|
|
498
544
|
});
|
|
499
545
|
const checkpoints = {
|
|
@@ -532,7 +578,8 @@ const createIndexes = getCreateFunction((store) => {
|
|
|
532
578
|
getTableId,
|
|
533
579
|
getIndex,
|
|
534
580
|
setIndex,
|
|
535
|
-
|
|
581
|
+
,
|
|
582
|
+
setDefinitionAndListen,
|
|
536
583
|
delDefinition,
|
|
537
584
|
destroy,
|
|
538
585
|
] = getDefinableFunctions(store, mapNew, (value) =>
|
|
@@ -553,7 +600,7 @@ const createIndexes = getCreateFunction((store) => {
|
|
|
553
600
|
const sliceIdArraySorter = isUndefined(sliceIdSorter)
|
|
554
601
|
? void 0
|
|
555
602
|
: ([id1], [id2]) => sliceIdSorter(id1, id2);
|
|
556
|
-
|
|
603
|
+
setDefinitionAndListen(
|
|
557
604
|
indexId,
|
|
558
605
|
tableId,
|
|
559
606
|
(change, changedSliceIds, changedSortKeys, sliceIds, sortKeys, force) => {
|
|
@@ -697,7 +744,7 @@ const createIndexes = getCreateFunction((store) => {
|
|
|
697
744
|
return objFreeze(indexes);
|
|
698
745
|
});
|
|
699
746
|
|
|
700
|
-
const
|
|
747
|
+
const numericAggregators = mapNew([
|
|
701
748
|
[
|
|
702
749
|
AVG,
|
|
703
750
|
[
|
|
@@ -737,6 +784,35 @@ const aggregators = mapNew([
|
|
|
737
784
|
],
|
|
738
785
|
],
|
|
739
786
|
]);
|
|
787
|
+
const getAggregateValue = (
|
|
788
|
+
aggregateValue,
|
|
789
|
+
oldLength,
|
|
790
|
+
newValues,
|
|
791
|
+
changedValues,
|
|
792
|
+
aggregators,
|
|
793
|
+
force = false,
|
|
794
|
+
) => {
|
|
795
|
+
if (collIsEmpty(newValues)) {
|
|
796
|
+
return void 0;
|
|
797
|
+
}
|
|
798
|
+
const [aggregate, aggregateAdd, aggregateRemove, aggregateReplace] =
|
|
799
|
+
aggregators;
|
|
800
|
+
force ||= isUndefined(aggregateValue);
|
|
801
|
+
collForEach(changedValues, ([oldValue, newValue]) => {
|
|
802
|
+
if (!force) {
|
|
803
|
+
aggregateValue = isUndefined(oldValue)
|
|
804
|
+
? aggregateAdd?.(aggregateValue, newValue, oldLength++)
|
|
805
|
+
: isUndefined(newValue)
|
|
806
|
+
? aggregateRemove?.(aggregateValue, oldValue, oldLength--)
|
|
807
|
+
: aggregateReplace?.(aggregateValue, newValue, oldValue, oldLength);
|
|
808
|
+
force ||= isUndefined(aggregateValue);
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
return force
|
|
812
|
+
? aggregate(collValues(newValues), collSize(newValues))
|
|
813
|
+
: aggregateValue;
|
|
814
|
+
};
|
|
815
|
+
|
|
740
816
|
const createMetrics = getCreateFunction((store) => {
|
|
741
817
|
const metricListeners = mapNew();
|
|
742
818
|
const [
|
|
@@ -747,7 +823,8 @@ const createMetrics = getCreateFunction((store) => {
|
|
|
747
823
|
getTableId,
|
|
748
824
|
getMetric,
|
|
749
825
|
setMetric,
|
|
750
|
-
|
|
826
|
+
,
|
|
827
|
+
setDefinitionAndListen,
|
|
751
828
|
delDefinition,
|
|
752
829
|
destroy,
|
|
753
830
|
] = getDefinableFunctions(store, getUndefined, (value) =>
|
|
@@ -771,38 +848,29 @@ const createMetrics = getCreateFunction((store) => {
|
|
|
771
848
|
aggregateRemove,
|
|
772
849
|
aggregateReplace,
|
|
773
850
|
) => {
|
|
774
|
-
const
|
|
851
|
+
const aggregators = isFunction(aggregate)
|
|
775
852
|
? [aggregate, aggregateAdd, aggregateRemove, aggregateReplace]
|
|
776
|
-
: mapGet(
|
|
777
|
-
|
|
853
|
+
: mapGet(numericAggregators, aggregate) ??
|
|
854
|
+
mapGet(numericAggregators, SUM);
|
|
855
|
+
setDefinitionAndListen(
|
|
778
856
|
metricId,
|
|
779
857
|
tableId,
|
|
780
858
|
(change, changedNumbers, _changedSortKeys, numbers, _sortKeys, force) => {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
metricAggregators;
|
|
785
|
-
force = force || isUndefined(newMetric);
|
|
786
|
-
collForEach(changedNumbers, ([oldNumber, newNumber]) => {
|
|
787
|
-
if (!force) {
|
|
788
|
-
newMetric = isUndefined(oldNumber)
|
|
789
|
-
? aggregateAdd2?.(newMetric, newNumber, length++)
|
|
790
|
-
: isUndefined(newNumber)
|
|
791
|
-
? aggregateRemove2?.(newMetric, oldNumber, length--)
|
|
792
|
-
: aggregateReplace2?.(newMetric, newNumber, oldNumber, length);
|
|
793
|
-
}
|
|
794
|
-
force = force || isUndefined(newMetric);
|
|
795
|
-
});
|
|
859
|
+
const oldMetric = getMetric(metricId);
|
|
860
|
+
const oldLength = collSize(numbers);
|
|
861
|
+
force ||= isUndefined(oldMetric);
|
|
796
862
|
change();
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
863
|
+
let newMetric = getAggregateValue(
|
|
864
|
+
oldMetric,
|
|
865
|
+
oldLength,
|
|
866
|
+
numbers,
|
|
867
|
+
changedNumbers,
|
|
868
|
+
aggregators,
|
|
869
|
+
force,
|
|
870
|
+
);
|
|
802
871
|
if (!isFiniteNumber(newMetric)) {
|
|
803
872
|
newMetric = void 0;
|
|
804
873
|
}
|
|
805
|
-
const oldMetric = getMetric(metricId);
|
|
806
874
|
if (newMetric != oldMetric) {
|
|
807
875
|
setMetric(metricId, newMetric);
|
|
808
876
|
callListeners(metricListeners, [metricId], newMetric, oldMetric);
|
|
@@ -860,7 +928,7 @@ const createCustomPersister = (
|
|
|
860
928
|
loads++;
|
|
861
929
|
}
|
|
862
930
|
const body = await getPersisted();
|
|
863
|
-
if (!isUndefined(body) && body !=
|
|
931
|
+
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
864
932
|
store.setJson(body);
|
|
865
933
|
} else {
|
|
866
934
|
store.setTables(initialTables);
|
|
@@ -1013,6 +1081,591 @@ const createRemotePersister = (
|
|
|
1013
1081
|
);
|
|
1014
1082
|
};
|
|
1015
1083
|
|
|
1084
|
+
const createQueries = getCreateFunction((store) => {
|
|
1085
|
+
const createStore = store.createStore;
|
|
1086
|
+
const [
|
|
1087
|
+
getStore,
|
|
1088
|
+
getQueryIds,
|
|
1089
|
+
forEachQuery,
|
|
1090
|
+
hasQuery,
|
|
1091
|
+
getTableId,
|
|
1092
|
+
,
|
|
1093
|
+
,
|
|
1094
|
+
setDefinition,
|
|
1095
|
+
,
|
|
1096
|
+
delDefinition,
|
|
1097
|
+
destroy,
|
|
1098
|
+
addStoreListeners,
|
|
1099
|
+
delStoreListeners,
|
|
1100
|
+
] = getDefinableFunctions(store, () => true, getUndefined);
|
|
1101
|
+
const preStore1 = createStore();
|
|
1102
|
+
const preStore2 = createStore();
|
|
1103
|
+
const resultStore = createStore();
|
|
1104
|
+
const preStoreListenerIds = mapNew();
|
|
1105
|
+
const addPreStoreListener = (preStore, queryId, ...listenerIds) =>
|
|
1106
|
+
arrayForEach(listenerIds, (listenerId) =>
|
|
1107
|
+
setAdd(
|
|
1108
|
+
mapEnsure(
|
|
1109
|
+
mapEnsure(preStoreListenerIds, queryId, mapNew),
|
|
1110
|
+
preStore,
|
|
1111
|
+
setNew,
|
|
1112
|
+
),
|
|
1113
|
+
listenerId,
|
|
1114
|
+
),
|
|
1115
|
+
);
|
|
1116
|
+
const cleanPreStores = (queryId) =>
|
|
1117
|
+
arrayForEach([resultStore, preStore2, preStore1], (store2) =>
|
|
1118
|
+
store2.delTable(queryId),
|
|
1119
|
+
);
|
|
1120
|
+
const synchronizeTransactions = (queryId, fromStore, toStore) =>
|
|
1121
|
+
addPreStoreListener(
|
|
1122
|
+
fromStore,
|
|
1123
|
+
queryId,
|
|
1124
|
+
fromStore.addWillFinishTransactionListener(toStore.startTransaction),
|
|
1125
|
+
fromStore.addDidFinishTransactionListener(() =>
|
|
1126
|
+
toStore.finishTransaction(),
|
|
1127
|
+
),
|
|
1128
|
+
);
|
|
1129
|
+
const setQueryDefinition = (queryId, tableId, build) => {
|
|
1130
|
+
setDefinition(queryId, tableId);
|
|
1131
|
+
cleanPreStores(queryId);
|
|
1132
|
+
let offsetLimit;
|
|
1133
|
+
const selectEntries = [];
|
|
1134
|
+
const joinEntries = [[null, [tableId, null, null, [], mapNew()]]];
|
|
1135
|
+
const wheres = [];
|
|
1136
|
+
const groupEntries = [];
|
|
1137
|
+
const havings = [];
|
|
1138
|
+
const orders = [];
|
|
1139
|
+
const select = (arg1, arg2) => {
|
|
1140
|
+
const selectEntry = isFunction(arg1)
|
|
1141
|
+
? [arrayLength(selectEntries) + EMPTY_STRING, arg1]
|
|
1142
|
+
: [
|
|
1143
|
+
isUndefined(arg2) ? arg1 : arg2,
|
|
1144
|
+
(getTableCell) => getTableCell(arg1, arg2),
|
|
1145
|
+
];
|
|
1146
|
+
arrayPush(selectEntries, selectEntry);
|
|
1147
|
+
return {as: (selectedCellId) => (selectEntry[0] = selectedCellId)};
|
|
1148
|
+
};
|
|
1149
|
+
const join = (joinedTableId, arg1, arg2) => {
|
|
1150
|
+
const fromIntermediateJoinedTableId =
|
|
1151
|
+
isUndefined(arg2) || isFunction(arg1) ? null : arg1;
|
|
1152
|
+
const onArg = isUndefined(fromIntermediateJoinedTableId) ? arg1 : arg2;
|
|
1153
|
+
const joinEntry = [
|
|
1154
|
+
joinedTableId,
|
|
1155
|
+
[
|
|
1156
|
+
joinedTableId,
|
|
1157
|
+
fromIntermediateJoinedTableId,
|
|
1158
|
+
isFunction(onArg) ? onArg : (getCell) => getCell(onArg),
|
|
1159
|
+
[],
|
|
1160
|
+
mapNew(),
|
|
1161
|
+
],
|
|
1162
|
+
];
|
|
1163
|
+
arrayPush(joinEntries, joinEntry);
|
|
1164
|
+
return {as: (joinedTableId2) => (joinEntry[0] = joinedTableId2)};
|
|
1165
|
+
};
|
|
1166
|
+
const where = (arg1, arg2, arg3) =>
|
|
1167
|
+
arrayPush(
|
|
1168
|
+
wheres,
|
|
1169
|
+
isFunction(arg1)
|
|
1170
|
+
? arg1
|
|
1171
|
+
: isUndefined(arg3)
|
|
1172
|
+
? (getTableCell) => getTableCell(arg1) === arg2
|
|
1173
|
+
: (getTableCell) => getTableCell(arg1, arg2) === arg3,
|
|
1174
|
+
);
|
|
1175
|
+
const group = (
|
|
1176
|
+
selectedCellId,
|
|
1177
|
+
aggregate,
|
|
1178
|
+
aggregateAdd,
|
|
1179
|
+
aggregateRemove,
|
|
1180
|
+
aggregateReplace,
|
|
1181
|
+
) => {
|
|
1182
|
+
const groupEntry = [
|
|
1183
|
+
selectedCellId,
|
|
1184
|
+
[
|
|
1185
|
+
selectedCellId,
|
|
1186
|
+
isFunction(aggregate)
|
|
1187
|
+
? [aggregate, aggregateAdd, aggregateRemove, aggregateReplace]
|
|
1188
|
+
: mapGet(numericAggregators, aggregate) ?? [
|
|
1189
|
+
(_cells, length) => length,
|
|
1190
|
+
],
|
|
1191
|
+
],
|
|
1192
|
+
];
|
|
1193
|
+
arrayPush(groupEntries, groupEntry);
|
|
1194
|
+
return {as: (groupedCellId) => (groupEntry[0] = groupedCellId)};
|
|
1195
|
+
};
|
|
1196
|
+
const having = (arg1, arg2) =>
|
|
1197
|
+
arrayPush(
|
|
1198
|
+
havings,
|
|
1199
|
+
isFunction(arg1)
|
|
1200
|
+
? arg1
|
|
1201
|
+
: (getSelectedOrGroupedCell) =>
|
|
1202
|
+
getSelectedOrGroupedCell(arg1) === arg2,
|
|
1203
|
+
);
|
|
1204
|
+
const order = (arg1, descending) =>
|
|
1205
|
+
arrayPush(orders, [
|
|
1206
|
+
isFunction(arg1)
|
|
1207
|
+
? arg1
|
|
1208
|
+
: (getSelectedOrGroupedCell) => getSelectedOrGroupedCell(arg1) ?? 0,
|
|
1209
|
+
descending,
|
|
1210
|
+
]);
|
|
1211
|
+
const limit = (arg1, arg2) => {
|
|
1212
|
+
offsetLimit = isUndefined(arg2) ? [0, arg1] : [arg1, arg2];
|
|
1213
|
+
};
|
|
1214
|
+
build({select, join, where, group, having, order, limit});
|
|
1215
|
+
const selects = mapNew(selectEntries);
|
|
1216
|
+
if (collIsEmpty(selects)) {
|
|
1217
|
+
return queries;
|
|
1218
|
+
}
|
|
1219
|
+
const joins = mapNew(joinEntries);
|
|
1220
|
+
mapForEach(joins, (asTableId, [, fromAsTableId]) =>
|
|
1221
|
+
ifNotUndefined(mapGet(joins, fromAsTableId), ({3: toAsTableIds}) =>
|
|
1222
|
+
isUndefined(asTableId) ? 0 : arrayPush(toAsTableIds, asTableId),
|
|
1223
|
+
),
|
|
1224
|
+
);
|
|
1225
|
+
const groups = mapNew(groupEntries);
|
|
1226
|
+
let selectJoinWhereStore = preStore1;
|
|
1227
|
+
let groupHavingStore = preStore2;
|
|
1228
|
+
if (arrayIsEmpty(orders) && isUndefined(offsetLimit)) {
|
|
1229
|
+
groupHavingStore = resultStore;
|
|
1230
|
+
} else {
|
|
1231
|
+
synchronizeTransactions(queryId, groupHavingStore, resultStore);
|
|
1232
|
+
const groupRowIdSorter = (rowId1, rowId2) => {
|
|
1233
|
+
const sortKeys1 = mapGet(sortKeysByGroupRowId, rowId1) ?? [];
|
|
1234
|
+
const sortKeys2 = mapGet(sortKeysByGroupRowId, rowId2) ?? [];
|
|
1235
|
+
const orderIndex = orders.findIndex(
|
|
1236
|
+
(_order, index) => sortKeys1[index] !== sortKeys2[index],
|
|
1237
|
+
);
|
|
1238
|
+
return orderIndex < 0
|
|
1239
|
+
? 0
|
|
1240
|
+
: defaultSorter(sortKeys1[orderIndex], sortKeys2[orderIndex]) *
|
|
1241
|
+
(orders[orderIndex][1] ? -1 : 1);
|
|
1242
|
+
};
|
|
1243
|
+
const sortKeysByGroupRowId = mapNew();
|
|
1244
|
+
const sortedGroupRowIds = mapNew();
|
|
1245
|
+
addPreStoreListener(
|
|
1246
|
+
groupHavingStore,
|
|
1247
|
+
queryId,
|
|
1248
|
+
arrayIsEmpty(orders)
|
|
1249
|
+
? groupHavingStore.addRowIdsListener(queryId, () =>
|
|
1250
|
+
collClear(sortedGroupRowIds),
|
|
1251
|
+
)
|
|
1252
|
+
: groupHavingStore.addRowListener(
|
|
1253
|
+
queryId,
|
|
1254
|
+
null,
|
|
1255
|
+
(_store, _tableId, groupRowId) => {
|
|
1256
|
+
let newSortKeys = null;
|
|
1257
|
+
if (groupHavingStore.hasRow(queryId, groupRowId)) {
|
|
1258
|
+
const oldSortKeys =
|
|
1259
|
+
mapGet(sortKeysByGroupRowId, groupRowId) ?? [];
|
|
1260
|
+
const groupRow = groupHavingStore.getRow(queryId, groupRowId);
|
|
1261
|
+
const getCell = (getSelectedOrGroupedCell) =>
|
|
1262
|
+
groupRow[getSelectedOrGroupedCell];
|
|
1263
|
+
newSortKeys = arrayMap(orders, ([getSortKey]) =>
|
|
1264
|
+
getSortKey(getCell, groupRowId),
|
|
1265
|
+
);
|
|
1266
|
+
if (arrayIsEqual(oldSortKeys, newSortKeys)) {
|
|
1267
|
+
if (mapGet(sortedGroupRowIds, groupRowId)) {
|
|
1268
|
+
resultStore.setRow(queryId, groupRowId, groupRow);
|
|
1269
|
+
}
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
mapSet(sortKeysByGroupRowId, groupRowId, newSortKeys);
|
|
1274
|
+
collClear(sortedGroupRowIds);
|
|
1275
|
+
},
|
|
1276
|
+
),
|
|
1277
|
+
groupHavingStore.addTableListener(queryId, () => {
|
|
1278
|
+
if (collIsEmpty(sortedGroupRowIds)) {
|
|
1279
|
+
resultStore.delTable(queryId);
|
|
1280
|
+
if (groupHavingStore.hasTable(queryId)) {
|
|
1281
|
+
const groupTable = groupHavingStore.getTable(queryId);
|
|
1282
|
+
arrayForEach(
|
|
1283
|
+
arraySort(objIds(groupTable), groupRowIdSorter),
|
|
1284
|
+
(id) => mapSet(sortedGroupRowIds, id, 0),
|
|
1285
|
+
);
|
|
1286
|
+
arrayForEach(
|
|
1287
|
+
ifNotUndefined(
|
|
1288
|
+
offsetLimit,
|
|
1289
|
+
([offset, limit2]) =>
|
|
1290
|
+
arraySlice(
|
|
1291
|
+
mapKeys(sortedGroupRowIds),
|
|
1292
|
+
offset,
|
|
1293
|
+
offset + limit2,
|
|
1294
|
+
),
|
|
1295
|
+
() => mapKeys(sortedGroupRowIds),
|
|
1296
|
+
),
|
|
1297
|
+
(groupRowId) => {
|
|
1298
|
+
resultStore.setRow(
|
|
1299
|
+
queryId,
|
|
1300
|
+
groupRowId,
|
|
1301
|
+
groupTable[groupRowId],
|
|
1302
|
+
);
|
|
1303
|
+
mapSet(sortedGroupRowIds, groupRowId, 1);
|
|
1304
|
+
},
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}),
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
if (collIsEmpty(groups) && arrayIsEmpty(havings)) {
|
|
1312
|
+
selectJoinWhereStore = groupHavingStore;
|
|
1313
|
+
} else {
|
|
1314
|
+
synchronizeTransactions(queryId, selectJoinWhereStore, groupHavingStore);
|
|
1315
|
+
const groupedSelectedCellIds = mapNew();
|
|
1316
|
+
mapForEach(groups, (groupedCellId, [selectedCellId, aggregators]) =>
|
|
1317
|
+
setAdd(mapEnsure(groupedSelectedCellIds, selectedCellId, setNew), [
|
|
1318
|
+
groupedCellId,
|
|
1319
|
+
aggregators,
|
|
1320
|
+
]),
|
|
1321
|
+
);
|
|
1322
|
+
const groupBySelectedCellIds = setNew();
|
|
1323
|
+
mapForEach(selects, (selectedCellId) =>
|
|
1324
|
+
collHas(groupedSelectedCellIds, selectedCellId)
|
|
1325
|
+
? 0
|
|
1326
|
+
: setAdd(groupBySelectedCellIds, selectedCellId),
|
|
1327
|
+
);
|
|
1328
|
+
const tree = mapNew();
|
|
1329
|
+
const writeGroupRow = (
|
|
1330
|
+
leaf,
|
|
1331
|
+
changedGroupedSelectedCells,
|
|
1332
|
+
selectedRowId,
|
|
1333
|
+
forceRemove,
|
|
1334
|
+
) =>
|
|
1335
|
+
ifNotUndefined(
|
|
1336
|
+
leaf,
|
|
1337
|
+
([selectedCells, selectedRowIds, groupRowId, groupRow]) => {
|
|
1338
|
+
mapForEach(
|
|
1339
|
+
changedGroupedSelectedCells,
|
|
1340
|
+
(selectedCellId, [newCell]) => {
|
|
1341
|
+
const selectedCell = mapEnsure(
|
|
1342
|
+
selectedCells,
|
|
1343
|
+
selectedCellId,
|
|
1344
|
+
mapNew,
|
|
1345
|
+
);
|
|
1346
|
+
const oldLeafCell = mapGet(selectedCell, selectedRowId);
|
|
1347
|
+
const newLeafCell = forceRemove ? void 0 : newCell;
|
|
1348
|
+
if (oldLeafCell !== newLeafCell) {
|
|
1349
|
+
const oldNewSet = setNew([[oldLeafCell, newLeafCell]]);
|
|
1350
|
+
const oldLength = collSize(selectedCell);
|
|
1351
|
+
mapSet(selectedCell, selectedRowId, newLeafCell);
|
|
1352
|
+
collForEach(
|
|
1353
|
+
mapGet(groupedSelectedCellIds, selectedCellId),
|
|
1354
|
+
([groupedCellId, aggregators]) => {
|
|
1355
|
+
const aggregateValue = getAggregateValue(
|
|
1356
|
+
groupRow[groupedCellId],
|
|
1357
|
+
oldLength,
|
|
1358
|
+
selectedCell,
|
|
1359
|
+
oldNewSet,
|
|
1360
|
+
aggregators,
|
|
1361
|
+
);
|
|
1362
|
+
groupRow[groupedCellId] = isUndefined(
|
|
1363
|
+
getCellType(aggregateValue),
|
|
1364
|
+
)
|
|
1365
|
+
? null
|
|
1366
|
+
: aggregateValue;
|
|
1367
|
+
},
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
},
|
|
1371
|
+
);
|
|
1372
|
+
(collIsEmpty(selectedRowIds) ||
|
|
1373
|
+
!arrayEvery(havings, (having2) =>
|
|
1374
|
+
having2((cellId) => groupRow[cellId]),
|
|
1375
|
+
)
|
|
1376
|
+
? groupHavingStore.delRow
|
|
1377
|
+
: groupHavingStore.setRow)(queryId, groupRowId, groupRow);
|
|
1378
|
+
},
|
|
1379
|
+
);
|
|
1380
|
+
addPreStoreListener(
|
|
1381
|
+
selectJoinWhereStore,
|
|
1382
|
+
queryId,
|
|
1383
|
+
selectJoinWhereStore.addRowListener(
|
|
1384
|
+
queryId,
|
|
1385
|
+
null,
|
|
1386
|
+
(_store, _tableId, selectedRowId, getCellChange) => {
|
|
1387
|
+
const oldPath = [];
|
|
1388
|
+
const newPath = [];
|
|
1389
|
+
const changedGroupedSelectedCells = mapNew();
|
|
1390
|
+
const rowExists = selectJoinWhereStore.hasRow(
|
|
1391
|
+
queryId,
|
|
1392
|
+
selectedRowId,
|
|
1393
|
+
);
|
|
1394
|
+
let changedLeaf = !rowExists;
|
|
1395
|
+
collForEach(groupBySelectedCellIds, (selectedCellId) => {
|
|
1396
|
+
const [changed, oldCell, newCell] = getCellChange(
|
|
1397
|
+
queryId,
|
|
1398
|
+
selectedRowId,
|
|
1399
|
+
selectedCellId,
|
|
1400
|
+
);
|
|
1401
|
+
arrayPush(oldPath, oldCell);
|
|
1402
|
+
arrayPush(newPath, newCell);
|
|
1403
|
+
changedLeaf ||= changed;
|
|
1404
|
+
});
|
|
1405
|
+
mapForEach(groupedSelectedCellIds, (selectedCellId) => {
|
|
1406
|
+
const [changed, , newCell] = getCellChange(
|
|
1407
|
+
queryId,
|
|
1408
|
+
selectedRowId,
|
|
1409
|
+
selectedCellId,
|
|
1410
|
+
);
|
|
1411
|
+
if (changedLeaf || changed) {
|
|
1412
|
+
mapSet(changedGroupedSelectedCells, selectedCellId, [newCell]);
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1415
|
+
if (changedLeaf) {
|
|
1416
|
+
writeGroupRow(
|
|
1417
|
+
visitTree(
|
|
1418
|
+
tree,
|
|
1419
|
+
oldPath,
|
|
1420
|
+
void 0,
|
|
1421
|
+
([, selectedRowIds, groupRowId]) => {
|
|
1422
|
+
collDel(selectedRowIds, selectedRowId);
|
|
1423
|
+
if (collIsEmpty(selectedRowIds)) {
|
|
1424
|
+
groupHavingStore.delRow(queryId, groupRowId);
|
|
1425
|
+
return 1;
|
|
1426
|
+
}
|
|
1427
|
+
},
|
|
1428
|
+
),
|
|
1429
|
+
changedGroupedSelectedCells,
|
|
1430
|
+
selectedRowId,
|
|
1431
|
+
1,
|
|
1432
|
+
);
|
|
1433
|
+
}
|
|
1434
|
+
if (rowExists) {
|
|
1435
|
+
writeGroupRow(
|
|
1436
|
+
visitTree(
|
|
1437
|
+
tree,
|
|
1438
|
+
newPath,
|
|
1439
|
+
() => {
|
|
1440
|
+
const groupRow = {};
|
|
1441
|
+
collForEach(
|
|
1442
|
+
groupBySelectedCellIds,
|
|
1443
|
+
(selectedCellId) =>
|
|
1444
|
+
(groupRow[selectedCellId] =
|
|
1445
|
+
selectJoinWhereStore.getCell(
|
|
1446
|
+
queryId,
|
|
1447
|
+
selectedRowId,
|
|
1448
|
+
selectedCellId,
|
|
1449
|
+
)),
|
|
1450
|
+
);
|
|
1451
|
+
return [
|
|
1452
|
+
mapNew(),
|
|
1453
|
+
setNew(),
|
|
1454
|
+
groupHavingStore.addRow(queryId, groupRow, 1),
|
|
1455
|
+
groupRow,
|
|
1456
|
+
];
|
|
1457
|
+
},
|
|
1458
|
+
([, selectedRowIds]) => {
|
|
1459
|
+
setAdd(selectedRowIds, selectedRowId);
|
|
1460
|
+
},
|
|
1461
|
+
),
|
|
1462
|
+
changedGroupedSelectedCells,
|
|
1463
|
+
selectedRowId,
|
|
1464
|
+
);
|
|
1465
|
+
}
|
|
1466
|
+
},
|
|
1467
|
+
),
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
synchronizeTransactions(queryId, store, selectJoinWhereStore);
|
|
1471
|
+
const writeSelectRow = (rootRowId) => {
|
|
1472
|
+
const getTableCell = (arg1, arg2) =>
|
|
1473
|
+
store.getCell(
|
|
1474
|
+
...(isUndefined(arg2)
|
|
1475
|
+
? [tableId, rootRowId, arg1]
|
|
1476
|
+
: arg1 === tableId
|
|
1477
|
+
? [tableId, rootRowId, arg2]
|
|
1478
|
+
: [
|
|
1479
|
+
mapGet(joins, arg1)?.[0],
|
|
1480
|
+
mapGet(mapGet(joins, arg1)?.[4], rootRowId)?.[0],
|
|
1481
|
+
arg2,
|
|
1482
|
+
]),
|
|
1483
|
+
);
|
|
1484
|
+
selectJoinWhereStore.transaction(() =>
|
|
1485
|
+
arrayEvery(wheres, (where2) => where2(getTableCell))
|
|
1486
|
+
? mapForEach(selects, (asCellId, tableCellGetter) =>
|
|
1487
|
+
setOrDelCell(
|
|
1488
|
+
selectJoinWhereStore,
|
|
1489
|
+
queryId,
|
|
1490
|
+
rootRowId,
|
|
1491
|
+
asCellId,
|
|
1492
|
+
tableCellGetter(getTableCell, rootRowId),
|
|
1493
|
+
),
|
|
1494
|
+
)
|
|
1495
|
+
: selectJoinWhereStore.delRow(queryId, rootRowId),
|
|
1496
|
+
);
|
|
1497
|
+
};
|
|
1498
|
+
const listenToTable = (rootRowId, tableId2, rowId, joinedTableIds2) => {
|
|
1499
|
+
const getCell = (cellId) => store.getCell(tableId2, rowId, cellId);
|
|
1500
|
+
arrayForEach(joinedTableIds2, (remoteAsTableId) => {
|
|
1501
|
+
const [realJoinedTableId, , on, nextJoinedTableIds, remoteIdPair] =
|
|
1502
|
+
mapGet(joins, remoteAsTableId);
|
|
1503
|
+
const remoteRowId = on?.(getCell, rootRowId);
|
|
1504
|
+
const [previousRemoteRowId, previousRemoteListenerId] =
|
|
1505
|
+
mapGet(remoteIdPair, rootRowId) ?? [];
|
|
1506
|
+
if (remoteRowId != previousRemoteRowId) {
|
|
1507
|
+
if (!isUndefined(previousRemoteListenerId)) {
|
|
1508
|
+
delStoreListeners(queryId, previousRemoteListenerId);
|
|
1509
|
+
}
|
|
1510
|
+
mapSet(
|
|
1511
|
+
remoteIdPair,
|
|
1512
|
+
rootRowId,
|
|
1513
|
+
isUndefined(remoteRowId)
|
|
1514
|
+
? null
|
|
1515
|
+
: [
|
|
1516
|
+
remoteRowId,
|
|
1517
|
+
...addStoreListeners(
|
|
1518
|
+
queryId,
|
|
1519
|
+
1,
|
|
1520
|
+
store.addRowListener(realJoinedTableId, remoteRowId, () =>
|
|
1521
|
+
listenToTable(
|
|
1522
|
+
rootRowId,
|
|
1523
|
+
realJoinedTableId,
|
|
1524
|
+
remoteRowId,
|
|
1525
|
+
nextJoinedTableIds,
|
|
1526
|
+
),
|
|
1527
|
+
),
|
|
1528
|
+
),
|
|
1529
|
+
],
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
});
|
|
1533
|
+
writeSelectRow(rootRowId);
|
|
1534
|
+
};
|
|
1535
|
+
const {3: joinedTableIds} = mapGet(joins, null);
|
|
1536
|
+
selectJoinWhereStore.transaction(() =>
|
|
1537
|
+
addStoreListeners(
|
|
1538
|
+
queryId,
|
|
1539
|
+
1,
|
|
1540
|
+
store.addRowListener(tableId, null, (_store, _tableId, rootRowId) => {
|
|
1541
|
+
if (store.hasRow(tableId, rootRowId)) {
|
|
1542
|
+
listenToTable(rootRowId, tableId, rootRowId, joinedTableIds);
|
|
1543
|
+
} else {
|
|
1544
|
+
selectJoinWhereStore.delRow(queryId, rootRowId);
|
|
1545
|
+
collForEach(joins, ({4: idsByRootRowId}) =>
|
|
1546
|
+
ifNotUndefined(
|
|
1547
|
+
mapGet(idsByRootRowId, rootRowId),
|
|
1548
|
+
([, listenerId]) => {
|
|
1549
|
+
delStoreListeners(queryId, listenerId);
|
|
1550
|
+
mapSet(idsByRootRowId, rootRowId);
|
|
1551
|
+
},
|
|
1552
|
+
),
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
}),
|
|
1556
|
+
),
|
|
1557
|
+
);
|
|
1558
|
+
return queries;
|
|
1559
|
+
};
|
|
1560
|
+
const delQueryDefinition = (queryId) => {
|
|
1561
|
+
mapForEach(mapGet(preStoreListenerIds, queryId), (preStore, listenerIds) =>
|
|
1562
|
+
collForEach(listenerIds, (listenerId) =>
|
|
1563
|
+
preStore.delListener(listenerId),
|
|
1564
|
+
),
|
|
1565
|
+
);
|
|
1566
|
+
cleanPreStores(queryId);
|
|
1567
|
+
delDefinition(queryId);
|
|
1568
|
+
return queries;
|
|
1569
|
+
};
|
|
1570
|
+
const getResultTable = (queryId) => resultStore.getTable(queryId);
|
|
1571
|
+
const getResultRowIds = (queryId) => resultStore.getRowIds(queryId);
|
|
1572
|
+
const getResultSortedRowIds = (queryId, cellId, descending) =>
|
|
1573
|
+
resultStore.getSortedRowIds(queryId, cellId, descending);
|
|
1574
|
+
const getResultRow = (queryId, rowId) => resultStore.getRow(queryId, rowId);
|
|
1575
|
+
const getResultCellIds = (queryId, rowId) =>
|
|
1576
|
+
resultStore.getCellIds(queryId, rowId);
|
|
1577
|
+
const getResultCell = (queryId, rowId, cellId) =>
|
|
1578
|
+
resultStore.getCell(queryId, rowId, cellId);
|
|
1579
|
+
const hasResultTable = (queryId) => resultStore.hasTable(queryId);
|
|
1580
|
+
const hasResultRow = (queryId, rowId) => resultStore.hasRow(queryId, rowId);
|
|
1581
|
+
const hasResultCell = (queryId, rowId, cellId) =>
|
|
1582
|
+
resultStore.hasCell(queryId, rowId, cellId);
|
|
1583
|
+
const forEachResultTable = (tableCallback) =>
|
|
1584
|
+
resultStore.forEachTable(tableCallback);
|
|
1585
|
+
const forEachResultRow = (queryId, rowCallback) =>
|
|
1586
|
+
resultStore.forEachRow(queryId, rowCallback);
|
|
1587
|
+
const forEachResultCell = (queryId, rowId, cellCallback) =>
|
|
1588
|
+
resultStore.forEachCell(queryId, rowId, cellCallback);
|
|
1589
|
+
const addResultTableListener = (queryId, listener) =>
|
|
1590
|
+
resultStore.addTableListener(queryId, (_store, ...args) =>
|
|
1591
|
+
listener(queries, ...args),
|
|
1592
|
+
);
|
|
1593
|
+
const addResultRowIdsListener = (queryId, listener, trackReorder) =>
|
|
1594
|
+
resultStore.addRowIdsListener(
|
|
1595
|
+
queryId,
|
|
1596
|
+
(_store, ...args) => listener(queries, ...args),
|
|
1597
|
+
trackReorder,
|
|
1598
|
+
);
|
|
1599
|
+
const addResultSortedRowIdsListener = (
|
|
1600
|
+
queryId,
|
|
1601
|
+
cellId,
|
|
1602
|
+
descending,
|
|
1603
|
+
listener,
|
|
1604
|
+
) =>
|
|
1605
|
+
resultStore.addSortedRowIdsListener(
|
|
1606
|
+
queryId,
|
|
1607
|
+
cellId,
|
|
1608
|
+
descending,
|
|
1609
|
+
(_store, ...args) => listener(queries, ...args),
|
|
1610
|
+
);
|
|
1611
|
+
const addResultRowListener = (queryId, rowId, listener) =>
|
|
1612
|
+
resultStore.addRowListener(queryId, rowId, (_store, ...args) =>
|
|
1613
|
+
listener(queries, ...args),
|
|
1614
|
+
);
|
|
1615
|
+
const addResultCellIdsListener = (queryId, rowId, listener) =>
|
|
1616
|
+
resultStore.addCellIdsListener(queryId, rowId, (_store, ...args) =>
|
|
1617
|
+
listener(queries, ...args),
|
|
1618
|
+
);
|
|
1619
|
+
const addResultCellListener = (queryId, rowId, cellId, listener) =>
|
|
1620
|
+
resultStore.addCellListener(queryId, rowId, cellId, (_store, ...args) =>
|
|
1621
|
+
listener(queries, ...args),
|
|
1622
|
+
);
|
|
1623
|
+
const delListener = (listenerId) => {
|
|
1624
|
+
resultStore.delListener(listenerId);
|
|
1625
|
+
return queries;
|
|
1626
|
+
};
|
|
1627
|
+
const getListenerStats = () => {
|
|
1628
|
+
const {
|
|
1629
|
+
tables: _1,
|
|
1630
|
+
tableIds: _2,
|
|
1631
|
+
transaction: _3,
|
|
1632
|
+
...stats
|
|
1633
|
+
} = resultStore.getListenerStats();
|
|
1634
|
+
return stats;
|
|
1635
|
+
};
|
|
1636
|
+
const queries = {
|
|
1637
|
+
setQueryDefinition,
|
|
1638
|
+
delQueryDefinition,
|
|
1639
|
+
getStore,
|
|
1640
|
+
getQueryIds,
|
|
1641
|
+
forEachQuery,
|
|
1642
|
+
hasQuery,
|
|
1643
|
+
getTableId,
|
|
1644
|
+
getResultTable,
|
|
1645
|
+
getResultRowIds,
|
|
1646
|
+
getResultSortedRowIds,
|
|
1647
|
+
getResultRow,
|
|
1648
|
+
getResultCellIds,
|
|
1649
|
+
getResultCell,
|
|
1650
|
+
hasResultTable,
|
|
1651
|
+
hasResultRow,
|
|
1652
|
+
hasResultCell,
|
|
1653
|
+
forEachResultTable,
|
|
1654
|
+
forEachResultRow,
|
|
1655
|
+
forEachResultCell,
|
|
1656
|
+
addResultTableListener,
|
|
1657
|
+
addResultRowIdsListener,
|
|
1658
|
+
addResultSortedRowIdsListener,
|
|
1659
|
+
addResultRowListener,
|
|
1660
|
+
addResultCellIdsListener,
|
|
1661
|
+
addResultCellListener,
|
|
1662
|
+
delListener,
|
|
1663
|
+
destroy,
|
|
1664
|
+
getListenerStats,
|
|
1665
|
+
};
|
|
1666
|
+
return objFreeze(queries);
|
|
1667
|
+
});
|
|
1668
|
+
|
|
1016
1669
|
const createRelationships = getCreateFunction((store) => {
|
|
1017
1670
|
const remoteTableIds = mapNew();
|
|
1018
1671
|
const remoteRowIdListeners = mapNew();
|
|
@@ -1026,7 +1679,8 @@ const createRelationships = getCreateFunction((store) => {
|
|
|
1026
1679
|
getLocalTableId,
|
|
1027
1680
|
getRelationship,
|
|
1028
1681
|
,
|
|
1029
|
-
|
|
1682
|
+
,
|
|
1683
|
+
setDefinitionAndListen,
|
|
1030
1684
|
delDefinition,
|
|
1031
1685
|
destroy,
|
|
1032
1686
|
] = getDefinableFunctions(
|
|
@@ -1073,7 +1727,7 @@ const createRelationships = getCreateFunction((store) => {
|
|
|
1073
1727
|
getRemoteRowId2,
|
|
1074
1728
|
) => {
|
|
1075
1729
|
mapSet(remoteTableIds, relationshipId, remoteTableId);
|
|
1076
|
-
|
|
1730
|
+
setDefinitionAndListen(
|
|
1077
1731
|
relationshipId,
|
|
1078
1732
|
localTableId,
|
|
1079
1733
|
(change, changedRemoteRowIds) => {
|
|
@@ -1199,6 +1853,14 @@ const createRelationships = getCreateFunction((store) => {
|
|
|
1199
1853
|
return objFreeze(relationships);
|
|
1200
1854
|
});
|
|
1201
1855
|
|
|
1856
|
+
const pairNew = (value) => [value, value];
|
|
1857
|
+
const pairCollSize2 = (pair, func = collSize2) => func(pair[0]) + func(pair[1]);
|
|
1858
|
+
const pairCollIsEmpty = (pair) => pairCollSize2(pair) == 0;
|
|
1859
|
+
const pairNewMap = () => [mapNew(), mapNew()];
|
|
1860
|
+
const pair2CollSize2 = (pair2, func = collSize2) =>
|
|
1861
|
+
pairCollSize2(pair2[0], func) + pairCollSize2(pair2[1], func);
|
|
1862
|
+
const pair2NewMap = () => [pairNewMap(), pairNewMap()];
|
|
1863
|
+
|
|
1202
1864
|
const transformMap = (map, toBeLikeObject, setId, delId = mapSet) => {
|
|
1203
1865
|
const idsToDelete = arrayFilter(
|
|
1204
1866
|
mapKeys(map),
|
|
@@ -1210,12 +1872,6 @@ const transformMap = (map, toBeLikeObject, setId, delId = mapSet) => {
|
|
|
1210
1872
|
arrayForEach(idsToDelete, (id2) => delId(map, id2));
|
|
1211
1873
|
return map;
|
|
1212
1874
|
};
|
|
1213
|
-
const getCellType = (cell) => {
|
|
1214
|
-
const type = getTypeOf(cell);
|
|
1215
|
-
return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
|
|
1216
|
-
? type
|
|
1217
|
-
: void 0;
|
|
1218
|
-
};
|
|
1219
1875
|
const validate = (obj, validateChild, onInvalidObj) => {
|
|
1220
1876
|
if (isUndefined(obj) || !isObject(obj) || objIsEmpty(obj) || objFrozen(obj)) {
|
|
1221
1877
|
onInvalidObj?.();
|
|
@@ -1228,8 +1884,8 @@ const validate = (obj, validateChild, onInvalidObj) => {
|
|
|
1228
1884
|
});
|
|
1229
1885
|
return !objIsEmpty(obj);
|
|
1230
1886
|
};
|
|
1231
|
-
const idsChanged = (
|
|
1232
|
-
mapSet(
|
|
1887
|
+
const idsChanged = (changedIds, id2, added) =>
|
|
1888
|
+
mapSet(changedIds, id2, mapGet(changedIds, id2) == -added ? void 0 : added);
|
|
1233
1889
|
const createStore = () => {
|
|
1234
1890
|
let hasSchema;
|
|
1235
1891
|
let cellsTouched;
|
|
@@ -1243,17 +1899,23 @@ const createStore = () => {
|
|
|
1243
1899
|
const schemaMap = mapNew();
|
|
1244
1900
|
const schemaRowCache = mapNew();
|
|
1245
1901
|
const tablesMap = mapNew();
|
|
1246
|
-
const tablesListeners =
|
|
1247
|
-
const tableIdsListeners =
|
|
1248
|
-
const tableListeners =
|
|
1249
|
-
const rowIdsListeners =
|
|
1250
|
-
const
|
|
1251
|
-
const
|
|
1252
|
-
const
|
|
1253
|
-
const
|
|
1254
|
-
const
|
|
1255
|
-
const
|
|
1256
|
-
|
|
1902
|
+
const tablesListeners = pairNewMap();
|
|
1903
|
+
const tableIdsListeners = pair2NewMap();
|
|
1904
|
+
const tableListeners = pairNewMap();
|
|
1905
|
+
const rowIdsListeners = pair2NewMap();
|
|
1906
|
+
const sortedRowIdsListeners = pairNewMap();
|
|
1907
|
+
const rowListeners = pairNewMap();
|
|
1908
|
+
const cellIdsListeners = pair2NewMap();
|
|
1909
|
+
const cellListeners = pairNewMap();
|
|
1910
|
+
const invalidCellListeners = pairNewMap();
|
|
1911
|
+
const finishTransactionListeners = pairNewMap();
|
|
1912
|
+
const [
|
|
1913
|
+
addListener,
|
|
1914
|
+
callListeners,
|
|
1915
|
+
delListenerImpl,
|
|
1916
|
+
hasListeners,
|
|
1917
|
+
callListenerImpl,
|
|
1918
|
+
] = getListenerFunctions(() => store);
|
|
1257
1919
|
const validateSchema = (schema) =>
|
|
1258
1920
|
validate(schema, (tableSchema) =>
|
|
1259
1921
|
validate(tableSchema, (cellSchema) => {
|
|
@@ -1435,12 +2097,49 @@ const createStore = () => {
|
|
|
1435
2097
|
}
|
|
1436
2098
|
};
|
|
1437
2099
|
const tableIdsChanged = (tableId, added) =>
|
|
1438
|
-
idsChanged(
|
|
2100
|
+
idsChanged(
|
|
2101
|
+
collIsEmpty(changedTableIds)
|
|
2102
|
+
? mapSet(
|
|
2103
|
+
changedTableIds,
|
|
2104
|
+
null,
|
|
2105
|
+
hasListeners(tableIdsListeners[0][1]) ||
|
|
2106
|
+
hasListeners(tableIdsListeners[1][1])
|
|
2107
|
+
? getTableIds()
|
|
2108
|
+
: 0,
|
|
2109
|
+
)
|
|
2110
|
+
: changedTableIds,
|
|
2111
|
+
tableId,
|
|
2112
|
+
added,
|
|
2113
|
+
);
|
|
1439
2114
|
const rowIdsChanged = (tableId, rowId, added) =>
|
|
1440
|
-
idsChanged(
|
|
2115
|
+
idsChanged(
|
|
2116
|
+
mapEnsure(changedRowIds, tableId, () =>
|
|
2117
|
+
mapNew([
|
|
2118
|
+
[
|
|
2119
|
+
null,
|
|
2120
|
+
hasListeners(rowIdsListeners[0][1], [tableId]) ||
|
|
2121
|
+
hasListeners(rowIdsListeners[1][1], [tableId])
|
|
2122
|
+
? getRowIds(tableId)
|
|
2123
|
+
: 0,
|
|
2124
|
+
],
|
|
2125
|
+
]),
|
|
2126
|
+
),
|
|
2127
|
+
rowId,
|
|
2128
|
+
added,
|
|
2129
|
+
);
|
|
1441
2130
|
const cellIdsChanged = (tableId, rowId, cellId, added) =>
|
|
1442
2131
|
idsChanged(
|
|
1443
|
-
mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId,
|
|
2132
|
+
mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, () =>
|
|
2133
|
+
mapNew([
|
|
2134
|
+
[
|
|
2135
|
+
null,
|
|
2136
|
+
hasListeners(cellIdsListeners[0][1], [tableId, rowId]) ||
|
|
2137
|
+
hasListeners(cellIdsListeners[1][1], [tableId, rowId])
|
|
2138
|
+
? getCellIds(tableId, rowId)
|
|
2139
|
+
: 0,
|
|
2140
|
+
],
|
|
2141
|
+
]),
|
|
2142
|
+
),
|
|
1444
2143
|
cellId,
|
|
1445
2144
|
added,
|
|
1446
2145
|
);
|
|
@@ -1465,7 +2164,7 @@ const createStore = () => {
|
|
|
1465
2164
|
ifNotUndefined(
|
|
1466
2165
|
mapGet(mapGet(mapGet(changedCells, tableId), rowId), cellId),
|
|
1467
2166
|
([oldCell, newCell]) => [true, oldCell, newCell],
|
|
1468
|
-
() => [false, ...
|
|
2167
|
+
() => [false, ...pairNew(getCell(tableId, rowId, cellId))],
|
|
1469
2168
|
);
|
|
1470
2169
|
const callInvalidCellListeners = (mutator) =>
|
|
1471
2170
|
!collIsEmpty(invalidCells) && !collIsEmpty(invalidCellListeners[mutator])
|
|
@@ -1483,17 +2182,36 @@ const createStore = () => {
|
|
|
1483
2182
|
),
|
|
1484
2183
|
)
|
|
1485
2184
|
: 0;
|
|
2185
|
+
const callIdsListenersIfChanged = (listeners, changedIds, getIds, ids) => {
|
|
2186
|
+
if (collSize(changedIds) > 1) {
|
|
2187
|
+
callListeners(listeners[0], ids);
|
|
2188
|
+
callListeners(listeners[1], ids);
|
|
2189
|
+
return 1;
|
|
2190
|
+
}
|
|
2191
|
+
if (
|
|
2192
|
+
!collIsEmpty(changedIds) &&
|
|
2193
|
+
mapGet(changedIds, null) != 0 &&
|
|
2194
|
+
!arrayIsEqual(mapGet(changedIds, null), getIds(...(ids ?? [])))
|
|
2195
|
+
) {
|
|
2196
|
+
callListeners(listeners[1], ids);
|
|
2197
|
+
return 1;
|
|
2198
|
+
}
|
|
2199
|
+
};
|
|
1486
2200
|
const callListenersForChanges = (mutator) => {
|
|
2201
|
+
const emptySortedRowIdListeners = collIsEmpty(
|
|
2202
|
+
sortedRowIdsListeners[mutator],
|
|
2203
|
+
);
|
|
1487
2204
|
const emptyIdListeners =
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
2205
|
+
pairCollIsEmpty(cellIdsListeners[mutator]) &&
|
|
2206
|
+
pairCollIsEmpty(rowIdsListeners[mutator]) &&
|
|
2207
|
+
emptySortedRowIdListeners &&
|
|
2208
|
+
pairCollIsEmpty(tableIdsListeners[mutator]);
|
|
1491
2209
|
const emptyOtherListeners =
|
|
1492
2210
|
collIsEmpty(cellListeners[mutator]) &&
|
|
1493
2211
|
collIsEmpty(rowListeners[mutator]) &&
|
|
1494
2212
|
collIsEmpty(tableListeners[mutator]) &&
|
|
1495
2213
|
collIsEmpty(tablesListeners[mutator]);
|
|
1496
|
-
if (!
|
|
2214
|
+
if (!emptyIdListeners || !emptyOtherListeners) {
|
|
1497
2215
|
const changes = mutator
|
|
1498
2216
|
? [
|
|
1499
2217
|
mapClone(changedTableIds),
|
|
@@ -1504,20 +2222,55 @@ const createStore = () => {
|
|
|
1504
2222
|
: [changedTableIds, changedRowIds, changedCellIds, changedCells];
|
|
1505
2223
|
if (!emptyIdListeners) {
|
|
1506
2224
|
collForEach(changes[2], (rowCellIds, tableId) =>
|
|
1507
|
-
collForEach(rowCellIds, (changedIds, rowId) =>
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
2225
|
+
collForEach(rowCellIds, (changedIds, rowId) =>
|
|
2226
|
+
callIdsListenersIfChanged(
|
|
2227
|
+
cellIdsListeners[mutator],
|
|
2228
|
+
changedIds,
|
|
2229
|
+
getCellIds,
|
|
2230
|
+
[tableId, rowId],
|
|
2231
|
+
),
|
|
2232
|
+
),
|
|
1512
2233
|
);
|
|
2234
|
+
const calledSortableTableIds = setNew();
|
|
1513
2235
|
collForEach(changes[1], (changedIds, tableId) => {
|
|
1514
|
-
if (
|
|
1515
|
-
|
|
2236
|
+
if (
|
|
2237
|
+
callIdsListenersIfChanged(
|
|
2238
|
+
rowIdsListeners[mutator],
|
|
2239
|
+
changedIds,
|
|
2240
|
+
getRowIds,
|
|
2241
|
+
[tableId],
|
|
2242
|
+
) &&
|
|
2243
|
+
!emptySortedRowIdListeners
|
|
2244
|
+
) {
|
|
2245
|
+
callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
|
|
2246
|
+
setAdd(calledSortableTableIds, tableId);
|
|
1516
2247
|
}
|
|
1517
2248
|
});
|
|
1518
|
-
if (!
|
|
1519
|
-
|
|
2249
|
+
if (!emptySortedRowIdListeners) {
|
|
2250
|
+
collForEach(changes[3], (rows, tableId) => {
|
|
2251
|
+
if (!collHas(calledSortableTableIds, tableId)) {
|
|
2252
|
+
const sortableCellIds = setNew();
|
|
2253
|
+
collForEach(rows, (cells) =>
|
|
2254
|
+
collForEach(cells, ([oldCell, newCell], cellId) =>
|
|
2255
|
+
newCell !== oldCell
|
|
2256
|
+
? setAdd(sortableCellIds, cellId)
|
|
2257
|
+
: collDel(cells, cellId),
|
|
2258
|
+
),
|
|
2259
|
+
);
|
|
2260
|
+
collForEach(sortableCellIds, (cellId) =>
|
|
2261
|
+
callListeners(sortedRowIdsListeners[mutator], [
|
|
2262
|
+
tableId,
|
|
2263
|
+
cellId,
|
|
2264
|
+
]),
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
});
|
|
1520
2268
|
}
|
|
2269
|
+
callIdsListenersIfChanged(
|
|
2270
|
+
tableIdsListeners[mutator],
|
|
2271
|
+
changes[0],
|
|
2272
|
+
getTableIds,
|
|
2273
|
+
);
|
|
1521
2274
|
}
|
|
1522
2275
|
if (!emptyOtherListeners) {
|
|
1523
2276
|
let tablesChanged;
|
|
@@ -1550,7 +2303,7 @@ const createStore = () => {
|
|
|
1550
2303
|
}
|
|
1551
2304
|
});
|
|
1552
2305
|
if (tablesChanged) {
|
|
1553
|
-
callListeners(tablesListeners[mutator],
|
|
2306
|
+
callListeners(tablesListeners[mutator], void 0, getCellChange);
|
|
1554
2307
|
}
|
|
1555
2308
|
}
|
|
1556
2309
|
}
|
|
@@ -1565,6 +2318,23 @@ const createStore = () => {
|
|
|
1565
2318
|
const getTable = (tableId) =>
|
|
1566
2319
|
mapToObj(mapGet(tablesMap, id(tableId)), mapToObj);
|
|
1567
2320
|
const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
|
|
2321
|
+
const getSortedRowIds = (tableId, cellId, descending) => {
|
|
2322
|
+
const cells = [];
|
|
2323
|
+
mapForEach(mapGet(tablesMap, id(tableId)), (rowId, row) =>
|
|
2324
|
+
arrayPush(cells, [
|
|
2325
|
+
isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
|
|
2326
|
+
rowId,
|
|
2327
|
+
]),
|
|
2328
|
+
);
|
|
2329
|
+
return arrayMap(
|
|
2330
|
+
arraySort(
|
|
2331
|
+
cells,
|
|
2332
|
+
([cell1], [cell2]) =>
|
|
2333
|
+
defaultSorter(cell1, cell2) * (descending ? -1 : 1),
|
|
2334
|
+
),
|
|
2335
|
+
([, rowId]) => rowId,
|
|
2336
|
+
);
|
|
2337
|
+
};
|
|
1568
2338
|
const getRow = (tableId, rowId) =>
|
|
1569
2339
|
mapToObj(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
|
|
1570
2340
|
const getCellIds = (tableId, rowId) =>
|
|
@@ -1603,17 +2373,16 @@ const createStore = () => {
|
|
|
1603
2373
|
tableId,
|
|
1604
2374
|
rowId,
|
|
1605
2375
|
);
|
|
1606
|
-
const addRow = (tableId, row) =>
|
|
2376
|
+
const addRow = (tableId, row, forceId) =>
|
|
1607
2377
|
transaction(() => {
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
tableId
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
);
|
|
2378
|
+
tableId = id(tableId);
|
|
2379
|
+
const isValidRow = validateRow(tableId, void 0, row);
|
|
2380
|
+
const rowId =
|
|
2381
|
+
isValidRow || forceId
|
|
2382
|
+
? getNewRowId(mapGet(tablesMap, tableId))
|
|
2383
|
+
: void 0;
|
|
2384
|
+
if (isValidRow) {
|
|
2385
|
+
setValidRow(tableId, getOrCreateTable(tableId), rowId, row);
|
|
1617
2386
|
}
|
|
1618
2387
|
return rowId;
|
|
1619
2388
|
});
|
|
@@ -1762,21 +2531,19 @@ const createStore = () => {
|
|
|
1762
2531
|
collForEach(changedCells, (table, tableId) =>
|
|
1763
2532
|
collForEach(table, (row, rowId) =>
|
|
1764
2533
|
collForEach(row, ([oldCell], cellId) =>
|
|
1765
|
-
|
|
1766
|
-
? delCell(tableId, rowId, cellId, true)
|
|
1767
|
-
: setCell(tableId, rowId, cellId, oldCell),
|
|
2534
|
+
setOrDelCell(store, tableId, rowId, cellId, oldCell),
|
|
1768
2535
|
),
|
|
1769
2536
|
),
|
|
1770
2537
|
);
|
|
1771
2538
|
transactions = -1;
|
|
1772
2539
|
cellsTouched = false;
|
|
1773
2540
|
}
|
|
1774
|
-
callListeners(finishTransactionListeners[0],
|
|
2541
|
+
callListeners(finishTransactionListeners[0], void 0, cellsTouched);
|
|
1775
2542
|
callInvalidCellListeners(0);
|
|
1776
2543
|
if (cellsTouched) {
|
|
1777
2544
|
callListenersForChanges(0);
|
|
1778
2545
|
}
|
|
1779
|
-
callListeners(finishTransactionListeners[1],
|
|
2546
|
+
callListeners(finishTransactionListeners[1], void 0, cellsTouched);
|
|
1780
2547
|
transactions = 0;
|
|
1781
2548
|
arrayForEach(
|
|
1782
2549
|
[
|
|
@@ -1810,16 +2577,53 @@ const createStore = () => {
|
|
|
1810
2577
|
mapForEach(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), cellCallback);
|
|
1811
2578
|
const addTablesListener = (listener, mutator) =>
|
|
1812
2579
|
addListener(listener, tablesListeners[mutator ? 1 : 0]);
|
|
1813
|
-
const addTableIdsListener = (listener, mutator) =>
|
|
1814
|
-
addListener(
|
|
2580
|
+
const addTableIdsListener = (listener, trackReorder, mutator) =>
|
|
2581
|
+
addListener(
|
|
2582
|
+
listener,
|
|
2583
|
+
tableIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
|
|
2584
|
+
);
|
|
1815
2585
|
const addTableListener = (tableId, listener, mutator) =>
|
|
1816
2586
|
addListener(listener, tableListeners[mutator ? 1 : 0], [tableId]);
|
|
1817
|
-
const addRowIdsListener = (tableId, listener, mutator) =>
|
|
1818
|
-
addListener(
|
|
2587
|
+
const addRowIdsListener = (tableId, listener, trackReorder, mutator) =>
|
|
2588
|
+
addListener(
|
|
2589
|
+
listener,
|
|
2590
|
+
rowIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
|
|
2591
|
+
[tableId],
|
|
2592
|
+
);
|
|
2593
|
+
const addSortedRowIdsListener = (
|
|
2594
|
+
tableId,
|
|
2595
|
+
cellId,
|
|
2596
|
+
descending,
|
|
2597
|
+
listener,
|
|
2598
|
+
mutator,
|
|
2599
|
+
) => {
|
|
2600
|
+
let sortedRowIds = getSortedRowIds(tableId, cellId, descending);
|
|
2601
|
+
return addListener(
|
|
2602
|
+
() => {
|
|
2603
|
+
const newSortedRowIds = getSortedRowIds(tableId, cellId, descending);
|
|
2604
|
+
if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
|
|
2605
|
+
sortedRowIds = newSortedRowIds;
|
|
2606
|
+
listener(store, tableId, cellId, descending, sortedRowIds);
|
|
2607
|
+
}
|
|
2608
|
+
},
|
|
2609
|
+
sortedRowIdsListeners[mutator ? 1 : 0],
|
|
2610
|
+
[tableId, cellId],
|
|
2611
|
+
);
|
|
2612
|
+
};
|
|
1819
2613
|
const addRowListener = (tableId, rowId, listener, mutator) =>
|
|
1820
2614
|
addListener(listener, rowListeners[mutator ? 1 : 0], [tableId, rowId]);
|
|
1821
|
-
const addCellIdsListener = (
|
|
1822
|
-
|
|
2615
|
+
const addCellIdsListener = (
|
|
2616
|
+
tableId,
|
|
2617
|
+
rowId,
|
|
2618
|
+
listener,
|
|
2619
|
+
trackReorder,
|
|
2620
|
+
mutator,
|
|
2621
|
+
) =>
|
|
2622
|
+
addListener(
|
|
2623
|
+
listener,
|
|
2624
|
+
cellIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
|
|
2625
|
+
[tableId, rowId],
|
|
2626
|
+
);
|
|
1823
2627
|
const addCellListener = (tableId, rowId, cellId, listener, mutator) =>
|
|
1824
2628
|
addListener(listener, cellListeners[mutator ? 1 : 0], [
|
|
1825
2629
|
tableId,
|
|
@@ -1838,7 +2642,7 @@ const createStore = () => {
|
|
|
1838
2642
|
addListener(listener, finishTransactionListeners[1]);
|
|
1839
2643
|
const callListener = (listenerId) => {
|
|
1840
2644
|
callListenerImpl(listenerId, [getTableIds, getRowIds, getCellIds], (ids) =>
|
|
1841
|
-
isUndefined(ids[2]) ? [] :
|
|
2645
|
+
isUndefined(ids[2]) ? [] : pairNew(getCell(...ids)),
|
|
1842
2646
|
);
|
|
1843
2647
|
return store;
|
|
1844
2648
|
};
|
|
@@ -1847,21 +2651,23 @@ const createStore = () => {
|
|
|
1847
2651
|
return store;
|
|
1848
2652
|
};
|
|
1849
2653
|
const getListenerStats = () => ({
|
|
1850
|
-
tables:
|
|
1851
|
-
tableIds:
|
|
1852
|
-
table:
|
|
1853
|
-
rowIds:
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
2654
|
+
tables: pairCollSize2(tablesListeners),
|
|
2655
|
+
tableIds: pair2CollSize2(tableIdsListeners),
|
|
2656
|
+
table: pairCollSize2(tableListeners),
|
|
2657
|
+
rowIds: pair2CollSize2(rowIdsListeners),
|
|
2658
|
+
sortedRowIds: pairCollSize2(sortedRowIdsListeners),
|
|
2659
|
+
row: pairCollSize2(rowListeners, collSize3),
|
|
2660
|
+
cellIds: pair2CollSize2(cellIdsListeners, collSize3),
|
|
2661
|
+
cell: pairCollSize2(cellListeners, collSize4),
|
|
2662
|
+
invalidCell: pairCollSize2(invalidCellListeners, collSize4),
|
|
2663
|
+
transaction: pairCollSize2(finishTransactionListeners),
|
|
1859
2664
|
});
|
|
1860
2665
|
const store = {
|
|
1861
2666
|
getTables,
|
|
1862
2667
|
getTableIds,
|
|
1863
2668
|
getTable,
|
|
1864
2669
|
getRowIds,
|
|
2670
|
+
getSortedRowIds,
|
|
1865
2671
|
getRow,
|
|
1866
2672
|
getCellIds,
|
|
1867
2673
|
getCell,
|
|
@@ -1894,6 +2700,7 @@ const createStore = () => {
|
|
|
1894
2700
|
addTableIdsListener,
|
|
1895
2701
|
addTableListener,
|
|
1896
2702
|
addRowIdsListener,
|
|
2703
|
+
addSortedRowIdsListener,
|
|
1897
2704
|
addRowListener,
|
|
1898
2705
|
addCellIdsListener,
|
|
1899
2706
|
addCellListener,
|
|
@@ -1903,6 +2710,7 @@ const createStore = () => {
|
|
|
1903
2710
|
callListener,
|
|
1904
2711
|
delListener,
|
|
1905
2712
|
getListenerStats,
|
|
2713
|
+
createStore,
|
|
1906
2714
|
};
|
|
1907
2715
|
return objFreeze(store);
|
|
1908
2716
|
};
|
|
@@ -1914,6 +2722,7 @@ export {
|
|
|
1914
2722
|
createIndexes,
|
|
1915
2723
|
createLocalPersister,
|
|
1916
2724
|
createMetrics,
|
|
2725
|
+
createQueries,
|
|
1917
2726
|
createRelationships,
|
|
1918
2727
|
createRemotePersister,
|
|
1919
2728
|
createSessionPersister,
|