tinybase 1.2.1 → 1.3.0-beta.0

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.
@@ -63,10 +63,9 @@ const mapForEach = (map, cb) =>
63
63
  collForEach(map, (value, key) => cb(key, value));
64
64
  const mapSet = (map, key, value) =>
65
65
  isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
66
- const mapEnsure = (map, key, defaultValue, onWillAdd) => {
66
+ const mapEnsure = (map, key, getDefaultValue) => {
67
67
  if (!collHas(map, key)) {
68
- onWillAdd?.(defaultValue);
69
- map.set(key, defaultValue);
68
+ map.set(key, getDefaultValue());
70
69
  }
71
70
  return mapGet(map, key);
72
71
  };
@@ -107,11 +106,11 @@ const setAdd = (set, value) => set?.add(value);
107
106
  const addDeepSet = (deepSet, value, ids) =>
108
107
  arrayLength(ids) < 2
109
108
  ? setAdd(
110
- arrayIsEmpty(ids) ? deepSet : mapEnsure(deepSet, ids[0], setNew()),
109
+ arrayIsEmpty(ids) ? deepSet : mapEnsure(deepSet, ids[0], setNew),
111
110
  value,
112
111
  )
113
112
  : addDeepSet(
114
- mapEnsure(deepSet, ids[0], mapNew()),
113
+ mapEnsure(deepSet, ids[0], mapNew),
115
114
  value,
116
115
  arrayFromSecond(ids),
117
116
  );
@@ -210,6 +209,7 @@ const idsChanged = (ids, id, added) =>
210
209
  mapSet(ids, id, mapGet(ids, id) == -added ? void 0 : added);
211
210
  const createStore = () => {
212
211
  let hasSchema;
212
+ let cellsTouched;
213
213
  let nextRowId = 0;
214
214
  let transactions = 0;
215
215
  const changedTableIds = mapNew();
@@ -228,6 +228,7 @@ const createStore = () => {
228
228
  const cellIdsListeners = mapNewPair();
229
229
  const cellListeners = mapNewPair();
230
230
  const invalidCellListeners = mapNewPair();
231
+ const finishTransactionListeners = mapNewPair(setNew);
231
232
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
232
233
  getListenerFunctions(() => store);
233
234
  const validateSchema = (schema) =>
@@ -310,7 +311,7 @@ const createStore = () => {
310
311
  const rowDefaulted = mapNew();
311
312
  const rowNonDefaulted = setNew();
312
313
  transformMap(
313
- mapEnsure(schemaMap, tableId, mapNew()),
314
+ mapEnsure(schemaMap, tableId, mapNew),
314
315
  tableSchema,
315
316
  (tableSchemaMap, cellId, cellSchema) => {
316
317
  mapSet(tableSchemaMap, cellId, cellSchema);
@@ -337,18 +338,20 @@ const createStore = () => {
337
338
  );
338
339
  const setValidTable = (tableId, table) =>
339
340
  transformMap(
340
- mapEnsure(tablesMap, tableId, mapNew(), () =>
341
- tableIdsChanged(tableId, 1),
342
- ),
341
+ mapEnsure(tablesMap, tableId, () => {
342
+ tableIdsChanged(tableId, 1);
343
+ return mapNew();
344
+ }),
343
345
  table,
344
346
  (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
345
347
  (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
346
348
  );
347
349
  const setValidRow = (tableId, tableMap, rowId, newRow, forceDel) =>
348
350
  transformMap(
349
- mapEnsure(tableMap, rowId, mapNew(), () =>
350
- rowIdsChanged(tableId, rowId, 1),
351
- ),
351
+ mapEnsure(tableMap, rowId, () => {
352
+ rowIdsChanged(tableId, rowId, 1);
353
+ return mapNew();
354
+ }),
352
355
  newRow,
353
356
  (rowMap, cellId, cell) =>
354
357
  setValidCell(tableId, rowId, rowMap, cellId, cell),
@@ -411,25 +414,25 @@ const createStore = () => {
411
414
  const tableIdsChanged = (tableId, added) =>
412
415
  idsChanged(changedTableIds, tableId, added);
413
416
  const rowIdsChanged = (tableId, rowId, added) =>
414
- idsChanged(mapEnsure(changedRowIds, tableId, mapNew()), rowId, added);
417
+ idsChanged(mapEnsure(changedRowIds, tableId, mapNew), rowId, added);
415
418
  const cellIdsChanged = (tableId, rowId, cellId, added) =>
416
419
  idsChanged(
417
- mapEnsure(mapEnsure(changedCellIds, tableId, mapNew()), rowId, mapNew()),
420
+ mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, mapNew),
418
421
  cellId,
419
422
  added,
420
423
  );
421
424
  const cellChanged = (tableId, rowId, cellId, oldCell, newCell) =>
422
425
  (mapEnsure(
423
- mapEnsure(mapEnsure(changedCells, tableId, mapNew()), rowId, mapNew()),
426
+ mapEnsure(mapEnsure(changedCells, tableId, mapNew), rowId, mapNew),
424
427
  cellId,
425
- [oldCell],
428
+ () => [oldCell, 0],
426
429
  )[1] = newCell);
427
430
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
428
431
  arrayPush(
429
432
  mapEnsure(
430
- mapEnsure(mapEnsure(invalidCells, tableId, mapNew()), rowId, mapNew()),
433
+ mapEnsure(mapEnsure(invalidCells, tableId, mapNew), rowId, mapNew),
431
434
  cellId,
432
- [],
435
+ () => [],
433
436
  ),
434
437
  invalidCell,
435
438
  );
@@ -458,75 +461,73 @@ const createStore = () => {
458
461
  )
459
462
  : 0;
460
463
  const callListenersForChanges = (mutator) => {
461
- if (!collIsEmpty(changedCells)) {
462
- const emptyIdListeners =
463
- collIsEmpty(cellIdsListeners[mutator]) &&
464
- collIsEmpty(rowIdsListeners[mutator]) &&
465
- collIsEmpty(tableIdsListeners[mutator]);
466
- const emptyOtherListeners =
467
- collIsEmpty(cellListeners[mutator]) &&
468
- collIsEmpty(rowListeners[mutator]) &&
469
- collIsEmpty(tableListeners[mutator]) &&
470
- collIsEmpty(tablesListeners[mutator]);
471
- if (!(emptyIdListeners && emptyOtherListeners)) {
472
- const changes = mutator
473
- ? [
474
- mapClone(changedTableIds),
475
- mapClone2(changedRowIds),
476
- mapClone(changedCellIds, mapClone2),
477
- mapClone(changedCells, mapClone2),
478
- ]
479
- : [changedTableIds, changedRowIds, changedCellIds, changedCells];
480
- if (!emptyIdListeners) {
481
- collForEach(changes[2], (rowCellIds, tableId) =>
482
- collForEach(rowCellIds, (changedIds, rowId) => {
483
- if (!collIsEmpty(changedIds)) {
484
- callListeners(cellIdsListeners[mutator], [tableId, rowId]);
485
- }
486
- }),
487
- );
488
- collForEach(changes[1], (changedIds, tableId) => {
464
+ const emptyIdListeners =
465
+ collIsEmpty(cellIdsListeners[mutator]) &&
466
+ collIsEmpty(rowIdsListeners[mutator]) &&
467
+ collIsEmpty(tableIdsListeners[mutator]);
468
+ const emptyOtherListeners =
469
+ collIsEmpty(cellListeners[mutator]) &&
470
+ collIsEmpty(rowListeners[mutator]) &&
471
+ collIsEmpty(tableListeners[mutator]) &&
472
+ collIsEmpty(tablesListeners[mutator]);
473
+ if (!(emptyIdListeners && emptyOtherListeners)) {
474
+ const changes = mutator
475
+ ? [
476
+ mapClone(changedTableIds),
477
+ mapClone2(changedRowIds),
478
+ mapClone(changedCellIds, mapClone2),
479
+ mapClone(changedCells, mapClone2),
480
+ ]
481
+ : [changedTableIds, changedRowIds, changedCellIds, changedCells];
482
+ if (!emptyIdListeners) {
483
+ collForEach(changes[2], (rowCellIds, tableId) =>
484
+ collForEach(rowCellIds, (changedIds, rowId) => {
489
485
  if (!collIsEmpty(changedIds)) {
490
- callListeners(rowIdsListeners[mutator], [tableId]);
486
+ callListeners(cellIdsListeners[mutator], [tableId, rowId]);
491
487
  }
492
- });
493
- if (!collIsEmpty(changes[0])) {
494
- callListeners(tableIdsListeners[mutator]);
488
+ }),
489
+ );
490
+ collForEach(changes[1], (changedIds, tableId) => {
491
+ if (!collIsEmpty(changedIds)) {
492
+ callListeners(rowIdsListeners[mutator], [tableId]);
495
493
  }
494
+ });
495
+ if (!collIsEmpty(changes[0])) {
496
+ callListeners(tableIdsListeners[mutator]);
496
497
  }
497
- if (!emptyOtherListeners) {
498
- let tablesChanged;
499
- collForEach(changes[3], (rows, tableId) => {
500
- let tableChanged;
501
- collForEach(rows, (cells, rowId) => {
502
- let rowChanged;
503
- collForEach(cells, ([oldCell, newCell], cellId) => {
504
- if (newCell !== oldCell) {
505
- callListeners(
506
- cellListeners[mutator],
507
- [tableId, rowId, cellId],
508
- newCell,
509
- oldCell,
510
- getCellChange,
511
- );
512
- tablesChanged = tableChanged = rowChanged = 1;
513
- }
514
- });
515
- if (rowChanged) {
498
+ }
499
+ if (!emptyOtherListeners) {
500
+ let tablesChanged;
501
+ collForEach(changes[3], (rows, tableId) => {
502
+ let tableChanged;
503
+ collForEach(rows, (cells, rowId) => {
504
+ let rowChanged;
505
+ collForEach(cells, ([oldCell, newCell], cellId) => {
506
+ if (newCell !== oldCell) {
516
507
  callListeners(
517
- rowListeners[mutator],
518
- [tableId, rowId],
508
+ cellListeners[mutator],
509
+ [tableId, rowId, cellId],
510
+ newCell,
511
+ oldCell,
519
512
  getCellChange,
520
513
  );
514
+ tablesChanged = tableChanged = rowChanged = 1;
521
515
  }
522
516
  });
523
- if (tableChanged) {
524
- callListeners(tableListeners[mutator], [tableId], getCellChange);
517
+ if (rowChanged) {
518
+ callListeners(
519
+ rowListeners[mutator],
520
+ [tableId, rowId],
521
+ getCellChange,
522
+ );
525
523
  }
526
524
  });
527
- if (tablesChanged) {
528
- callListeners(tablesListeners[mutator], [], getCellChange);
525
+ if (tableChanged) {
526
+ callListeners(tableListeners[mutator], [tableId], getCellChange);
529
527
  }
528
+ });
529
+ if (tablesChanged) {
530
+ callListeners(tablesListeners[mutator], [], getCellChange);
530
531
  }
531
532
  }
532
533
  }
@@ -655,61 +656,79 @@ const createStore = () => {
655
656
  if (transactions == -1) {
656
657
  return;
657
658
  }
658
- transactions++;
659
+ startTransaction();
659
660
  const result = actions?.();
660
- transactions--;
661
- if (transactions == 0) {
662
- transactions = 1;
663
- callInvalidCellListeners(1);
664
- callListenersForChanges(1);
665
- transactions = -1;
666
- if (
667
- doRollback?.(
668
- mapToObj(
669
- changedCells,
670
- (table) =>
671
- mapToObj(
672
- table,
673
- (row) =>
674
- mapToObj(
675
- row,
676
- (cells) => [...cells],
677
- ([oldCell, newCell]) => oldCell === newCell,
678
- ),
679
- objIsEmpty,
680
- ),
681
- objIsEmpty,
682
- ),
683
- mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
684
- )
685
- ) {
661
+ finishTransaction(doRollback);
662
+ return result;
663
+ };
664
+ const startTransaction = () => {
665
+ transactions++;
666
+ return store;
667
+ };
668
+ const finishTransaction = (doRollback) => {
669
+ if (transactions > 0) {
670
+ transactions--;
671
+ if (transactions == 0) {
672
+ cellsTouched = !collIsEmpty(changedCells);
686
673
  transactions = 1;
687
- collForEach(changedCells, (table, tableId) =>
688
- collForEach(table, (row, rowId) =>
689
- collForEach(row, ([oldCell], cellId) =>
690
- isUndefined(oldCell)
691
- ? delCell(tableId, rowId, cellId, true)
692
- : setCell(tableId, rowId, cellId, oldCell),
674
+ callInvalidCellListeners(1);
675
+ if (cellsTouched) {
676
+ callListenersForChanges(1);
677
+ }
678
+ transactions = -1;
679
+ if (
680
+ doRollback?.(
681
+ mapToObj(
682
+ changedCells,
683
+ (table) =>
684
+ mapToObj(
685
+ table,
686
+ (row) =>
687
+ mapToObj(
688
+ row,
689
+ (cells) => [...cells],
690
+ ([oldCell, newCell]) => oldCell === newCell,
691
+ ),
692
+ objIsEmpty,
693
+ ),
694
+ objIsEmpty,
693
695
  ),
694
- ),
696
+ mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
697
+ )
698
+ ) {
699
+ transactions = 1;
700
+ collForEach(changedCells, (table, tableId) =>
701
+ collForEach(table, (row, rowId) =>
702
+ collForEach(row, ([oldCell], cellId) =>
703
+ isUndefined(oldCell)
704
+ ? delCell(tableId, rowId, cellId, true)
705
+ : setCell(tableId, rowId, cellId, oldCell),
706
+ ),
707
+ ),
708
+ );
709
+ transactions = -1;
710
+ cellsTouched = false;
711
+ }
712
+ callListeners(finishTransactionListeners[0], [], cellsTouched);
713
+ callInvalidCellListeners(0);
714
+ if (cellsTouched) {
715
+ callListenersForChanges(0);
716
+ }
717
+ callListeners(finishTransactionListeners[1], [], cellsTouched);
718
+ transactions = 0;
719
+ arrayForEach(
720
+ [
721
+ changedCells,
722
+ invalidCells,
723
+ changedTableIds,
724
+ changedRowIds,
725
+ changedCellIds,
726
+ ],
727
+ collClear,
695
728
  );
696
- transactions = -1;
697
729
  }
698
- callInvalidCellListeners(0);
699
- callListenersForChanges(0);
700
- transactions = 0;
701
- arrayForEach(
702
- [
703
- changedCells,
704
- invalidCells,
705
- changedTableIds,
706
- changedRowIds,
707
- changedCellIds,
708
- ],
709
- collClear,
710
- );
711
730
  }
712
- return result;
731
+ return store;
713
732
  };
714
733
  const forEachTable = (tableCallback) =>
715
734
  collForEach(tablesMap, (tableMap, tableId) =>
@@ -751,6 +770,10 @@ const createStore = () => {
751
770
  rowId,
752
771
  cellId,
753
772
  ]);
773
+ const addWillFinishTransactionListener = (listener) =>
774
+ addListener(listener, finishTransactionListeners[0]);
775
+ const addDidFinishTransactionListener = (listener) =>
776
+ addListener(listener, finishTransactionListeners[1]);
754
777
  const callListener = (listenerId) => {
755
778
  callListenerImpl(listenerId, [getTableIds, getRowIds, getCellIds], (ids) =>
756
779
  isUndefined(ids[2]) ? [] : arrayPair(getCell(...ids)),
@@ -769,6 +792,7 @@ const createStore = () => {
769
792
  row: collPairSize(rowListeners, collSize3),
770
793
  cellIds: collPairSize(cellIdsListeners, collSize3),
771
794
  cell: collPairSize(cellListeners, collSize4),
795
+ invalidCell: collPairSize(invalidCellListeners, collSize4),
772
796
  });
773
797
  const store = {
774
798
  getTables,
@@ -798,6 +822,8 @@ const createStore = () => {
798
822
  delCell,
799
823
  delSchema,
800
824
  transaction,
825
+ startTransaction,
826
+ finishTransaction,
801
827
  forEachTable,
802
828
  forEachRow,
803
829
  forEachCell,
@@ -809,6 +835,8 @@ const createStore = () => {
809
835
  addCellIdsListener,
810
836
  addCellListener,
811
837
  addInvalidCellListener,
838
+ addWillFinishTransactionListener,
839
+ addDidFinishTransactionListener,
812
840
  callListener,
813
841
  delListener,
814
842
  getListenerStats,