tinybase 2.0.0-beta.0 → 2.0.0-beta.3

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.
Files changed (63) hide show
  1. package/lib/checkpoints.d.ts +4 -3
  2. package/lib/checkpoints.js +1 -1
  3. package/lib/checkpoints.js.gz +0 -0
  4. package/lib/common.js +1 -1
  5. package/lib/common.js.gz +0 -0
  6. package/lib/debug/checkpoints.d.ts +4 -3
  7. package/lib/debug/checkpoints.js +13 -16
  8. package/lib/debug/common.js +4 -1
  9. package/lib/debug/indexes.d.ts +4 -2
  10. package/lib/debug/indexes.js +13 -15
  11. package/lib/debug/metrics.d.ts +1 -1
  12. package/lib/debug/metrics.js +13 -16
  13. package/lib/debug/persisters.d.ts +6 -0
  14. package/lib/debug/queries.d.ts +249 -299
  15. package/lib/debug/queries.js +67 -192
  16. package/lib/debug/relationships.d.ts +6 -5
  17. package/lib/debug/relationships.js +13 -16
  18. package/lib/debug/store.d.ts +386 -86
  19. package/lib/debug/store.js +278 -216
  20. package/lib/debug/tinybase.js +318 -390
  21. package/lib/debug/ui-react.d.ts +4320 -1796
  22. package/lib/debug/ui-react.js +380 -98
  23. package/lib/indexes.d.ts +4 -2
  24. package/lib/indexes.js +1 -1
  25. package/lib/indexes.js.gz +0 -0
  26. package/lib/metrics.d.ts +1 -1
  27. package/lib/metrics.js +1 -1
  28. package/lib/metrics.js.gz +0 -0
  29. package/lib/persisters.d.ts +6 -0
  30. package/lib/queries.d.ts +249 -299
  31. package/lib/queries.js +1 -1
  32. package/lib/queries.js.gz +0 -0
  33. package/lib/relationships.d.ts +6 -5
  34. package/lib/relationships.js +1 -1
  35. package/lib/relationships.js.gz +0 -0
  36. package/lib/store.d.ts +386 -86
  37. package/lib/store.js +1 -1
  38. package/lib/store.js.gz +0 -0
  39. package/lib/tinybase.js +1 -1
  40. package/lib/tinybase.js.gz +0 -0
  41. package/lib/ui-react.d.ts +4320 -1796
  42. package/lib/ui-react.js +1 -1
  43. package/lib/ui-react.js.gz +0 -0
  44. package/lib/umd/checkpoints.js +1 -1
  45. package/lib/umd/checkpoints.js.gz +0 -0
  46. package/lib/umd/common.js +1 -1
  47. package/lib/umd/common.js.gz +0 -0
  48. package/lib/umd/indexes.js +1 -1
  49. package/lib/umd/indexes.js.gz +0 -0
  50. package/lib/umd/metrics.js +1 -1
  51. package/lib/umd/metrics.js.gz +0 -0
  52. package/lib/umd/queries.js +1 -1
  53. package/lib/umd/queries.js.gz +0 -0
  54. package/lib/umd/relationships.js +1 -1
  55. package/lib/umd/relationships.js.gz +0 -0
  56. package/lib/umd/store.js +1 -1
  57. package/lib/umd/store.js.gz +0 -0
  58. package/lib/umd/tinybase.js +1 -1
  59. package/lib/umd/tinybase.js.gz +0 -0
  60. package/lib/umd/ui-react.js +1 -1
  61. package/lib/umd/ui-react.js.gz +0 -0
  62. package/package.json +26 -26
  63. package/readme.md +2 -2
@@ -7,17 +7,29 @@ const NUMBER = getTypeOf(0);
7
7
  const FUNCTION = getTypeOf(getTypeOf);
8
8
  const TYPE = 'type';
9
9
  const DEFAULT = 'default';
10
+ const LISTENER = 'Listener';
11
+ const ADD = 'add';
12
+ const TABLES = 'Tables';
13
+ const TABLE_IDS = 'TableIds';
14
+ const TABLE = 'Table';
15
+ const ROW_IDS = 'RowIds';
16
+ const ROW = 'Row';
17
+ const CELL_IDS = 'CellIds';
18
+ const CELL = 'Cell';
10
19
 
11
20
  const arrayHas = (array, value) => array.includes(value);
12
21
  const arrayEvery = (array, cb) => array.every(cb);
13
22
  const arrayIsEqual = (array1, array2) =>
14
23
  arrayLength(array1) === arrayLength(array2) &&
15
24
  arrayEvery(array1, (value1, index) => array2[index] === value1);
25
+ const arraySort = (array, sorter) => array.sort(sorter);
16
26
  const arrayForEach = (array, cb) => array.forEach(cb);
27
+ const arrayMap = (array, cb) => array.map(cb);
17
28
  const arrayLength = (array) => array.length;
18
29
  const arrayIsEmpty = (array) => arrayLength(array) == 0;
19
30
  const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
20
31
  const arrayFilter = (array, cb) => array.filter(cb);
32
+ const arraySlice = (array, start, end) => array.slice(start, end);
21
33
  const arrayPush = (array, ...values) => array.push(...values);
22
34
  const arrayPop = (array) => array.pop();
23
35
 
@@ -65,7 +77,7 @@ const mapSet = (map, key, value) =>
65
77
  isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
66
78
  const mapEnsure = (map, key, getDefaultValue) => {
67
79
  if (!collHas(map, key)) {
68
- map.set(key, getDefaultValue());
80
+ mapSet(map, key, getDefaultValue());
69
81
  }
70
82
  return mapGet(map, key);
71
83
  };
@@ -125,32 +137,32 @@ const setNew = (entries) => new Set(entries);
125
137
  const setAdd = (set, value) => set?.add(value);
126
138
 
127
139
  const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
128
- const sets = [];
129
- const deep = (set, p) =>
140
+ const leaves = [];
141
+ const deep = (node, p) =>
130
142
  p == arrayLength(path)
131
- ? arrayPush(sets, set)
132
- : arrayForEach([path[p], null], (id) => deep(mapGet(set, id), p + 1));
143
+ ? arrayPush(leaves, node)
144
+ : path[p] === null
145
+ ? collForEach(node, (node2) => deep(node2, p + 1))
146
+ : arrayForEach([path[p], null], (id) => deep(mapGet(node, id), p + 1));
133
147
  deep(deepIdSet, 0);
134
- return sets;
148
+ return leaves;
135
149
  };
136
150
  const getListenerFunctions = (getThing) => {
137
151
  let thing;
138
152
  let nextId = 0;
139
153
  const listenerPool = [];
140
154
  const allListeners = mapNew();
141
- const addListener = (listener, idSetNode, idOrNulls) => {
155
+ const addListener = (listener, idSetNode, path) => {
142
156
  thing ??= getThing();
143
157
  const id = arrayPop(listenerPool) ?? EMPTY_STRING + nextId++;
144
- mapSet(allListeners, id, [listener, idSetNode, idOrNulls]);
145
- setAdd(visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], setNew), id);
158
+ mapSet(allListeners, id, [listener, idSetNode, path]);
159
+ setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
146
160
  return id;
147
161
  };
148
162
  const callListeners = (idSetNode, ids, ...extraArgs) =>
149
163
  arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
150
164
  collForEach(set, (id) =>
151
- ifNotUndefined(mapGet(allListeners, id), ([listener]) =>
152
- listener(thing, ...(ids ?? []), ...extraArgs),
153
- ),
165
+ mapGet(allListeners, id)[0](thing, ...(ids ?? []), ...extraArgs),
154
166
  ),
155
167
  );
156
168
  const delListener = (id) =>
@@ -165,8 +177,6 @@ const getListenerFunctions = (getThing) => {
165
177
  }
166
178
  return idOrNulls;
167
179
  });
168
- const hasListeners = (idSetNode, ids) =>
169
- !arrayEvery(getWildcardedLeaves(idSetNode, ids), isUndefined);
170
180
  const callListener = (id, idNullGetters, extraArgsGetter) =>
171
181
  ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls = []]) => {
172
182
  const callWithIds = (...ids) => {
@@ -181,16 +191,12 @@ const getListenerFunctions = (getThing) => {
181
191
  };
182
192
  callWithIds();
183
193
  });
184
- return [addListener, callListeners, delListener, hasListeners, callListener];
194
+ return [addListener, callListeners, delListener, callListener];
185
195
  };
186
196
 
187
197
  const pairNew = (value) => [value, value];
188
198
  const pairCollSize2 = (pair, func = collSize2) => func(pair[0]) + func(pair[1]);
189
- const pairCollIsEmpty = (pair) => pairCollSize2(pair) == 0;
190
199
  const pairNewMap = () => [mapNew(), mapNew()];
191
- const pair2CollSize2 = (pair2, func = collSize2) =>
192
- pairCollSize2(pair2[0], func) + pairCollSize2(pair2[1], func);
193
- const pair2NewMap = () => [pairNewMap(), pairNewMap()];
194
200
 
195
201
  const getCellType = (cell) => {
196
202
  const type = getTypeOf(cell);
@@ -198,16 +204,23 @@ const getCellType = (cell) => {
198
204
  ? type
199
205
  : void 0;
200
206
  };
207
+ const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
208
+ isUndefined(cell)
209
+ ? store.delCell(tableId, rowId, cellId, true)
210
+ : store.setCell(tableId, rowId, cellId, cell);
211
+
212
+ const defaultSorter = (sortKey1, sortKey2) => (sortKey1 < sortKey2 ? -1 : 1);
213
+ const id = (key) => EMPTY_STRING + key;
201
214
 
202
215
  const transformMap = (map, toBeLikeObject, setId, delId = mapSet) => {
203
216
  const idsToDelete = arrayFilter(
204
217
  mapKeys(map),
205
- (id) => !objHas(toBeLikeObject, id),
218
+ (id2) => !objHas(toBeLikeObject, id2),
206
219
  );
207
- arrayForEach(objIds(toBeLikeObject), (id) =>
208
- setId(map, id, toBeLikeObject[id]),
220
+ arrayForEach(objIds(toBeLikeObject), (id2) =>
221
+ setId(map, id2, toBeLikeObject[id2]),
209
222
  );
210
- arrayForEach(idsToDelete, (id) => delId(map, id));
223
+ arrayForEach(idsToDelete, (id2) => delId(map, id2));
211
224
  return map;
212
225
  };
213
226
  const validate = (obj, validateChild, onInvalidObj) => {
@@ -215,15 +228,15 @@ const validate = (obj, validateChild, onInvalidObj) => {
215
228
  onInvalidObj?.();
216
229
  return false;
217
230
  }
218
- objForEach(obj, (child, id) => {
219
- if (!validateChild(child, id)) {
220
- objDel(obj, id);
231
+ objForEach(obj, (child, id2) => {
232
+ if (!validateChild(child, id2)) {
233
+ objDel(obj, id2);
221
234
  }
222
235
  });
223
236
  return !objIsEmpty(obj);
224
237
  };
225
- const idsChanged = (changedIds, id, added) =>
226
- mapSet(changedIds, id, mapGet(changedIds, id) == -added ? void 0 : added);
238
+ const idsChanged = (changedIds, id2, added) =>
239
+ mapSet(changedIds, id2, mapGet(changedIds, id2) == -added ? void 0 : added);
227
240
  const createStore = () => {
228
241
  let hasSchema;
229
242
  let cellsTouched;
@@ -238,26 +251,22 @@ const createStore = () => {
238
251
  const schemaRowCache = mapNew();
239
252
  const tablesMap = mapNew();
240
253
  const tablesListeners = pairNewMap();
241
- const tableIdsListeners = pair2NewMap();
254
+ const tableIdsListeners = pairNewMap();
242
255
  const tableListeners = pairNewMap();
243
- const rowIdsListeners = pair2NewMap();
256
+ const rowIdsListeners = pairNewMap();
257
+ const sortedRowIdsListeners = pairNewMap();
244
258
  const rowListeners = pairNewMap();
245
- const cellIdsListeners = pair2NewMap();
259
+ const cellIdsListeners = pairNewMap();
246
260
  const cellListeners = pairNewMap();
247
261
  const invalidCellListeners = pairNewMap();
248
262
  const finishTransactionListeners = pairNewMap();
249
- const [
250
- addListener,
251
- callListeners,
252
- delListenerImpl,
253
- hasListeners,
254
- callListenerImpl,
255
- ] = getListenerFunctions(() => store);
263
+ const [addListener, callListeners, delListenerImpl, callListenerImpl] =
264
+ getListenerFunctions(() => store);
256
265
  const validateSchema = (schema) =>
257
266
  validate(schema, (tableSchema) =>
258
267
  validate(tableSchema, (cellSchema) => {
259
268
  if (
260
- !validate(cellSchema, (_child, id) => arrayHas([TYPE, DEFAULT], id))
269
+ !validate(cellSchema, (_child, id2) => arrayHas([TYPE, DEFAULT], id2))
261
270
  ) {
262
271
  return false;
263
272
  }
@@ -434,49 +443,12 @@ const createStore = () => {
434
443
  }
435
444
  };
436
445
  const tableIdsChanged = (tableId, added) =>
437
- idsChanged(
438
- collIsEmpty(changedTableIds)
439
- ? mapSet(
440
- changedTableIds,
441
- null,
442
- hasListeners(tableIdsListeners[0][1]) ||
443
- hasListeners(tableIdsListeners[1][1])
444
- ? getTableIds()
445
- : 0,
446
- )
447
- : changedTableIds,
448
- tableId,
449
- added,
450
- );
446
+ idsChanged(changedTableIds, tableId, added);
451
447
  const rowIdsChanged = (tableId, rowId, added) =>
452
- idsChanged(
453
- mapEnsure(changedRowIds, tableId, () =>
454
- mapNew([
455
- [
456
- null,
457
- hasListeners(rowIdsListeners[0][1], [tableId]) ||
458
- hasListeners(rowIdsListeners[1][1], [tableId])
459
- ? getRowIds(tableId)
460
- : 0,
461
- ],
462
- ]),
463
- ),
464
- rowId,
465
- added,
466
- );
448
+ idsChanged(mapEnsure(changedRowIds, tableId, mapNew), rowId, added);
467
449
  const cellIdsChanged = (tableId, rowId, cellId, added) =>
468
450
  idsChanged(
469
- mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, () =>
470
- mapNew([
471
- [
472
- null,
473
- hasListeners(cellIdsListeners[0][1], [tableId, rowId]) ||
474
- hasListeners(cellIdsListeners[1][1], [tableId, rowId])
475
- ? getCellIds(tableId, rowId)
476
- : 0,
477
- ],
478
- ]),
479
- ),
451
+ mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, mapNew),
480
452
  cellId,
481
453
  added,
482
454
  );
@@ -519,23 +491,21 @@ const createStore = () => {
519
491
  ),
520
492
  )
521
493
  : 0;
522
- const callIdsListenersIfChanged = (listeners, changedIds, getIds, ids) => {
523
- if (collSize(changedIds) > 1) {
524
- callListeners(listeners[0], ids);
525
- callListeners(listeners[1], ids);
526
- } else if (
527
- !collIsEmpty(changedIds) &&
528
- mapGet(changedIds, null) != 0 &&
529
- !arrayIsEqual(mapGet(changedIds, null), getIds(...(ids ?? [])))
530
- ) {
531
- callListeners(listeners[1], ids);
494
+ const callIdsListenersIfChanged = (listeners, changedIds, ids) => {
495
+ if (!collIsEmpty(changedIds)) {
496
+ callListeners(listeners, ids);
497
+ return 1;
532
498
  }
533
499
  };
534
500
  const callListenersForChanges = (mutator) => {
501
+ const emptySortedRowIdListeners = collIsEmpty(
502
+ sortedRowIdsListeners[mutator],
503
+ );
535
504
  const emptyIdListeners =
536
- pairCollIsEmpty(cellIdsListeners[mutator]) &&
537
- pairCollIsEmpty(rowIdsListeners[mutator]) &&
538
- pairCollIsEmpty(tableIdsListeners[mutator]);
505
+ collIsEmpty(cellIdsListeners[mutator]) &&
506
+ collIsEmpty(rowIdsListeners[mutator]) &&
507
+ emptySortedRowIdListeners &&
508
+ collIsEmpty(tableIdsListeners[mutator]);
539
509
  const emptyOtherListeners =
540
510
  collIsEmpty(cellListeners[mutator]) &&
541
511
  collIsEmpty(rowListeners[mutator]) &&
@@ -553,27 +523,45 @@ const createStore = () => {
553
523
  if (!emptyIdListeners) {
554
524
  collForEach(changes[2], (rowCellIds, tableId) =>
555
525
  collForEach(rowCellIds, (changedIds, rowId) =>
556
- callIdsListenersIfChanged(
557
- cellIdsListeners[mutator],
558
- changedIds,
559
- getCellIds,
560
- [tableId, rowId],
561
- ),
562
- ),
563
- );
564
- collForEach(changes[1], (changedIds, tableId) =>
565
- callIdsListenersIfChanged(
566
- rowIdsListeners[mutator],
567
- changedIds,
568
- getRowIds,
569
- [tableId],
526
+ callIdsListenersIfChanged(cellIdsListeners[mutator], changedIds, [
527
+ tableId,
528
+ rowId,
529
+ ]),
570
530
  ),
571
531
  );
572
- callIdsListenersIfChanged(
573
- tableIdsListeners[mutator],
574
- changes[0],
575
- getTableIds,
576
- );
532
+ const calledSortableTableIds = setNew();
533
+ collForEach(changes[1], (changedIds, tableId) => {
534
+ if (
535
+ callIdsListenersIfChanged(rowIdsListeners[mutator], changedIds, [
536
+ tableId,
537
+ ]) &&
538
+ !emptySortedRowIdListeners
539
+ ) {
540
+ callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
541
+ setAdd(calledSortableTableIds, tableId);
542
+ }
543
+ });
544
+ if (!emptySortedRowIdListeners) {
545
+ collForEach(changes[3], (rows, tableId) => {
546
+ if (!collHas(calledSortableTableIds, tableId)) {
547
+ const sortableCellIds = setNew();
548
+ collForEach(rows, (cells) =>
549
+ collForEach(cells, ([oldCell, newCell], cellId) =>
550
+ newCell !== oldCell
551
+ ? setAdd(sortableCellIds, cellId)
552
+ : collDel(cells, cellId),
553
+ ),
554
+ );
555
+ collForEach(sortableCellIds, (cellId) =>
556
+ callListeners(sortedRowIdsListeners[mutator], [
557
+ tableId,
558
+ cellId,
559
+ ]),
560
+ );
561
+ }
562
+ });
563
+ }
564
+ callIdsListenersIfChanged(tableIdsListeners[mutator], changes[0]);
577
565
  }
578
566
  if (!emptyOtherListeners) {
579
567
  let tablesChanged;
@@ -611,26 +599,49 @@ const createStore = () => {
611
599
  }
612
600
  }
613
601
  };
614
- const fluentTransaction = (actions) => {
615
- transaction(actions);
602
+ const fluentTransaction = (actions, ...args) => {
603
+ transaction(() => actions(...arrayMap(args, id)));
616
604
  return store;
617
605
  };
618
606
  const getTables = () =>
619
607
  mapToObj(tablesMap, (table) => mapToObj(table, mapToObj));
620
608
  const getTableIds = () => mapKeys(tablesMap);
621
- const getTable = (tableId) => mapToObj(mapGet(tablesMap, tableId), mapToObj);
622
- const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, tableId));
609
+ const getTable = (tableId) =>
610
+ mapToObj(mapGet(tablesMap, id(tableId)), mapToObj);
611
+ const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
612
+ const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) => {
613
+ const cells = [];
614
+ mapForEach(mapGet(tablesMap, id(tableId)), (rowId, row) =>
615
+ arrayPush(cells, [
616
+ isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
617
+ rowId,
618
+ ]),
619
+ );
620
+ return arrayMap(
621
+ arraySlice(
622
+ arraySort(
623
+ cells,
624
+ ([cell1], [cell2]) =>
625
+ defaultSorter(cell1, cell2) * (descending ? -1 : 1),
626
+ ),
627
+ offset,
628
+ isUndefined(limit) ? limit : offset + limit,
629
+ ),
630
+ ([, rowId]) => rowId,
631
+ );
632
+ };
623
633
  const getRow = (tableId, rowId) =>
624
- mapToObj(mapGet(mapGet(tablesMap, tableId), rowId));
634
+ mapToObj(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
625
635
  const getCellIds = (tableId, rowId) =>
626
- mapKeys(mapGet(mapGet(tablesMap, tableId), rowId));
636
+ mapKeys(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
627
637
  const getCell = (tableId, rowId, cellId) =>
628
- mapGet(mapGet(mapGet(tablesMap, tableId), rowId), cellId);
638
+ mapGet(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
629
639
  const hasTables = () => !collIsEmpty(tablesMap);
630
- const hasTable = (tableId) => collHas(tablesMap, tableId);
631
- const hasRow = (tableId, rowId) => collHas(mapGet(tablesMap, tableId), rowId);
640
+ const hasTable = (tableId) => collHas(tablesMap, id(tableId));
641
+ const hasRow = (tableId, rowId) =>
642
+ collHas(mapGet(tablesMap, id(tableId)), id(rowId));
632
643
  const hasCell = (tableId, rowId, cellId) =>
633
- collHas(mapGet(mapGet(tablesMap, tableId), rowId), cellId);
644
+ collHas(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
634
645
  const getJson = () => jsonString(tablesMap);
635
646
  const getSchemaJson = () => jsonString(schemaMap);
636
647
  const setTables = (tables) =>
@@ -638,17 +649,28 @@ const createStore = () => {
638
649
  validateTables(tables) ? setValidTables(tables) : 0,
639
650
  );
640
651
  const setTable = (tableId, table) =>
641
- fluentTransaction(() =>
642
- validateTable(table, tableId) ? setValidTable(tableId, table) : 0,
652
+ fluentTransaction(
653
+ (tableId2) =>
654
+ validateTable(table, tableId2) ? setValidTable(tableId2, table) : 0,
655
+ tableId,
643
656
  );
644
657
  const setRow = (tableId, rowId, row) =>
645
- fluentTransaction(() =>
646
- validateRow(tableId, rowId, row)
647
- ? setValidRow(tableId, getOrCreateTable(tableId), rowId, row)
648
- : 0,
658
+ fluentTransaction(
659
+ (tableId2, rowId2) =>
660
+ validateRow(id(tableId2), id(rowId2), row)
661
+ ? setValidRow(
662
+ id(tableId2),
663
+ getOrCreateTable(id(tableId2)),
664
+ id(rowId2),
665
+ row,
666
+ )
667
+ : 0,
668
+ tableId,
669
+ rowId,
649
670
  );
650
671
  const addRow = (tableId, row, forceId) =>
651
672
  transaction(() => {
673
+ tableId = id(tableId);
652
674
  const isValidRow = validateRow(tableId, void 0, row);
653
675
  const rowId =
654
676
  isValidRow || forceId
@@ -660,32 +682,40 @@ const createStore = () => {
660
682
  return rowId;
661
683
  });
662
684
  const setPartialRow = (tableId, rowId, partialRow) =>
663
- fluentTransaction(() => {
664
- if (validateRow(tableId, rowId, partialRow, 1)) {
665
- const table = getOrCreateTable(tableId);
666
- objForEach(partialRow, (cell, cellId) =>
667
- setCellIntoDefaultRow(tableId, table, rowId, cellId, cell),
668
- );
669
- }
670
- });
685
+ fluentTransaction(
686
+ (tableId2, rowId2) => {
687
+ if (validateRow(tableId2, rowId2, partialRow, 1)) {
688
+ const table = getOrCreateTable(tableId2);
689
+ objForEach(partialRow, (cell, cellId) =>
690
+ setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
691
+ );
692
+ }
693
+ },
694
+ tableId,
695
+ rowId,
696
+ );
671
697
  const setCell = (tableId, rowId, cellId, cell) =>
672
- fluentTransaction(() =>
673
- ifNotUndefined(
674
- getValidatedCell(
675
- tableId,
676
- rowId,
677
- cellId,
678
- isFunction(cell) ? cell(getCell(tableId, rowId, cellId)) : cell,
679
- ),
680
- (validCell) =>
681
- setCellIntoDefaultRow(
682
- tableId,
683
- getOrCreateTable(tableId),
684
- rowId,
685
- cellId,
686
- validCell,
698
+ fluentTransaction(
699
+ (tableId2, rowId2, cellId2) =>
700
+ ifNotUndefined(
701
+ getValidatedCell(
702
+ tableId2,
703
+ rowId2,
704
+ cellId2,
705
+ isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
687
706
  ),
688
- ),
707
+ (validCell) =>
708
+ setCellIntoDefaultRow(
709
+ tableId2,
710
+ getOrCreateTable(tableId2),
711
+ rowId2,
712
+ cellId2,
713
+ validCell,
714
+ ),
715
+ ),
716
+ tableId,
717
+ rowId,
718
+ cellId,
689
719
  );
690
720
  const setJson = (json) => {
691
721
  try {
@@ -706,24 +736,42 @@ const createStore = () => {
706
736
  });
707
737
  const delTables = () => fluentTransaction(() => setValidTables({}));
708
738
  const delTable = (tableId) =>
709
- fluentTransaction(() =>
710
- collHas(tablesMap, tableId) ? delValidTable(tableId) : 0,
739
+ fluentTransaction(
740
+ (tableId2) =>
741
+ collHas(tablesMap, tableId2) ? delValidTable(tableId2) : 0,
742
+ tableId,
711
743
  );
712
744
  const delRow = (tableId, rowId) =>
713
- fluentTransaction(() =>
714
- ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) =>
715
- collHas(tableMap, rowId) ? delValidRow(tableId, tableMap, rowId) : 0,
716
- ),
745
+ fluentTransaction(
746
+ (tableId2, rowId2) =>
747
+ ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
748
+ collHas(tableMap, rowId2)
749
+ ? delValidRow(tableId2, tableMap, rowId2)
750
+ : 0,
751
+ ),
752
+ tableId,
753
+ rowId,
717
754
  );
718
755
  const delCell = (tableId, rowId, cellId, forceDel) =>
719
- fluentTransaction(() =>
720
- ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) =>
721
- ifNotUndefined(mapGet(tableMap, rowId), (rowMap) =>
722
- collHas(rowMap, cellId)
723
- ? delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel)
724
- : 0,
756
+ fluentTransaction(
757
+ (tableId2, rowId2, cellId2) =>
758
+ ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
759
+ ifNotUndefined(mapGet(tableMap, rowId2), (rowMap) =>
760
+ collHas(rowMap, cellId2)
761
+ ? delValidCell(
762
+ tableId2,
763
+ tableMap,
764
+ rowId2,
765
+ rowMap,
766
+ cellId2,
767
+ forceDel,
768
+ )
769
+ : 0,
770
+ ),
725
771
  ),
726
- ),
772
+ tableId,
773
+ rowId,
774
+ cellId,
727
775
  );
728
776
  const delSchema = () =>
729
777
  fluentTransaction(() => {
@@ -778,9 +826,7 @@ const createStore = () => {
778
826
  collForEach(changedCells, (table, tableId) =>
779
827
  collForEach(table, (row, rowId) =>
780
828
  collForEach(row, ([oldCell], cellId) =>
781
- isUndefined(oldCell)
782
- ? delCell(tableId, rowId, cellId, true)
783
- : setCell(tableId, rowId, cellId, oldCell),
829
+ setOrDelCell(store, tableId, rowId, cellId, oldCell),
784
830
  ),
785
831
  ),
786
832
  );
@@ -819,52 +865,53 @@ const createStore = () => {
819
865
  ),
820
866
  );
821
867
  const forEachRow = (tableId, rowCallback) =>
822
- collForEach(mapGet(tablesMap, tableId), (rowMap, rowId) =>
868
+ collForEach(mapGet(tablesMap, id(tableId)), (rowMap, rowId) =>
823
869
  rowCallback(rowId, (cellCallback) => mapForEach(rowMap, cellCallback)),
824
870
  );
825
871
  const forEachCell = (tableId, rowId, cellCallback) =>
826
- mapForEach(mapGet(mapGet(tablesMap, tableId), rowId), cellCallback);
827
- const addTablesListener = (listener, mutator) =>
828
- addListener(listener, tablesListeners[mutator ? 1 : 0]);
829
- const addTableIdsListener = (listener, trackReorder, mutator) =>
830
- addListener(
831
- listener,
832
- tableIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
833
- );
834
- const addTableListener = (tableId, listener, mutator) =>
835
- addListener(listener, tableListeners[mutator ? 1 : 0], [tableId]);
836
- const addRowIdsListener = (tableId, listener, trackReorder, mutator) =>
837
- addListener(
838
- listener,
839
- rowIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
840
- [tableId],
841
- );
842
- const addRowListener = (tableId, rowId, listener, mutator) =>
843
- addListener(listener, rowListeners[mutator ? 1 : 0], [tableId, rowId]);
844
- const addCellIdsListener = (
872
+ mapForEach(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), cellCallback);
873
+ const addSortedRowIdsListener = (
845
874
  tableId,
846
- rowId,
875
+ cellId,
876
+ descending,
877
+ offset,
878
+ limit,
847
879
  listener,
848
- trackReorder,
849
880
  mutator,
850
- ) =>
851
- addListener(
852
- listener,
853
- cellIdsListeners[mutator ? 1 : 0][trackReorder ? 1 : 0],
854
- [tableId, rowId],
855
- );
856
- const addCellListener = (tableId, rowId, cellId, listener, mutator) =>
857
- addListener(listener, cellListeners[mutator ? 1 : 0], [
881
+ ) => {
882
+ let sortedRowIds = getSortedRowIds(
858
883
  tableId,
859
- rowId,
860
- cellId,
861
- ]);
862
- const addInvalidCellListener = (tableId, rowId, cellId, listener, mutator) =>
863
- addListener(listener, invalidCellListeners[mutator ? 1 : 0], [
864
- tableId,
865
- rowId,
866
884
  cellId,
867
- ]);
885
+ descending,
886
+ offset,
887
+ limit,
888
+ );
889
+ return addListener(
890
+ () => {
891
+ const newSortedRowIds = getSortedRowIds(
892
+ tableId,
893
+ cellId,
894
+ descending,
895
+ offset,
896
+ limit,
897
+ );
898
+ if (!arrayIsEqual(newSortedRowIds, sortedRowIds)) {
899
+ sortedRowIds = newSortedRowIds;
900
+ listener(
901
+ store,
902
+ tableId,
903
+ cellId,
904
+ descending,
905
+ offset,
906
+ limit,
907
+ sortedRowIds,
908
+ );
909
+ }
910
+ },
911
+ sortedRowIdsListeners[mutator ? 1 : 0],
912
+ [tableId, cellId],
913
+ );
914
+ };
868
915
  const addWillFinishTransactionListener = (listener) =>
869
916
  addListener(listener, finishTransactionListeners[0]);
870
917
  const addDidFinishTransactionListener = (listener) =>
@@ -881,11 +928,12 @@ const createStore = () => {
881
928
  };
882
929
  const getListenerStats = () => ({
883
930
  tables: pairCollSize2(tablesListeners),
884
- tableIds: pair2CollSize2(tableIdsListeners),
931
+ tableIds: pairCollSize2(tableIdsListeners),
885
932
  table: pairCollSize2(tableListeners),
886
- rowIds: pair2CollSize2(rowIdsListeners),
933
+ rowIds: pairCollSize2(rowIdsListeners),
934
+ sortedRowIds: pairCollSize2(sortedRowIdsListeners),
887
935
  row: pairCollSize2(rowListeners, collSize3),
888
- cellIds: pair2CollSize2(cellIdsListeners, collSize3),
936
+ cellIds: pairCollSize2(cellIdsListeners, collSize3),
889
937
  cell: pairCollSize2(cellListeners, collSize4),
890
938
  invalidCell: pairCollSize2(invalidCellListeners, collSize4),
891
939
  transaction: pairCollSize2(finishTransactionListeners),
@@ -895,6 +943,7 @@ const createStore = () => {
895
943
  getTableIds,
896
944
  getTable,
897
945
  getRowIds,
946
+ getSortedRowIds,
898
947
  getRow,
899
948
  getCellIds,
900
949
  getCell,
@@ -923,14 +972,7 @@ const createStore = () => {
923
972
  forEachTable,
924
973
  forEachRow,
925
974
  forEachCell,
926
- addTablesListener,
927
- addTableIdsListener,
928
- addTableListener,
929
- addRowIdsListener,
930
- addRowListener,
931
- addCellIdsListener,
932
- addCellListener,
933
- addInvalidCellListener,
975
+ addSortedRowIdsListener,
934
976
  addWillFinishTransactionListener,
935
977
  addDidFinishTransactionListener,
936
978
  callListener,
@@ -938,6 +980,26 @@ const createStore = () => {
938
980
  getListenerStats,
939
981
  createStore,
940
982
  };
983
+ objForEach(
984
+ {
985
+ [TABLES]: [0, tablesListeners],
986
+ [TABLE_IDS]: [0, tableIdsListeners],
987
+ [TABLE]: [1, tableListeners],
988
+ [ROW_IDS]: [1, rowIdsListeners],
989
+ [ROW]: [2, rowListeners],
990
+ [CELL_IDS]: [2, cellIdsListeners],
991
+ [CELL]: [3, cellListeners],
992
+ InvalidCell: [3, invalidCellListeners],
993
+ },
994
+ ([argumentCount, idSetNode], listenable) => {
995
+ store[ADD + listenable + LISTENER] = (...args) =>
996
+ addListener(
997
+ args[argumentCount],
998
+ idSetNode[args[argumentCount + 1] ? 1 : 0],
999
+ argumentCount > 0 ? arraySlice(args, 0, argumentCount) : void 0,
1000
+ );
1001
+ },
1002
+ );
941
1003
  return objFreeze(store);
942
1004
  };
943
1005