tinybase 3.0.0-beta.0 → 3.0.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.
Files changed (110) hide show
  1. package/bin/cli.js +1 -1
  2. package/lib/checkpoints.d.ts +18 -3
  3. package/lib/checkpoints.js +1 -1
  4. package/lib/checkpoints.js.gz +0 -0
  5. package/lib/debug/checkpoints.d.ts +18 -3
  6. package/lib/debug/checkpoints.js +97 -49
  7. package/lib/debug/indexes.js +31 -16
  8. package/lib/debug/metrics.js +31 -16
  9. package/lib/debug/persisters.d.ts +33 -23
  10. package/lib/debug/persisters.js +10 -5
  11. package/lib/debug/queries.js +2 -2
  12. package/lib/debug/relationships.js +31 -16
  13. package/lib/debug/store.d.ts +2053 -381
  14. package/lib/debug/store.js +444 -106
  15. package/lib/debug/tinybase.js +512 -138
  16. package/lib/debug/tools.d.ts +109 -38
  17. package/lib/debug/tools.js +759 -453
  18. package/lib/debug/ui-react.d.ts +1218 -138
  19. package/lib/debug/ui-react.js +163 -12
  20. package/lib/es6/checkpoints.d.ts +18 -3
  21. package/lib/es6/checkpoints.js +1 -1
  22. package/lib/es6/checkpoints.js.gz +0 -0
  23. package/lib/es6/indexes.js +1 -1
  24. package/lib/es6/indexes.js.gz +0 -0
  25. package/lib/es6/metrics.js +1 -1
  26. package/lib/es6/metrics.js.gz +0 -0
  27. package/lib/es6/persisters.d.ts +33 -23
  28. package/lib/es6/persisters.js +1 -1
  29. package/lib/es6/persisters.js.gz +0 -0
  30. package/lib/es6/relationships.js +1 -1
  31. package/lib/es6/relationships.js.gz +0 -0
  32. package/lib/es6/store.d.ts +2053 -381
  33. package/lib/es6/store.js +1 -1
  34. package/lib/es6/store.js.gz +0 -0
  35. package/lib/es6/tinybase.js +1 -1
  36. package/lib/es6/tinybase.js.gz +0 -0
  37. package/lib/es6/tools.d.ts +109 -38
  38. package/lib/es6/tools.js +1 -1
  39. package/lib/es6/tools.js.gz +0 -0
  40. package/lib/es6/ui-react.d.ts +1218 -138
  41. package/lib/es6/ui-react.js +1 -1
  42. package/lib/es6/ui-react.js.gz +0 -0
  43. package/lib/indexes.js +1 -1
  44. package/lib/indexes.js.gz +0 -0
  45. package/lib/metrics.js +1 -1
  46. package/lib/metrics.js.gz +0 -0
  47. package/lib/persisters.d.ts +33 -23
  48. package/lib/persisters.js +1 -1
  49. package/lib/persisters.js.gz +0 -0
  50. package/lib/relationships.js +1 -1
  51. package/lib/relationships.js.gz +0 -0
  52. package/lib/store.d.ts +2053 -381
  53. package/lib/store.js +1 -1
  54. package/lib/store.js.gz +0 -0
  55. package/lib/tinybase.js +1 -1
  56. package/lib/tinybase.js.gz +0 -0
  57. package/lib/tools.d.ts +109 -38
  58. package/lib/tools.js +1 -1
  59. package/lib/tools.js.gz +0 -0
  60. package/lib/ui-react.d.ts +1218 -138
  61. package/lib/ui-react.js +1 -1
  62. package/lib/ui-react.js.gz +0 -0
  63. package/lib/umd/checkpoints.d.ts +18 -3
  64. package/lib/umd/checkpoints.js +1 -1
  65. package/lib/umd/checkpoints.js.gz +0 -0
  66. package/lib/umd/indexes.js +1 -1
  67. package/lib/umd/indexes.js.gz +0 -0
  68. package/lib/umd/metrics.js +1 -1
  69. package/lib/umd/metrics.js.gz +0 -0
  70. package/lib/umd/persisters.d.ts +33 -23
  71. package/lib/umd/persisters.js +1 -1
  72. package/lib/umd/persisters.js.gz +0 -0
  73. package/lib/umd/relationships.js +1 -1
  74. package/lib/umd/relationships.js.gz +0 -0
  75. package/lib/umd/store.d.ts +2053 -381
  76. package/lib/umd/store.js +1 -1
  77. package/lib/umd/store.js.gz +0 -0
  78. package/lib/umd/tinybase.js +1 -1
  79. package/lib/umd/tinybase.js.gz +0 -0
  80. package/lib/umd/tools.d.ts +109 -38
  81. package/lib/umd/tools.js +1 -1
  82. package/lib/umd/tools.js.gz +0 -0
  83. package/lib/umd/ui-react.d.ts +1218 -138
  84. package/lib/umd/ui-react.js +1 -1
  85. package/lib/umd/ui-react.js.gz +0 -0
  86. package/lib/umd-es6/checkpoints.d.ts +18 -3
  87. package/lib/umd-es6/checkpoints.js +1 -1
  88. package/lib/umd-es6/checkpoints.js.gz +0 -0
  89. package/lib/umd-es6/indexes.js +1 -1
  90. package/lib/umd-es6/indexes.js.gz +0 -0
  91. package/lib/umd-es6/metrics.js +1 -1
  92. package/lib/umd-es6/metrics.js.gz +0 -0
  93. package/lib/umd-es6/persisters.d.ts +33 -23
  94. package/lib/umd-es6/persisters.js +1 -1
  95. package/lib/umd-es6/persisters.js.gz +0 -0
  96. package/lib/umd-es6/relationships.js +1 -1
  97. package/lib/umd-es6/relationships.js.gz +0 -0
  98. package/lib/umd-es6/store.d.ts +2053 -381
  99. package/lib/umd-es6/store.js +1 -1
  100. package/lib/umd-es6/store.js.gz +0 -0
  101. package/lib/umd-es6/tinybase.js +1 -1
  102. package/lib/umd-es6/tinybase.js.gz +0 -0
  103. package/lib/umd-es6/tools.d.ts +109 -38
  104. package/lib/umd-es6/tools.js +1 -1
  105. package/lib/umd-es6/tools.js.gz +0 -0
  106. package/lib/umd-es6/ui-react.d.ts +1218 -138
  107. package/lib/umd-es6/ui-react.js +1 -1
  108. package/lib/umd-es6/ui-react.js.gz +0 -0
  109. package/package.json +20 -20
  110. package/readme.md +27 -16
@@ -1,7 +1,6 @@
1
1
  import {promises, watch} from 'fs';
2
2
 
3
3
  const getTypeOf = (thing) => typeof thing;
4
- const EMPTY_OBJECT = '{}';
5
4
  const EMPTY_STRING = '';
6
5
  const STRING = getTypeOf(EMPTY_STRING);
7
6
  const BOOLEAN = getTypeOf(true);
@@ -26,6 +25,9 @@ const SORTED_ROW_IDS = 'SortedRowIds';
26
25
  const ROW = 'Row';
27
26
  const CELL_IDS = 'CellIds';
28
27
  const CELL = 'Cell';
28
+ const VALUES = 'Values';
29
+ const VALUE_IDS = 'ValueIds';
30
+ const VALUE = 'Value';
29
31
  const id = (key) => EMPTY_STRING + key;
30
32
 
31
33
  const arrayHas = (array, value) => array.includes(value);
@@ -148,6 +150,19 @@ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
148
150
  },
149
151
  );
150
152
 
153
+ const getCellOrValueType = (cell) => {
154
+ const type = getTypeOf(cell);
155
+ return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
156
+ ? type
157
+ : void 0;
158
+ };
159
+ const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
160
+ isUndefined(cell)
161
+ ? store.delCell(tableId, rowId, cellId, true)
162
+ : store.setCell(tableId, rowId, cellId, cell);
163
+ const setOrDelValue = (store, valueId, value) =>
164
+ isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
165
+
151
166
  const setNew = (entryOrEntries) =>
152
167
  new Set(
153
168
  isArray(entryOrEntries) || isUndefined(entryOrEntries)
@@ -343,10 +358,22 @@ const getListenerFunctions = (getThing) => {
343
358
  let thing;
344
359
  const [getId, releaseId] = getPoolFunctions();
345
360
  const allListeners = mapNew();
346
- const addListener = (listener, idSetNode, path) => {
361
+ const addListener = (
362
+ listener,
363
+ idSetNode,
364
+ path,
365
+ pathGetters = [],
366
+ extraArgsGetter = () => [],
367
+ ) => {
347
368
  thing ??= getThing();
348
369
  const id = getId();
349
- mapSet(allListeners, id, [listener, idSetNode, path]);
370
+ mapSet(allListeners, id, [
371
+ listener,
372
+ idSetNode,
373
+ path,
374
+ pathGetters,
375
+ extraArgsGetter,
376
+ ]);
350
377
  setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
351
378
  return id;
352
379
  };
@@ -366,20 +393,23 @@ const getListenerFunctions = (getThing) => {
366
393
  releaseId(id);
367
394
  return idOrNulls;
368
395
  });
369
- const callListener = (id, idNullGetters, extraArgsGetter) =>
370
- ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls = []]) => {
371
- const callWithIds = (...ids) => {
372
- const index = arrayLength(ids);
373
- index == arrayLength(idOrNulls)
374
- ? listener(thing, ...ids, ...extraArgsGetter(ids))
375
- : isUndefined(idOrNulls[index])
376
- ? arrayForEach(idNullGetters[index](...ids), (id2) =>
377
- callWithIds(...ids, id2),
378
- )
379
- : callWithIds(...ids, idOrNulls[index]);
380
- };
381
- callWithIds();
382
- });
396
+ const callListener = (id) =>
397
+ ifNotUndefined(
398
+ mapGet(allListeners, id),
399
+ ([listener, , path = [], pathGetters, extraArgsGetter]) => {
400
+ const callWithIds = (...ids) => {
401
+ const index = arrayLength(ids);
402
+ index == arrayLength(path)
403
+ ? listener(thing, ...ids, ...extraArgsGetter(ids))
404
+ : isUndefined(path[index])
405
+ ? arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
406
+ callWithIds(...ids, id2),
407
+ )
408
+ : callWithIds(...ids, path[index]);
409
+ };
410
+ callWithIds();
411
+ },
412
+ );
383
413
  return [addListener, callListeners, delListener, callListener];
384
414
  };
385
415
 
@@ -394,23 +424,13 @@ const objHas = (obj, id) => !isUndefined(objGet(obj, id));
394
424
  const objDel = (obj, id) => delete obj[id];
395
425
  const objMap = (obj, cb) =>
396
426
  arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
397
- const objIsEmpty = (obj) => arrayIsEmpty(objIds(obj));
398
-
399
- const getCellType = (cell) => {
400
- const type = getTypeOf(cell);
401
- return isTypeStringOrBoolean(type) || (type == NUMBER && isFiniteNumber(cell))
402
- ? type
403
- : void 0;
404
- };
405
- const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
406
- isUndefined(cell)
407
- ? store.delCell(tableId, rowId, cellId, true)
408
- : store.setCell(tableId, rowId, cellId, cell);
427
+ const objIsEmpty = (obj) => isObject(obj) && arrayIsEmpty(objIds(obj));
409
428
 
410
429
  const createCheckpoints = getCreateFunction((store) => {
411
430
  let backwardIdsSize = 100;
412
431
  let currentId;
413
- let delta = mapNew();
432
+ let cellsDelta = mapNew();
433
+ let valuesDelta = mapNew();
414
434
  let listening = 1;
415
435
  let nextCheckpointId;
416
436
  let checkpointsChanged;
@@ -425,15 +445,19 @@ const createCheckpoints = getCreateFunction((store) => {
425
445
  const forwardIds = [];
426
446
  const updateStore = (oldOrNew, checkpointId) => {
427
447
  listening = 0;
428
- store.transaction(() =>
429
- collForEach(mapGet(deltas, checkpointId), (table, tableId) =>
448
+ store.transaction(() => {
449
+ const [cellsDelta2, valuesDelta2] = mapGet(deltas, checkpointId);
450
+ collForEach(cellsDelta2, (table, tableId) =>
430
451
  collForEach(table, (row, rowId) =>
431
452
  collForEach(row, (oldNew, cellId) =>
432
453
  setOrDelCell(store, tableId, rowId, cellId, oldNew[oldOrNew]),
433
454
  ),
434
455
  ),
435
- ),
436
- );
456
+ );
457
+ collForEach(valuesDelta2, (oldNew, valueId) =>
458
+ setOrDelValue(store, valueId, oldNew[oldOrNew]),
459
+ );
460
+ });
437
461
  listening = 1;
438
462
  };
439
463
  const clearCheckpointId = (checkpointId) => {
@@ -448,32 +472,56 @@ const createCheckpoints = getCreateFunction((store) => {
448
472
  );
449
473
  const trimBackwardsIds = () =>
450
474
  clearCheckpointIds(backwardIds, arrayLength(backwardIds) - backwardIdsSize);
451
- const listenerId = store.addCellListener(
475
+ const storeChanged = () =>
476
+ ifNotUndefined(currentId, () => {
477
+ arrayPush(backwardIds, currentId);
478
+ trimBackwardsIds();
479
+ clearCheckpointIds(forwardIds);
480
+ currentId = void 0;
481
+ checkpointsChanged = 1;
482
+ });
483
+ const storeUnchanged = () => {
484
+ currentId = arrayPop(backwardIds);
485
+ checkpointsChanged = 1;
486
+ };
487
+ const cellListenerId = store.addCellListener(
452
488
  null,
453
489
  null,
454
490
  null,
455
491
  (_store, tableId, rowId, cellId, newCell, oldCell) => {
456
492
  if (listening) {
457
- ifNotUndefined(currentId, () => {
458
- arrayPush(backwardIds, currentId);
459
- trimBackwardsIds();
460
- clearCheckpointIds(forwardIds);
461
- currentId = void 0;
462
- checkpointsChanged = 1;
463
- });
464
- const table = mapEnsure(delta, tableId, mapNew);
493
+ storeChanged();
494
+ const table = mapEnsure(cellsDelta, tableId, mapNew);
465
495
  const row = mapEnsure(table, rowId, mapNew);
466
496
  const oldNew = mapEnsure(row, cellId, () => [oldCell, void 0]);
467
497
  oldNew[1] = newCell;
468
- if (oldNew[0] === newCell) {
469
- if (collIsEmpty(mapSet(row, cellId))) {
470
- if (collIsEmpty(mapSet(table, rowId))) {
471
- if (collIsEmpty(mapSet(delta, tableId))) {
472
- currentId = arrayPop(backwardIds);
473
- checkpointsChanged = 1;
474
- }
475
- }
476
- }
498
+ if (
499
+ oldNew[0] === newCell &&
500
+ collIsEmpty(mapSet(row, cellId)) &&
501
+ collIsEmpty(mapSet(table, rowId)) &&
502
+ collIsEmpty(mapSet(cellsDelta, tableId))
503
+ ) {
504
+ storeUnchanged();
505
+ }
506
+ callListenersIfChanged();
507
+ }
508
+ },
509
+ );
510
+ const valueListenerId = store.addValueListener(
511
+ null,
512
+ (_store, valueId, newValue, oldValue) => {
513
+ if (listening) {
514
+ storeChanged();
515
+ const oldNew = mapEnsure(valuesDelta, valueId, () => [
516
+ oldValue,
517
+ void 0,
518
+ ]);
519
+ oldNew[1] = newValue;
520
+ if (
521
+ oldNew[0] === newValue &&
522
+ collIsEmpty(mapSet(valuesDelta, valueId))
523
+ ) {
524
+ storeUnchanged();
477
525
  }
478
526
  callListenersIfChanged();
479
527
  }
@@ -482,9 +530,10 @@ const createCheckpoints = getCreateFunction((store) => {
482
530
  const addCheckpointImpl = (label = EMPTY_STRING) => {
483
531
  if (isUndefined(currentId)) {
484
532
  currentId = EMPTY_STRING + nextCheckpointId++;
485
- mapSet(deltas, currentId, delta);
533
+ mapSet(deltas, currentId, [cellsDelta, valuesDelta]);
486
534
  setCheckpoint(currentId, label);
487
- delta = mapNew();
535
+ cellsDelta = mapNew();
536
+ valuesDelta = mapNew();
488
537
  checkpointsChanged = 1;
489
538
  }
490
539
  return currentId;
@@ -560,8 +609,8 @@ const createCheckpoints = getCreateFunction((store) => {
560
609
  addListener(listener, checkpointIdsListeners);
561
610
  const addCheckpointListener = (checkpointId, listener) =>
562
611
  addListener(listener, checkpointListeners, [checkpointId]);
563
- const delListener = (listenerId2) => {
564
- delListenerImpl(listenerId2);
612
+ const delListener = (listenerId) => {
613
+ delListenerImpl(listenerId);
565
614
  return checkpoints;
566
615
  };
567
616
  const clear = () => {
@@ -576,7 +625,8 @@ const createCheckpoints = getCreateFunction((store) => {
576
625
  return checkpoints;
577
626
  };
578
627
  const destroy = () => {
579
- store.delListener(listenerId);
628
+ store.delListener(cellListenerId);
629
+ store.delListener(valueListenerId);
580
630
  };
581
631
  const getListenerStats = () => ({
582
632
  checkpointIds: collSize2(checkpointIdsListeners),
@@ -969,11 +1019,12 @@ const createCustomPersister = (
969
1019
  stopListeningToPersisted,
970
1020
  ) => {
971
1021
  let tablesListenerId;
1022
+ let valuesListenerId;
972
1023
  let loadSave = 0;
973
1024
  let loads = 0;
974
1025
  let saves = 0;
975
1026
  const persister = {
976
- load: async (initialTables) => {
1027
+ load: async (initialTables, initialValues) => {
977
1028
  /* istanbul ignore else */
978
1029
  if (loadSave != 2) {
979
1030
  loadSave = 1;
@@ -984,15 +1035,17 @@ const createCustomPersister = (
984
1035
  if (!isUndefined(body) && body != EMPTY_STRING) {
985
1036
  store.setJson(body);
986
1037
  } else {
987
- store.setTables(initialTables);
1038
+ store.transaction(() =>
1039
+ store.setTables(initialTables).setValues(initialValues),
1040
+ );
988
1041
  }
989
1042
  loadSave = 0;
990
1043
  }
991
1044
  return persister;
992
1045
  },
993
- startAutoLoad: async (initialTables) => {
1046
+ startAutoLoad: async (initialTables, initialValues) => {
994
1047
  persister.stopAutoLoad();
995
- await persister.load(initialTables);
1048
+ await persister.load(initialTables, initialValues);
996
1049
  startListeningToPersisted(persister.load);
997
1050
  return persister;
998
1051
  },
@@ -1014,11 +1067,13 @@ const createCustomPersister = (
1014
1067
  },
1015
1068
  startAutoSave: async () => {
1016
1069
  await persister.stopAutoSave().save();
1017
- tablesListenerId = store.addTablesListener(() => persister.save());
1070
+ tablesListenerId = store.addTablesListener(persister.save);
1071
+ valuesListenerId = store.addValuesListener(persister.save);
1018
1072
  return persister;
1019
1073
  },
1020
1074
  stopAutoSave: () => {
1021
1075
  ifNotUndefined(tablesListenerId, store.delListener);
1076
+ ifNotUndefined(valuesListenerId, store.delListener);
1022
1077
  return persister;
1023
1078
  },
1024
1079
  getStore: () => store,
@@ -1326,7 +1381,7 @@ const createQueries = getCreateFunction((store) => {
1326
1381
  aggregators,
1327
1382
  );
1328
1383
  groupRow[groupedCellId] = isUndefined(
1329
- getCellType(aggregateValue),
1384
+ getCellOrValueType(aggregateValue),
1330
1385
  )
1331
1386
  ? null
1332
1387
  : aggregateValue;
@@ -1790,18 +1845,27 @@ const validate = (obj, validateChild, onInvalidObj) => {
1790
1845
  const idsChanged = (changedIds, id2, added) =>
1791
1846
  mapSet(changedIds, id2, mapGet(changedIds, id2) == -added ? void 0 : added);
1792
1847
  const createStore = () => {
1793
- let hasSchema;
1848
+ let hasTablesSchema;
1849
+ let hasValuesSchema;
1794
1850
  let cellsTouched;
1851
+ let valuesTouched;
1795
1852
  let transactions = 0;
1796
1853
  const changedTableIds = mapNew();
1797
1854
  const changedRowIds = mapNew();
1798
1855
  const changedCellIds = mapNew();
1799
1856
  const changedCells = mapNew();
1857
+ const changedValueIds = mapNew();
1858
+ const changedValues = mapNew();
1800
1859
  const invalidCells = mapNew();
1801
- const schemaMap = mapNew();
1802
- const schemaRowCache = mapNew();
1860
+ const invalidValues = mapNew();
1861
+ const tablesSchemaMap = mapNew();
1862
+ const tablesSchemaRowCache = mapNew();
1863
+ const valuesSchemaMap = mapNew();
1864
+ const valuesDefaulted = mapNew();
1865
+ const valuesNonDefaulted = setNew();
1803
1866
  const tablePoolFunctions = mapNew();
1804
1867
  const tablesMap = mapNew();
1868
+ const valuesMap = mapNew();
1805
1869
  const tablesListeners = pairNewMap();
1806
1870
  const tableIdsListeners = pairNewMap();
1807
1871
  const tableListeners = pairNewMap();
@@ -1811,31 +1875,38 @@ const createStore = () => {
1811
1875
  const cellIdsListeners = pairNewMap();
1812
1876
  const cellListeners = pairNewMap();
1813
1877
  const invalidCellListeners = pairNewMap();
1878
+ const invalidValueListeners = pairNewMap();
1879
+ const valuesListeners = pairNewMap();
1880
+ const valueIdsListeners = pairNewMap();
1881
+ const valueListeners = pairNewMap();
1814
1882
  const finishTransactionListeners = pairNewMap();
1815
1883
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
1816
1884
  getListenerFunctions(() => store);
1817
- const validateSchema = (schema) =>
1818
- validate(schema, (tableSchema) =>
1819
- validate(tableSchema, (cellSchema) => {
1820
- if (
1821
- !validate(cellSchema, (_child, id2) => arrayHas([TYPE, DEFAULT], id2))
1822
- ) {
1823
- return false;
1824
- }
1825
- const type = cellSchema[TYPE];
1826
- if (!isTypeStringOrBoolean(type) && type != NUMBER) {
1827
- return false;
1828
- }
1829
- if (getCellType(cellSchema[DEFAULT]) != type) {
1830
- objDel(cellSchema, DEFAULT);
1831
- }
1832
- return true;
1833
- }),
1885
+ const validateTablesSchema = (tableSchema) =>
1886
+ validate(tableSchema, (tableSchema2) =>
1887
+ validate(tableSchema2, validateCellOrValueSchema),
1834
1888
  );
1889
+ const validateValuesSchema = (valuesSchema) =>
1890
+ validate(valuesSchema, validateCellOrValueSchema);
1891
+ const validateCellOrValueSchema = (schema) => {
1892
+ if (!validate(schema, (_child, id2) => arrayHas([TYPE, DEFAULT], id2))) {
1893
+ return false;
1894
+ }
1895
+ const type = schema[TYPE];
1896
+ if (!isTypeStringOrBoolean(type) && type != NUMBER) {
1897
+ return false;
1898
+ }
1899
+ if (getCellOrValueType(schema[DEFAULT]) != type) {
1900
+ objDel(schema, DEFAULT);
1901
+ }
1902
+ return true;
1903
+ };
1835
1904
  const validateTables = (tables) =>
1836
1905
  validate(tables, validateTable, cellInvalid);
1837
1906
  const validateTable = (table, tableId) =>
1838
- (!hasSchema || collHas(schemaMap, tableId) || cellInvalid(tableId)) &&
1907
+ (!hasTablesSchema ||
1908
+ collHas(tablesSchemaMap, tableId) ||
1909
+ cellInvalid(tableId)) &&
1839
1910
  validate(
1840
1911
  table,
1841
1912
  (row, rowId) => validateRow(tableId, rowId, row),
@@ -1856,21 +1927,48 @@ const createStore = () => {
1856
1927
  () => cellInvalid(tableId, rowId),
1857
1928
  );
1858
1929
  const getValidatedCell = (tableId, rowId, cellId, cell) =>
1859
- hasSchema
1930
+ hasTablesSchema
1860
1931
  ? ifNotUndefined(
1861
- mapGet(mapGet(schemaMap, tableId), cellId),
1932
+ mapGet(mapGet(tablesSchemaMap, tableId), cellId),
1862
1933
  (cellSchema) =>
1863
- getCellType(cell) != cellSchema[TYPE]
1934
+ getCellOrValueType(cell) != cellSchema[TYPE]
1864
1935
  ? cellInvalid(tableId, rowId, cellId, cell, cellSchema[DEFAULT])
1865
1936
  : cell,
1866
1937
  () => cellInvalid(tableId, rowId, cellId, cell),
1867
1938
  )
1868
- : isUndefined(getCellType(cell))
1939
+ : isUndefined(getCellOrValueType(cell))
1869
1940
  ? cellInvalid(tableId, rowId, cellId, cell)
1870
1941
  : cell;
1942
+ const validateValues = (values, skipDefaults) =>
1943
+ validate(
1944
+ skipDefaults ? values : addDefaultsToValues(values),
1945
+ (value, valueId) =>
1946
+ ifNotUndefined(
1947
+ getValidatedValue(valueId, value),
1948
+ (validValue) => {
1949
+ values[valueId] = validValue;
1950
+ return true;
1951
+ },
1952
+ () => false,
1953
+ ),
1954
+ () => valueInvalid(),
1955
+ );
1956
+ const getValidatedValue = (valueId, value) =>
1957
+ hasValuesSchema
1958
+ ? ifNotUndefined(
1959
+ mapGet(valuesSchemaMap, valueId),
1960
+ (valueSchema) =>
1961
+ getCellOrValueType(value) != valueSchema[TYPE]
1962
+ ? valueInvalid(valueId, value, valueSchema[DEFAULT])
1963
+ : value,
1964
+ () => valueInvalid(valueId, value),
1965
+ )
1966
+ : isUndefined(getCellOrValueType(value))
1967
+ ? valueInvalid(valueId, value)
1968
+ : value;
1871
1969
  const addDefaultsToRow = (row, tableId, rowId) => {
1872
1970
  ifNotUndefined(
1873
- mapGet(schemaRowCache, tableId),
1971
+ mapGet(tablesSchemaRowCache, tableId),
1874
1972
  ([rowDefaulted, rowNonDefaulted]) => {
1875
1973
  collForEach(rowDefaulted, (cell, cellId) => {
1876
1974
  if (!objHas(row, cellId)) {
@@ -1886,15 +1984,30 @@ const createStore = () => {
1886
1984
  );
1887
1985
  return row;
1888
1986
  };
1889
- const setValidSchema = (schema) =>
1987
+ const addDefaultsToValues = (values) => {
1988
+ if (hasValuesSchema) {
1989
+ collForEach(valuesDefaulted, (value, valueId) => {
1990
+ if (!objHas(values, valueId)) {
1991
+ values[valueId] = value;
1992
+ }
1993
+ });
1994
+ collForEach(valuesNonDefaulted, (valueId) => {
1995
+ if (!objHas(values, valueId)) {
1996
+ valueInvalid(valueId);
1997
+ }
1998
+ });
1999
+ }
2000
+ return values;
2001
+ };
2002
+ const setValidTablesSchema = (tablesSchema) =>
1890
2003
  transformMap(
1891
- schemaMap,
1892
- schema,
1893
- (_schema, tableId, tableSchema) => {
2004
+ tablesSchemaMap,
2005
+ tablesSchema,
2006
+ (_tablesSchema, tableId, tableSchema) => {
1894
2007
  const rowDefaulted = mapNew();
1895
2008
  const rowNonDefaulted = setNew();
1896
2009
  transformMap(
1897
- mapEnsure(schemaMap, tableId, mapNew),
2010
+ mapEnsure(tablesSchemaMap, tableId, mapNew),
1898
2011
  tableSchema,
1899
2012
  (tableSchemaMap, cellId, cellSchema) => {
1900
2013
  mapSet(tableSchemaMap, cellId, cellSchema);
@@ -1905,13 +2018,33 @@ const createStore = () => {
1905
2018
  );
1906
2019
  },
1907
2020
  );
1908
- mapSet(schemaRowCache, tableId, [rowDefaulted, rowNonDefaulted]);
2021
+ mapSet(tablesSchemaRowCache, tableId, [rowDefaulted, rowNonDefaulted]);
1909
2022
  },
1910
- (_schema, tableId) => {
1911
- mapSet(schemaMap, tableId);
1912
- mapSet(schemaRowCache, tableId);
2023
+ (_tablesSchema, tableId) => {
2024
+ mapSet(tablesSchemaMap, tableId);
2025
+ mapSet(tablesSchemaRowCache, tableId);
1913
2026
  },
1914
2027
  );
2028
+ const setValidValuesSchema = (valuesSchema) =>
2029
+ transformMap(
2030
+ valuesSchemaMap,
2031
+ valuesSchema,
2032
+ (_valuesSchema, valueId, valueSchema) => {
2033
+ mapSet(valuesSchemaMap, valueId, valueSchema);
2034
+ ifNotUndefined(
2035
+ valueSchema[DEFAULT],
2036
+ (def) => mapSet(valuesDefaulted, valueId, def),
2037
+ () => setAdd(valuesNonDefaulted, valueId),
2038
+ );
2039
+ },
2040
+ (_valuesSchema, valueId) => {
2041
+ mapSet(valuesSchemaMap, valueId);
2042
+ mapSet(valuesDefaulted, valueId);
2043
+ collDel(valuesNonDefaulted, valueId);
2044
+ },
2045
+ );
2046
+ const setOrDelTables = (tables) =>
2047
+ objIsEmpty(tables) ? delTables() : setTables(tables);
1915
2048
  const setValidTables = (tables) =>
1916
2049
  transformMap(
1917
2050
  tablesMap,
@@ -1929,26 +2062,26 @@ const createStore = () => {
1929
2062
  (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
1930
2063
  (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
1931
2064
  );
1932
- const setValidRow = (tableId, tableMap, rowId, newRow, forceDel) =>
2065
+ const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
1933
2066
  transformMap(
1934
2067
  mapEnsure(tableMap, rowId, () => {
1935
2068
  rowIdsChanged(tableId, rowId, 1);
1936
2069
  return mapNew();
1937
2070
  }),
1938
- newRow,
2071
+ row,
1939
2072
  (rowMap, cellId, cell) =>
1940
2073
  setValidCell(tableId, rowId, rowMap, cellId, cell),
1941
2074
  (rowMap, cellId) =>
1942
2075
  delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
1943
2076
  );
1944
- const setValidCell = (tableId, rowId, rowMap, cellId, newCell) => {
2077
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
1945
2078
  if (!collHas(rowMap, cellId)) {
1946
2079
  cellIdsChanged(tableId, rowId, cellId, 1);
1947
2080
  }
1948
2081
  const oldCell = mapGet(rowMap, cellId);
1949
- if (newCell !== oldCell) {
1950
- cellChanged(tableId, rowId, cellId, oldCell, newCell);
1951
- mapSet(rowMap, cellId, newCell);
2082
+ if (cell !== oldCell) {
2083
+ cellChanged(tableId, rowId, cellId, oldCell, cell);
2084
+ mapSet(rowMap, cellId, cell);
1952
2085
  }
1953
2086
  };
1954
2087
  const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
@@ -1963,6 +2096,25 @@ const createStore = () => {
1963
2096
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
1964
2097
  ),
1965
2098
  );
2099
+ const setOrDelValues = (values) =>
2100
+ objIsEmpty(values) ? delValues() : setValues(values);
2101
+ const setValidValues = (values) =>
2102
+ transformMap(
2103
+ valuesMap,
2104
+ values,
2105
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
2106
+ (_valuesMap, valueId) => delValidValue(valueId),
2107
+ );
2108
+ const setValidValue = (valueId, value) => {
2109
+ if (!collHas(valuesMap, valueId)) {
2110
+ valueIdsChanged(valueId, 1);
2111
+ }
2112
+ const oldValue = mapGet(valuesMap, valueId);
2113
+ if (value !== oldValue) {
2114
+ valueChanged(valueId, oldValue, value);
2115
+ mapSet(valuesMap, valueId, value);
2116
+ }
2117
+ };
1966
2118
  const getNewRowId = (tableId) => {
1967
2119
  const [getId] = mapEnsure(tablePoolFunctions, tableId, getPoolFunctions);
1968
2120
  const rowId = getId();
@@ -1984,7 +2136,10 @@ const createStore = () => {
1984
2136
  setValidRow(tableId, tableMap, rowId, {}, true);
1985
2137
  };
1986
2138
  const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
1987
- const defaultCell = mapGet(mapGet(schemaRowCache, tableId)?.[0], cellId);
2139
+ const defaultCell = mapGet(
2140
+ mapGet(tablesSchemaRowCache, tableId)?.[0],
2141
+ cellId,
2142
+ );
1988
2143
  if (!isUndefined(defaultCell) && !forceDel) {
1989
2144
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
1990
2145
  }
@@ -2003,6 +2158,15 @@ const createStore = () => {
2003
2158
  }
2004
2159
  }
2005
2160
  };
2161
+ const delValidValue = (valueId) => {
2162
+ const defaultValue = mapGet(valuesDefaulted, valueId);
2163
+ if (!isUndefined(defaultValue)) {
2164
+ return setValidValue(valueId, defaultValue);
2165
+ }
2166
+ valueChanged(valueId, mapGet(valuesMap, valueId));
2167
+ valueIdsChanged(valueId, -1);
2168
+ mapSet(valuesMap, valueId);
2169
+ };
2006
2170
  const tableIdsChanged = (tableId, added) =>
2007
2171
  idsChanged(changedTableIds, tableId, added);
2008
2172
  const rowIdsChanged = (tableId, rowId, added) =>
@@ -2019,6 +2183,10 @@ const createStore = () => {
2019
2183
  cellId,
2020
2184
  () => [oldCell, 0],
2021
2185
  )[1] = newCell);
2186
+ const valueIdsChanged = (valueId, added) =>
2187
+ idsChanged(changedValueIds, valueId, added);
2188
+ const valueChanged = (valueId, oldValue, newValue) =>
2189
+ (mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue);
2022
2190
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
2023
2191
  arrayPush(
2024
2192
  mapEnsure(
@@ -2030,12 +2198,25 @@ const createStore = () => {
2030
2198
  );
2031
2199
  return defaultedCell;
2032
2200
  };
2201
+ const valueInvalid = (valueId, invalidValue, defaultedValue) => {
2202
+ arrayPush(
2203
+ mapEnsure(invalidValues, valueId, () => []),
2204
+ invalidValue,
2205
+ );
2206
+ return defaultedValue;
2207
+ };
2033
2208
  const getCellChange = (tableId, rowId, cellId) =>
2034
2209
  ifNotUndefined(
2035
2210
  mapGet(mapGet(mapGet(changedCells, tableId), rowId), cellId),
2036
2211
  ([oldCell, newCell]) => [true, oldCell, newCell],
2037
2212
  () => [false, ...pairNew(getCell(tableId, rowId, cellId))],
2038
2213
  );
2214
+ const getValueChange = (valueId) =>
2215
+ ifNotUndefined(
2216
+ mapGet(changedValues, valueId),
2217
+ ([oldValue, newValue]) => [true, oldValue, newValue],
2218
+ () => [false, ...pairNew(getValue(valueId))],
2219
+ );
2039
2220
  const callInvalidCellListeners = (mutator) =>
2040
2221
  !collIsEmpty(invalidCells) && !collIsEmpty(invalidCellListeners[mutator])
2041
2222
  ? collForEach(
@@ -2052,13 +2233,25 @@ const createStore = () => {
2052
2233
  ),
2053
2234
  )
2054
2235
  : 0;
2236
+ const callInvalidValueListeners = (mutator) =>
2237
+ !collIsEmpty(invalidValues) && !collIsEmpty(invalidValueListeners[mutator])
2238
+ ? collForEach(
2239
+ mutator ? mapClone(invalidValues) : invalidValues,
2240
+ (invalidValue, valueId) =>
2241
+ callListeners(
2242
+ invalidValueListeners[mutator],
2243
+ [valueId],
2244
+ invalidValue,
2245
+ ),
2246
+ )
2247
+ : 0;
2055
2248
  const callIdsListenersIfChanged = (listeners, changedIds, ids) => {
2056
2249
  if (!collIsEmpty(changedIds)) {
2057
2250
  callListeners(listeners, ids);
2058
2251
  return 1;
2059
2252
  }
2060
2253
  };
2061
- const callListenersForChanges = (mutator) => {
2254
+ const callTabularListenersForChanges = (mutator) => {
2062
2255
  const emptySortedRowIdListeners = collIsEmpty(
2063
2256
  sortedRowIdsListeners[mutator],
2064
2257
  );
@@ -2160,6 +2353,38 @@ const createStore = () => {
2160
2353
  }
2161
2354
  }
2162
2355
  };
2356
+ const callKeyedValuesListenersForChanges = (mutator) => {
2357
+ const emptyIdListeners = collIsEmpty(valueIdsListeners[mutator]);
2358
+ const emptyOtherListeners =
2359
+ collIsEmpty(valueListeners[mutator]) &&
2360
+ collIsEmpty(valuesListeners[mutator]);
2361
+ if (!emptyIdListeners || !emptyOtherListeners) {
2362
+ const changes = mutator
2363
+ ? [mapClone(changedValueIds), mapClone(changedValues)]
2364
+ : [changedValueIds, changedValues];
2365
+ if (!emptyIdListeners) {
2366
+ callIdsListenersIfChanged(valueIdsListeners[mutator], changes[0]);
2367
+ }
2368
+ if (!emptyOtherListeners) {
2369
+ let valuesChanged;
2370
+ collForEach(changes[1], ([oldValue, newValue], valueId) => {
2371
+ if (newValue !== oldValue) {
2372
+ callListeners(
2373
+ valueListeners[mutator],
2374
+ [valueId],
2375
+ newValue,
2376
+ oldValue,
2377
+ getValueChange,
2378
+ );
2379
+ valuesChanged = 1;
2380
+ }
2381
+ });
2382
+ if (valuesChanged) {
2383
+ callListeners(valuesListeners[mutator], void 0, getValueChange);
2384
+ }
2385
+ }
2386
+ }
2387
+ };
2163
2388
  const fluentTransaction = (actions, ...args) => {
2164
2389
  transaction(() => actions(...arrayMap(args, id)));
2165
2390
  return store;
@@ -2192,14 +2417,23 @@ const createStore = () => {
2192
2417
  mapKeys(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
2193
2418
  const getCell = (tableId, rowId, cellId) =>
2194
2419
  mapGet(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
2420
+ const getValues = () => mapToObj(valuesMap);
2421
+ const getValueIds = () => mapKeys(valuesMap);
2422
+ const getValue = (valueId) => mapGet(valuesMap, id(valueId));
2195
2423
  const hasTables = () => !collIsEmpty(tablesMap);
2196
2424
  const hasTable = (tableId) => collHas(tablesMap, id(tableId));
2197
2425
  const hasRow = (tableId, rowId) =>
2198
2426
  collHas(mapGet(tablesMap, id(tableId)), id(rowId));
2199
2427
  const hasCell = (tableId, rowId, cellId) =>
2200
2428
  collHas(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), id(cellId));
2201
- const getJson = () => jsonString(tablesMap);
2202
- const getSchemaJson = () => jsonString(schemaMap);
2429
+ const hasValues = () => !collIsEmpty(valuesMap);
2430
+ const hasValue = (valueId) => collHas(valuesMap, id(valueId));
2431
+ const getTablesJson = () => jsonString(tablesMap);
2432
+ const getValuesJson = () => jsonString(valuesMap);
2433
+ const getJson = () => jsonString([tablesMap, valuesMap]);
2434
+ const getTablesSchemaJson = () => jsonString(tablesSchemaMap);
2435
+ const getValuesSchemaJson = () => jsonString(valuesSchemaMap);
2436
+ const getSchemaJson = () => jsonString([tablesSchemaMap, valuesSchemaMap]);
2203
2437
  const setTables = (tables) =>
2204
2438
  fluentTransaction(() =>
2205
2439
  validateTables(tables) ? setValidTables(tables) : 0,
@@ -2213,13 +2447,8 @@ const createStore = () => {
2213
2447
  const setRow = (tableId, rowId, row) =>
2214
2448
  fluentTransaction(
2215
2449
  (tableId2, rowId2) =>
2216
- validateRow(id(tableId2), id(rowId2), row)
2217
- ? setValidRow(
2218
- id(tableId2),
2219
- getOrCreateTable(id(tableId2)),
2220
- id(rowId2),
2221
- row,
2222
- )
2450
+ validateRow(tableId2, rowId2, row)
2451
+ ? setValidRow(tableId2, getOrCreateTable(tableId2), rowId2, row)
2223
2452
  : 0,
2224
2453
  tableId,
2225
2454
  rowId,
@@ -2274,16 +2503,56 @@ const createStore = () => {
2274
2503
  rowId,
2275
2504
  cellId,
2276
2505
  );
2277
- const setJson = (json) => {
2506
+ const setValues = (values) =>
2507
+ fluentTransaction(() =>
2508
+ validateValues(values) ? setValidValues(values) : 0,
2509
+ );
2510
+ const setPartialValues = (partialValues) =>
2511
+ fluentTransaction(() =>
2512
+ validateValues(partialValues, 1)
2513
+ ? objMap(partialValues, (value, valueId) =>
2514
+ setValidValue(valueId, value),
2515
+ )
2516
+ : 0,
2517
+ );
2518
+ const setValue = (valueId, value) =>
2519
+ fluentTransaction(
2520
+ (valueId2) =>
2521
+ ifNotUndefined(
2522
+ getValidatedValue(
2523
+ valueId2,
2524
+ isFunction(value) ? value(getValue(valueId2)) : value,
2525
+ ),
2526
+ (validValue) => setValidValue(valueId2, validValue),
2527
+ ),
2528
+ valueId,
2529
+ );
2530
+ const setTablesJson = (tablesJson) => {
2531
+ try {
2532
+ setOrDelTables(jsonParse(tablesJson));
2533
+ } catch {}
2534
+ return store;
2535
+ };
2536
+ const setValuesJson = (valuesJson) => {
2278
2537
  try {
2279
- json === EMPTY_OBJECT ? delTables() : setTables(jsonParse(json));
2538
+ setOrDelValues(jsonParse(valuesJson));
2280
2539
  } catch {}
2281
2540
  return store;
2282
2541
  };
2283
- const setSchema = (schema) =>
2542
+ const setJson = (tablesAndValuesJson) => {
2543
+ try {
2544
+ const [tables, values] = jsonParse(tablesAndValuesJson);
2545
+ setOrDelTables(tables);
2546
+ setOrDelValues(values);
2547
+ } catch {
2548
+ setTablesJson(tablesAndValuesJson);
2549
+ }
2550
+ return store;
2551
+ };
2552
+ const setTablesSchema = (tablesSchema) =>
2284
2553
  fluentTransaction(() => {
2285
- if ((hasSchema = validateSchema(schema))) {
2286
- setValidSchema(schema);
2554
+ if ((hasTablesSchema = validateTablesSchema(tablesSchema))) {
2555
+ setValidTablesSchema(tablesSchema);
2287
2556
  if (!collIsEmpty(tablesMap)) {
2288
2557
  const tables = getTables();
2289
2558
  delTables();
@@ -2291,6 +2560,22 @@ const createStore = () => {
2291
2560
  }
2292
2561
  }
2293
2562
  });
2563
+ const setValuesSchema = (valuesSchema) =>
2564
+ fluentTransaction(() => {
2565
+ if ((hasValuesSchema = validateValuesSchema(valuesSchema))) {
2566
+ const values = getValues();
2567
+ delValuesSchema();
2568
+ delValues();
2569
+ hasValuesSchema = true;
2570
+ setValidValuesSchema(valuesSchema);
2571
+ setValues(values);
2572
+ }
2573
+ });
2574
+ const setSchema = (tablesSchema, valuesSchema) =>
2575
+ fluentTransaction(() => {
2576
+ setTablesSchema(tablesSchema);
2577
+ setValuesSchema(valuesSchema);
2578
+ });
2294
2579
  const delTables = () => fluentTransaction(() => setValidTables({}));
2295
2580
  const delTable = (tableId) =>
2296
2581
  fluentTransaction(
@@ -2330,10 +2615,27 @@ const createStore = () => {
2330
2615
  rowId,
2331
2616
  cellId,
2332
2617
  );
2618
+ const delValues = () => fluentTransaction(() => setValidValues({}));
2619
+ const delValue = (valueId) =>
2620
+ fluentTransaction(
2621
+ (valueId2) =>
2622
+ collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
2623
+ valueId,
2624
+ );
2625
+ const delTablesSchema = () =>
2626
+ fluentTransaction(() => {
2627
+ setValidTablesSchema({});
2628
+ hasTablesSchema = false;
2629
+ });
2630
+ const delValuesSchema = () =>
2631
+ fluentTransaction(() => {
2632
+ setValidValuesSchema({});
2633
+ hasValuesSchema = false;
2634
+ });
2333
2635
  const delSchema = () =>
2334
2636
  fluentTransaction(() => {
2335
- setValidSchema({});
2336
- hasSchema = false;
2637
+ delTablesSchema();
2638
+ delValuesSchema();
2337
2639
  });
2338
2640
  const transaction = (actions, doRollback) => {
2339
2641
  if (transactions == -1) {
@@ -2353,10 +2655,15 @@ const createStore = () => {
2353
2655
  transactions--;
2354
2656
  if (transactions == 0) {
2355
2657
  cellsTouched = !collIsEmpty(changedCells);
2658
+ valuesTouched = !collIsEmpty(changedValues);
2356
2659
  transactions = 1;
2357
2660
  callInvalidCellListeners(1);
2358
2661
  if (cellsTouched) {
2359
- callListenersForChanges(1);
2662
+ callTabularListenersForChanges(1);
2663
+ }
2664
+ callInvalidValueListeners(1);
2665
+ if (valuesTouched) {
2666
+ callKeyedValuesListenersForChanges(1);
2360
2667
  }
2361
2668
  transactions = -1;
2362
2669
  if (
@@ -2377,6 +2684,12 @@ const createStore = () => {
2377
2684
  objIsEmpty,
2378
2685
  ),
2379
2686
  mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
2687
+ mapToObj(
2688
+ changedValues,
2689
+ (values) => [...values],
2690
+ ([oldValue, newValue]) => oldValue === newValue,
2691
+ ),
2692
+ mapToObj(invalidValues),
2380
2693
  )
2381
2694
  ) {
2382
2695
  transactions = 1;
@@ -2387,23 +2700,43 @@ const createStore = () => {
2387
2700
  ),
2388
2701
  ),
2389
2702
  );
2703
+ collForEach(changedValues, ([oldValue], valueId) =>
2704
+ setOrDelValue(store, valueId, oldValue),
2705
+ );
2390
2706
  transactions = -1;
2391
- cellsTouched = false;
2707
+ cellsTouched = valuesTouched = false;
2392
2708
  }
2393
- callListeners(finishTransactionListeners[0], void 0, cellsTouched);
2709
+ callListeners(
2710
+ finishTransactionListeners[0],
2711
+ void 0,
2712
+ cellsTouched,
2713
+ valuesTouched,
2714
+ );
2394
2715
  callInvalidCellListeners(0);
2395
2716
  if (cellsTouched) {
2396
- callListenersForChanges(0);
2717
+ callTabularListenersForChanges(0);
2718
+ }
2719
+ callInvalidValueListeners(0);
2720
+ if (valuesTouched) {
2721
+ callKeyedValuesListenersForChanges(0);
2397
2722
  }
2398
- callListeners(finishTransactionListeners[1], void 0, cellsTouched);
2723
+ callListeners(
2724
+ finishTransactionListeners[1],
2725
+ void 0,
2726
+ cellsTouched,
2727
+ valuesTouched,
2728
+ );
2399
2729
  transactions = 0;
2400
2730
  arrayForEach(
2401
2731
  [
2402
- changedCells,
2403
- invalidCells,
2404
2732
  changedTableIds,
2405
2733
  changedRowIds,
2406
2734
  changedCellIds,
2735
+ changedCells,
2736
+ invalidCells,
2737
+ changedValueIds,
2738
+ changedValues,
2739
+ invalidValues,
2407
2740
  ],
2408
2741
  collClear,
2409
2742
  );
@@ -2427,6 +2760,7 @@ const createStore = () => {
2427
2760
  );
2428
2761
  const forEachCell = (tableId, rowId, cellCallback) =>
2429
2762
  mapForEach(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), cellCallback);
2763
+ const forEachValue = (valueCallback) => mapForEach(valuesMap, valueCallback);
2430
2764
  const addSortedRowIdsListener = (
2431
2765
  tableId,
2432
2766
  cellId,
@@ -2467,6 +2801,7 @@ const createStore = () => {
2467
2801
  },
2468
2802
  sortedRowIdsListeners[mutator ? 1 : 0],
2469
2803
  [tableId, cellId],
2804
+ [getTableIds],
2470
2805
  );
2471
2806
  };
2472
2807
  const addWillFinishTransactionListener = (listener) =>
@@ -2474,9 +2809,7 @@ const createStore = () => {
2474
2809
  const addDidFinishTransactionListener = (listener) =>
2475
2810
  addListener(listener, finishTransactionListeners[1]);
2476
2811
  const callListener = (listenerId) => {
2477
- callListenerImpl(listenerId, [getTableIds, getRowIds, getCellIds], (ids) =>
2478
- isUndefined(ids[2]) ? [] : pairNew(getCell(...ids)),
2479
- );
2812
+ callListenerImpl(listenerId);
2480
2813
  return store;
2481
2814
  };
2482
2815
  const delListener = (listenerId) => {
@@ -2493,6 +2826,10 @@ const createStore = () => {
2493
2826
  cellIds: pairCollSize2(cellIdsListeners, collSize3),
2494
2827
  cell: pairCollSize2(cellListeners, collSize4),
2495
2828
  invalidCell: pairCollSize2(invalidCellListeners, collSize4),
2829
+ values: pairCollSize2(valuesListeners),
2830
+ valueIds: pairCollSize2(valueIdsListeners),
2831
+ value: pairCollSize2(valueListeners),
2832
+ invalidValue: pairCollSize2(invalidValueListeners),
2496
2833
  transaction: pairCollSize2(finishTransactionListeners),
2497
2834
  });
2498
2835
  const store = {
@@ -2504,11 +2841,20 @@ const createStore = () => {
2504
2841
  getRow,
2505
2842
  getCellIds,
2506
2843
  getCell,
2844
+ getValues,
2845
+ getValueIds,
2846
+ getValue,
2507
2847
  hasTables,
2508
2848
  hasTable,
2509
2849
  hasRow,
2510
2850
  hasCell,
2851
+ hasValues,
2852
+ hasValue,
2853
+ getTablesJson,
2854
+ getValuesJson,
2511
2855
  getJson,
2856
+ getTablesSchemaJson,
2857
+ getValuesSchemaJson,
2512
2858
  getSchemaJson,
2513
2859
  setTables,
2514
2860
  setTable,
@@ -2516,12 +2862,23 @@ const createStore = () => {
2516
2862
  addRow,
2517
2863
  setPartialRow,
2518
2864
  setCell,
2865
+ setValues,
2866
+ setPartialValues,
2867
+ setValue,
2868
+ setTablesJson,
2869
+ setValuesJson,
2519
2870
  setJson,
2871
+ setTablesSchema,
2872
+ setValuesSchema,
2520
2873
  setSchema,
2521
2874
  delTables,
2522
2875
  delTable,
2523
2876
  delRow,
2524
2877
  delCell,
2878
+ delValues,
2879
+ delValue,
2880
+ delTablesSchema,
2881
+ delValuesSchema,
2525
2882
  delSchema,
2526
2883
  transaction,
2527
2884
  startTransaction,
@@ -2529,6 +2886,7 @@ const createStore = () => {
2529
2886
  forEachTable,
2530
2887
  forEachRow,
2531
2888
  forEachCell,
2889
+ forEachValue,
2532
2890
  addSortedRowIdsListener,
2533
2891
  addWillFinishTransactionListener,
2534
2892
  addDidFinishTransactionListener,
@@ -2541,19 +2899,35 @@ const createStore = () => {
2541
2899
  {
2542
2900
  [TABLES]: [0, tablesListeners],
2543
2901
  [TABLE_IDS]: [0, tableIdsListeners],
2544
- [TABLE]: [1, tableListeners],
2545
- [ROW_IDS]: [1, rowIdsListeners],
2546
- [ROW]: [2, rowListeners],
2547
- [CELL_IDS]: [2, cellIdsListeners],
2548
- [CELL]: [3, cellListeners],
2902
+ [TABLE]: [1, tableListeners, [getTableIds]],
2903
+ [ROW_IDS]: [1, rowIdsListeners, [getTableIds]],
2904
+ [ROW]: [2, rowListeners, [getTableIds, getRowIds]],
2905
+ [CELL_IDS]: [2, cellIdsListeners, [getTableIds, getRowIds]],
2906
+ [CELL]: [
2907
+ 3,
2908
+ cellListeners,
2909
+ [getTableIds, getRowIds, getCellIds],
2910
+ (ids) => pairNew(getCell(...ids)),
2911
+ ],
2549
2912
  InvalidCell: [3, invalidCellListeners],
2913
+ [VALUES]: [0, valuesListeners],
2914
+ [VALUE_IDS]: [0, valueIdsListeners],
2915
+ [VALUE]: [
2916
+ 1,
2917
+ valueListeners,
2918
+ [getValueIds],
2919
+ (ids) => pairNew(getValue(ids[0])),
2920
+ ],
2921
+ InvalidValue: [1, invalidValueListeners],
2550
2922
  },
2551
- ([argumentCount, idSetNode], listenable) => {
2923
+ ([argumentCount, idSetNode, pathGetters, extraArgsGetter], listenable) => {
2552
2924
  store[ADD + listenable + LISTENER] = (...args) =>
2553
2925
  addListener(
2554
2926
  args[argumentCount],
2555
2927
  idSetNode[args[argumentCount + 1] ? 1 : 0],
2556
2928
  argumentCount > 0 ? arraySlice(args, 0, argumentCount) : void 0,
2929
+ pathGetters,
2930
+ extraArgsGetter,
2557
2931
  );
2558
2932
  },
2559
2933
  );