tinybase 1.1.0-beta.0 → 1.2.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.
@@ -8,6 +8,7 @@ const FUNCTION = getTypeOf(getTypeOf);
8
8
  const TYPE = 'type';
9
9
  const DEFAULT = 'default';
10
10
 
11
+ const arrayPair = (value) => [value, value];
11
12
  const arrayHas = (array, value) => array.includes(value);
12
13
  const arrayForEach = (array, cb) => array.forEach(cb);
13
14
  const arrayLength = (array) => array.length;
@@ -69,10 +70,14 @@ const mapEnsure = (map, key, defaultValue, onWillAdd) => {
69
70
  }
70
71
  return mapGet(map, key);
71
72
  };
72
- const mapToObj = (map, childMapper) => {
73
+ const mapToObj = (map, childMapper, childExclude) => {
73
74
  const obj = {};
74
75
  const mapper = childMapper ?? ((mapValue) => mapValue);
75
- collForEach(map, (value, key) => (obj[key] = mapper(value)));
76
+ collForEach(map, (value, key) =>
77
+ ifNotUndefined(mapper(value), (mappedValue) =>
78
+ childExclude?.(mappedValue) ? 0 : (obj[key] = mappedValue),
79
+ ),
80
+ );
76
81
  return obj;
77
82
  };
78
83
  const mapClone = (map, childMapper) => {
@@ -81,6 +86,7 @@ const mapClone = (map, childMapper) => {
81
86
  collForEach(map, (value, key) => map2.set(key, mapper(value)));
82
87
  return map2;
83
88
  };
89
+ const mapClone2 = (map) => mapClone(map, mapClone);
84
90
 
85
91
  const object = Object;
86
92
  const objIds = object.keys;
@@ -188,8 +194,9 @@ const getCellType = (cell) => {
188
194
  ? type
189
195
  : void 0;
190
196
  };
191
- const validate = (obj, validateChild) => {
192
- if (isUndefined(obj) || !isObject(obj) || objFrozen(obj)) {
197
+ const validate = (obj, validateChild, onInvalidObj) => {
198
+ if (isUndefined(obj) || !isObject(obj) || objIsEmpty(obj) || objFrozen(obj)) {
199
+ onInvalidObj?.();
193
200
  return false;
194
201
  }
195
202
  objForEach(obj, (child, id) => {
@@ -211,7 +218,7 @@ const createStore = () => {
211
218
  const changedCells = mapNew();
212
219
  const invalidCells = mapNew();
213
220
  const schemaMap = mapNew();
214
- const schemaDefaultRows = mapNew();
221
+ const schemaRowCache = mapNew();
215
222
  const tablesMap = mapNew();
216
223
  const tablesListeners = mapNewPair(setNew);
217
224
  const tableIdsListeners = mapNewPair(setNew);
@@ -241,13 +248,18 @@ const createStore = () => {
241
248
  return true;
242
249
  }),
243
250
  );
244
- const validateTables = (tables) => validate(tables, validateTable);
251
+ const validateTables = (tables) =>
252
+ validate(tables, validateTable, cellInvalid);
245
253
  const validateTable = (table, tableId) =>
246
- (!hasSchema || collHas(schemaMap, tableId)) &&
247
- validate(table, (row, rowId) => validateRow(tableId, rowId, row));
254
+ (!hasSchema || collHas(schemaMap, tableId) || cellInvalid(tableId)) &&
255
+ validate(
256
+ table,
257
+ (row, rowId) => validateRow(tableId, rowId, row),
258
+ () => cellInvalid(tableId),
259
+ );
248
260
  const validateRow = (tableId, rowId, row, skipDefaults) =>
249
261
  validate(
250
- skipDefaults ? row : addDefaultsToRow(row, tableId),
262
+ skipDefaults ? row : addDefaultsToRow(row, tableId, rowId),
251
263
  (cell, cellId) =>
252
264
  ifNotUndefined(
253
265
  getValidatedCell(tableId, rowId, cellId, cell),
@@ -257,6 +269,7 @@ const createStore = () => {
257
269
  },
258
270
  () => false,
259
271
  ),
272
+ () => cellInvalid(tableId, rowId),
260
273
  );
261
274
  const getValidatedCell = (tableId, rowId, cellId, cell) =>
262
275
  hasSchema
@@ -266,17 +279,26 @@ const createStore = () => {
266
279
  getCellType(cell) != cellSchema[TYPE]
267
280
  ? cellInvalid(tableId, rowId, cellId, cell, cellSchema[DEFAULT])
268
281
  : cell,
282
+ () => cellInvalid(tableId, rowId, cellId, cell),
269
283
  )
270
284
  : isUndefined(getCellType(cell))
271
285
  ? cellInvalid(tableId, rowId, cellId, cell)
272
286
  : cell;
273
- const addDefaultsToRow = (row, tableId) => {
274
- ifNotUndefined(mapGet(schemaDefaultRows, tableId), (defaultRow) =>
275
- objForEach(defaultRow, (cell, cellId) => {
276
- if (!objHas(row, cellId)) {
277
- row[cellId] = cell;
278
- }
279
- }),
287
+ const addDefaultsToRow = (row, tableId, rowId) => {
288
+ ifNotUndefined(
289
+ mapGet(schemaRowCache, tableId),
290
+ ([rowDefaulted, rowNonDefaulted]) => {
291
+ collForEach(rowDefaulted, (cell, cellId) => {
292
+ if (!objHas(row, cellId)) {
293
+ row[cellId] = cell;
294
+ }
295
+ });
296
+ collForEach(rowNonDefaulted, (cellId) => {
297
+ if (!objHas(row, cellId)) {
298
+ cellInvalid(tableId, rowId, cellId);
299
+ }
300
+ });
301
+ },
280
302
  );
281
303
  return row;
282
304
  };
@@ -285,7 +307,8 @@ const createStore = () => {
285
307
  schemaMap,
286
308
  schema,
287
309
  (_schema, tableId, tableSchema) => {
288
- const defaultRow = {};
310
+ const rowDefaulted = mapNew();
311
+ const rowNonDefaulted = setNew();
289
312
  transformMap(
290
313
  mapEnsure(schemaMap, tableId, mapNew()),
291
314
  tableSchema,
@@ -293,15 +316,16 @@ const createStore = () => {
293
316
  mapSet(tableSchemaMap, cellId, cellSchema);
294
317
  ifNotUndefined(
295
318
  cellSchema[DEFAULT],
296
- (def) => (defaultRow[cellId] = def),
319
+ (def) => mapSet(rowDefaulted, cellId, def),
320
+ () => setAdd(rowNonDefaulted, cellId),
297
321
  );
298
322
  },
299
323
  );
300
- mapSet(schemaDefaultRows, tableId, defaultRow);
324
+ mapSet(schemaRowCache, tableId, [rowDefaulted, rowNonDefaulted]);
301
325
  },
302
326
  (_schema, tableId) => {
303
327
  mapSet(schemaMap, tableId);
304
- mapSet(schemaDefaultRows, tableId);
328
+ mapSet(schemaRowCache, tableId);
305
329
  },
306
330
  );
307
331
  const setValidTables = (tables) =>
@@ -337,14 +361,10 @@ const createStore = () => {
337
361
  }
338
362
  const oldCell = mapGet(rowMap, cellId);
339
363
  if (newCell !== oldCell) {
340
- cellChanged(tableId, rowId, cellId, oldCell);
364
+ cellChanged(tableId, rowId, cellId, oldCell, newCell);
341
365
  mapSet(rowMap, cellId, newCell);
342
366
  }
343
367
  };
344
- const setValidRowTransaction = (tableId, rowId, row) =>
345
- transaction(() =>
346
- setValidRow(tableId, getOrCreateTable(tableId), rowId, row),
347
- );
348
368
  const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
349
369
  ifNotUndefined(
350
370
  mapGet(tableMap, rowId),
@@ -354,7 +374,7 @@ const createStore = () => {
354
374
  tableId,
355
375
  tableMap,
356
376
  rowId,
357
- addDefaultsToRow({[cellId]: validCell}, tableId),
377
+ addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
358
378
  ),
359
379
  );
360
380
  const getNewRowId = (tableMap) => {
@@ -370,7 +390,7 @@ const createStore = () => {
370
390
  const delValidRow = (tableId, tableMap, rowId) =>
371
391
  setValidRow(tableId, tableMap, rowId, {}, true);
372
392
  const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
373
- const defaultCell = mapGet(schemaDefaultRows, tableId)?.[cellId];
393
+ const defaultCell = mapGet(mapGet(schemaRowCache, tableId)?.[0], cellId);
374
394
  if (!isUndefined(defaultCell) && !forceDel) {
375
395
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
376
396
  }
@@ -398,12 +418,12 @@ const createStore = () => {
398
418
  cellId,
399
419
  added,
400
420
  );
401
- const cellChanged = (tableId, rowId, cellId, oldCell) =>
402
- mapEnsure(
421
+ const cellChanged = (tableId, rowId, cellId, oldCell, newCell) =>
422
+ (mapEnsure(
403
423
  mapEnsure(mapEnsure(changedCells, tableId, mapNew()), rowId, mapNew()),
404
424
  cellId,
405
- oldCell,
406
- );
425
+ [oldCell],
426
+ )[1] = newCell);
407
427
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
408
428
  arrayPush(
409
429
  mapEnsure(
@@ -415,108 +435,108 @@ const createStore = () => {
415
435
  );
416
436
  return defaultedCell;
417
437
  };
418
- const getCellChange = (tableId, rowId, cellId) => {
419
- const changedRow = mapGet(mapGet(changedCells, tableId), rowId);
420
- const newCell = getCell(tableId, rowId, cellId);
421
- return collHas(changedRow, cellId)
422
- ? [true, mapGet(changedRow, cellId), newCell]
423
- : [false, newCell, newCell];
424
- };
425
- const callInvalidCellListeners = (mutator) => {
426
- if (!collIsEmpty(invalidCellListeners[mutator])) {
427
- collForEach(
428
- mutator
429
- ? mapClone(invalidCells, (table) => mapClone(table, mapClone))
430
- : invalidCells,
431
- (rows, tableId) =>
432
- collForEach(rows, (cells, rowId) =>
433
- collForEach(cells, (invalidCell, cellId) =>
434
- callListeners(
435
- invalidCellListeners[mutator],
436
- [tableId, rowId, cellId],
437
- invalidCell,
438
+ const getCellChange = (tableId, rowId, cellId) =>
439
+ ifNotUndefined(
440
+ mapGet(mapGet(mapGet(changedCells, tableId), rowId), cellId),
441
+ ([oldCell, newCell]) => [true, oldCell, newCell],
442
+ () => [false, ...arrayPair(getCell(tableId, rowId, cellId))],
443
+ );
444
+ const callInvalidCellListeners = (mutator) =>
445
+ !collIsEmpty(invalidCells) && !collIsEmpty(invalidCellListeners[mutator])
446
+ ? collForEach(
447
+ mutator ? mapClone(invalidCells, mapClone2) : invalidCells,
448
+ (rows, tableId) =>
449
+ collForEach(rows, (cells, rowId) =>
450
+ collForEach(cells, (invalidCell, cellId) =>
451
+ callListeners(
452
+ invalidCellListeners[mutator],
453
+ [tableId, rowId, cellId],
454
+ invalidCell,
455
+ ),
438
456
  ),
439
457
  ),
440
- ),
441
- );
442
- }
443
- };
458
+ )
459
+ : 0;
444
460
  const callListenersForChanges = (mutator) => {
445
- const emptyIdListeners =
446
- collIsEmpty(cellIdsListeners[mutator]) &&
447
- collIsEmpty(rowIdsListeners[mutator]) &&
448
- collIsEmpty(tableIdsListeners[mutator]);
449
- const emptyOtherListeners =
450
- collIsEmpty(cellListeners[mutator]) &&
451
- collIsEmpty(rowListeners[mutator]) &&
452
- collIsEmpty(tableListeners[mutator]) &&
453
- collIsEmpty(tablesListeners[mutator]);
454
- if (emptyIdListeners && emptyOtherListeners) {
455
- return;
456
- }
457
- const changes = mutator
458
- ? [
459
- mapClone(changedTableIds),
460
- mapClone(changedRowIds, mapClone),
461
- mapClone(changedCellIds, (table) => mapClone(table, mapClone)),
462
- mapClone(changedCells, (table) => mapClone(table, mapClone)),
463
- ]
464
- : [changedTableIds, changedRowIds, changedCellIds, changedCells];
465
- if (!emptyIdListeners) {
466
- collForEach(changes[2], (rowCellIds, tableId) =>
467
- collForEach(rowCellIds, (changedIds, rowId) => {
468
- if (!collIsEmpty(changedIds)) {
469
- callListeners(cellIdsListeners[mutator], [tableId, rowId]);
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) => {
489
+ if (!collIsEmpty(changedIds)) {
490
+ callListeners(rowIdsListeners[mutator], [tableId]);
491
+ }
492
+ });
493
+ if (!collIsEmpty(changes[0])) {
494
+ callListeners(tableIdsListeners[mutator]);
470
495
  }
471
- }),
472
- );
473
- collForEach(changes[1], (changedIds, tableId) => {
474
- if (!collIsEmpty(changedIds)) {
475
- callListeners(rowIdsListeners[mutator], [tableId]);
476
496
  }
477
- });
478
- if (!collIsEmpty(changes[0])) {
479
- callListeners(tableIdsListeners[mutator]);
480
- }
481
- }
482
- if (!emptyOtherListeners) {
483
- let tablesChanged;
484
- collForEach(changes[3], (rows, tableId) => {
485
- let tableChanged;
486
- collForEach(rows, (cells, rowId) => {
487
- let rowChanged;
488
- collForEach(cells, (oldCell, cellId) => {
489
- const newCell = getCell(tableId, rowId, cellId);
490
- if (newCell !== oldCell) {
491
- callListeners(
492
- cellListeners[mutator],
493
- [tableId, rowId, cellId],
494
- newCell,
495
- oldCell,
496
- getCellChange,
497
- );
498
- tablesChanged = tableChanged = rowChanged = 1;
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) {
516
+ callListeners(
517
+ rowListeners[mutator],
518
+ [tableId, rowId],
519
+ getCellChange,
520
+ );
521
+ }
522
+ });
523
+ if (tableChanged) {
524
+ callListeners(tableListeners[mutator], [tableId], getCellChange);
499
525
  }
500
526
  });
501
- if (rowChanged) {
502
- callListeners(
503
- rowListeners[mutator],
504
- [tableId, rowId],
505
- getCellChange,
506
- );
527
+ if (tablesChanged) {
528
+ callListeners(tablesListeners[mutator], [], getCellChange);
507
529
  }
508
- });
509
- if (tableChanged) {
510
- callListeners(tableListeners[mutator], [tableId], getCellChange);
511
530
  }
512
- });
513
- if (tablesChanged) {
514
- callListeners(tablesListeners[mutator], [], getCellChange);
515
531
  }
516
532
  }
517
533
  };
534
+ const fluentTransaction = (actions) => {
535
+ transaction(actions);
536
+ return store;
537
+ };
518
538
  const getTables = () =>
519
- mapToObj(tablesMap, (tableMap) => mapToObj(tableMap, mapToObj));
539
+ mapToObj(tablesMap, (table) => mapToObj(table, mapToObj));
520
540
  const getTableIds = () => mapKeys(tablesMap);
521
541
  const getTable = (tableId) => mapToObj(mapGet(tablesMap, tableId), mapToObj);
522
542
  const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, tableId));
@@ -533,56 +553,52 @@ const createStore = () => {
533
553
  collHas(mapGet(mapGet(tablesMap, tableId), rowId), cellId);
534
554
  const getJson = () => jsonString(tablesMap);
535
555
  const getSchemaJson = () => jsonString(schemaMap);
536
- const setTables = (tables) => {
537
- validateTables(tables)
538
- ? transaction(() => setValidTables(tables))
539
- : transaction();
540
- return store;
541
- };
542
- const setTable = (tableId, table) => {
543
- validateTable(table, tableId)
544
- ? transaction(() => setValidTable(tableId, table))
545
- : transaction();
546
- return store;
547
- };
548
- const setRow = (tableId, rowId, row) => {
549
- validateRow(tableId, rowId, row)
550
- ? setValidRowTransaction(tableId, rowId, row)
551
- : transaction();
552
- return store;
553
- };
554
- const addRow = (tableId, row) => {
555
- let rowId = void 0;
556
- validateRow(tableId, rowId, row)
557
- ? setValidRowTransaction(
556
+ const setTables = (tables) =>
557
+ fluentTransaction(() =>
558
+ validateTables(tables) ? setValidTables(tables) : 0,
559
+ );
560
+ const setTable = (tableId, table) =>
561
+ fluentTransaction(() =>
562
+ validateTable(table, tableId) ? setValidTable(tableId, table) : 0,
563
+ );
564
+ const setRow = (tableId, rowId, row) =>
565
+ fluentTransaction(() =>
566
+ validateRow(tableId, rowId, row)
567
+ ? setValidRow(tableId, getOrCreateTable(tableId), rowId, row)
568
+ : 0,
569
+ );
570
+ const addRow = (tableId, row) =>
571
+ transaction(() => {
572
+ let rowId = void 0;
573
+ if (validateRow(tableId, rowId, row)) {
574
+ setValidRow(
558
575
  tableId,
576
+ getOrCreateTable(tableId),
559
577
  (rowId = getNewRowId(mapGet(tablesMap, tableId))),
560
578
  row,
561
- )
562
- : transaction();
563
- return rowId;
564
- };
565
- const setPartialRow = (tableId, rowId, partialRow) => {
566
- validateRow(tableId, rowId, partialRow, 1)
567
- ? transaction(() => {
568
- const table = getOrCreateTable(tableId);
569
- objForEach(partialRow, (cell, cellId) =>
570
- setCellIntoDefaultRow(tableId, table, rowId, cellId, cell),
571
- );
572
- })
573
- : transaction();
574
- return store;
575
- };
576
- const setCell = (tableId, rowId, cellId, cell) => {
577
- ifNotUndefined(
578
- getValidatedCell(
579
- tableId,
580
- rowId,
581
- cellId,
582
- isFunction(cell) ? cell(getCell(tableId, rowId, cellId)) : cell,
583
- ),
584
- (validCell) =>
585
- transaction(() =>
579
+ );
580
+ }
581
+ return rowId;
582
+ });
583
+ const setPartialRow = (tableId, rowId, partialRow) =>
584
+ fluentTransaction(() => {
585
+ if (validateRow(tableId, rowId, partialRow, 1)) {
586
+ const table = getOrCreateTable(tableId);
587
+ objForEach(partialRow, (cell, cellId) =>
588
+ setCellIntoDefaultRow(tableId, table, rowId, cellId, cell),
589
+ );
590
+ }
591
+ });
592
+ const setCell = (tableId, rowId, cellId, cell) =>
593
+ fluentTransaction(() =>
594
+ ifNotUndefined(
595
+ getValidatedCell(
596
+ tableId,
597
+ rowId,
598
+ cellId,
599
+ isFunction(cell) ? cell(getCell(tableId, rowId, cellId)) : cell,
600
+ ),
601
+ (validCell) =>
586
602
  setCellIntoDefaultRow(
587
603
  tableId,
588
604
  getOrCreateTable(tableId),
@@ -590,64 +606,52 @@ const createStore = () => {
590
606
  cellId,
591
607
  validCell,
592
608
  ),
593
- ),
594
- transaction,
609
+ ),
595
610
  );
596
- return store;
597
- };
598
611
  const setJson = (json) => {
599
612
  try {
600
613
  json === EMPTY_OBJECT ? delTables() : setTables(jsonParse(json));
601
614
  } catch {}
602
615
  return store;
603
616
  };
604
- const setSchema = (schema) => {
605
- if ((hasSchema = validateSchema(schema))) {
606
- setValidSchema(schema);
607
- if (!collIsEmpty(tablesMap)) {
608
- const tables = getTables();
609
- delTables();
610
- setTables(tables);
611
- }
612
- }
613
- return store;
614
- };
615
- const delTables = () => {
616
- transaction(() => setValidTables({}));
617
- return store;
618
- };
619
- const delTable = (tableId) => {
620
- if (collHas(tablesMap, tableId)) {
621
- transaction(() => delValidTable(tableId));
622
- }
623
- return store;
624
- };
625
- const delRow = (tableId, rowId) => {
626
- ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) => {
627
- if (collHas(tableMap, rowId)) {
628
- transaction(() => delValidRow(tableId, tableMap, rowId));
617
+ const setSchema = (schema) =>
618
+ fluentTransaction(() => {
619
+ if ((hasSchema = validateSchema(schema))) {
620
+ setValidSchema(schema);
621
+ if (!collIsEmpty(tablesMap)) {
622
+ const tables = getTables();
623
+ delTables();
624
+ setTables(tables);
625
+ }
629
626
  }
630
627
  });
631
- return store;
632
- };
633
- const delCell = (tableId, rowId, cellId, forceDel) => {
634
- ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) =>
635
- ifNotUndefined(mapGet(tableMap, rowId), (rowMap) => {
636
- if (collHas(rowMap, cellId)) {
637
- transaction(() =>
638
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
639
- );
640
- }
641
- }),
628
+ const delTables = () => fluentTransaction(() => setValidTables({}));
629
+ const delTable = (tableId) =>
630
+ fluentTransaction(() =>
631
+ collHas(tablesMap, tableId) ? delValidTable(tableId) : 0,
642
632
  );
643
- return store;
644
- };
645
- const delSchema = () => {
646
- setValidSchema({});
647
- hasSchema = false;
648
- return store;
649
- };
650
- const transaction = (actions) => {
633
+ const delRow = (tableId, rowId) =>
634
+ fluentTransaction(() =>
635
+ ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) =>
636
+ collHas(tableMap, rowId) ? delValidRow(tableId, tableMap, rowId) : 0,
637
+ ),
638
+ );
639
+ const delCell = (tableId, rowId, cellId, forceDel) =>
640
+ fluentTransaction(() =>
641
+ ifNotUndefined(mapGet(tablesMap, tableId), (tableMap) =>
642
+ ifNotUndefined(mapGet(tableMap, rowId), (rowMap) =>
643
+ collHas(rowMap, cellId)
644
+ ? delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel)
645
+ : 0,
646
+ ),
647
+ ),
648
+ );
649
+ const delSchema = () =>
650
+ fluentTransaction(() => {
651
+ setValidSchema({});
652
+ hasSchema = false;
653
+ });
654
+ const transaction = (actions, doRollback) => {
651
655
  if (transactions == -1) {
652
656
  return;
653
657
  }
@@ -659,6 +663,38 @@ const createStore = () => {
659
663
  callInvalidCellListeners(1);
660
664
  callListenersForChanges(1);
661
665
  transactions = -1;
666
+ if (
667
+ doRollback?.(
668
+ mapToObj(
669
+ changedCells,
670
+ (table) =>
671
+ mapToObj(
672
+ table,
673
+ (row) =>
674
+ mapToObj(
675
+ row,
676
+ void 0,
677
+ ([oldCell, newCell]) => oldCell === newCell,
678
+ ),
679
+ objIsEmpty,
680
+ ),
681
+ objIsEmpty,
682
+ ),
683
+ mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
684
+ )
685
+ ) {
686
+ 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),
693
+ ),
694
+ ),
695
+ );
696
+ transactions = -1;
697
+ }
662
698
  callInvalidCellListeners(0);
663
699
  callListenersForChanges(0);
664
700
  transactions = 0;
@@ -717,7 +753,7 @@ const createStore = () => {
717
753
  ]);
718
754
  const callListener = (listenerId) => {
719
755
  callListenerImpl(listenerId, [getTableIds, getRowIds, getCellIds], (ids) =>
720
- isUndefined(ids[2]) ? [] : Array(2).fill(getCell(...ids)),
756
+ isUndefined(ids[2]) ? [] : arrayPair(getCell(...ids)),
721
757
  );
722
758
  return store;
723
759
  };