tinybase 2.2.6 → 3.0.0-beta.1

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 +2022 -383
  14. package/lib/debug/store.js +440 -108
  15. package/lib/debug/tinybase.js +508 -140
  16. package/lib/debug/tools.d.ts +89 -38
  17. package/lib/debug/tools.js +757 -453
  18. package/lib/debug/ui-react.d.ts +1525 -381
  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 +2022 -383
  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 +89 -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 +1525 -381
  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 +2022 -383
  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 +89 -38
  58. package/lib/tools.js +1 -1
  59. package/lib/tools.js.gz +0 -0
  60. package/lib/ui-react.d.ts +1525 -381
  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 +2022 -383
  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 +89 -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 +1525 -381
  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 +2022 -383
  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 +89 -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 +1525 -381
  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 +26 -26
  110. package/readme.md +20 -19
@@ -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]);
2022
+ },
2023
+ (_tablesSchema, tableId) => {
2024
+ mapSet(tablesSchemaMap, tableId);
2025
+ mapSet(tablesSchemaRowCache, tableId);
2026
+ },
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
+ );
1909
2039
  },
1910
- (_schema, tableId) => {
1911
- mapSet(schemaMap, tableId);
1912
- mapSet(schemaRowCache, tableId);
2040
+ (_valuesSchema, valueId) => {
2041
+ mapSet(valuesSchemaMap, valueId);
2042
+ mapSet(valuesDefaulted, valueId);
2043
+ collDel(valuesNonDefaulted, valueId);
1913
2044
  },
1914
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,22 @@ const createStore = () => {
2330
2615
  rowId,
2331
2616
  cellId,
2332
2617
  );
2333
- const delSchema = () =>
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 = () =>
2334
2631
  fluentTransaction(() => {
2335
- setValidSchema({});
2336
- hasSchema = false;
2632
+ setValidValuesSchema({});
2633
+ hasValuesSchema = false;
2337
2634
  });
2338
2635
  const transaction = (actions, doRollback) => {
2339
2636
  if (transactions == -1) {
@@ -2353,10 +2650,15 @@ const createStore = () => {
2353
2650
  transactions--;
2354
2651
  if (transactions == 0) {
2355
2652
  cellsTouched = !collIsEmpty(changedCells);
2653
+ valuesTouched = !collIsEmpty(changedValues);
2356
2654
  transactions = 1;
2357
2655
  callInvalidCellListeners(1);
2358
2656
  if (cellsTouched) {
2359
- callListenersForChanges(1);
2657
+ callTabularListenersForChanges(1);
2658
+ }
2659
+ callInvalidValueListeners(1);
2660
+ if (valuesTouched) {
2661
+ callKeyedValuesListenersForChanges(1);
2360
2662
  }
2361
2663
  transactions = -1;
2362
2664
  if (
@@ -2377,6 +2679,12 @@ const createStore = () => {
2377
2679
  objIsEmpty,
2378
2680
  ),
2379
2681
  mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
2682
+ mapToObj(
2683
+ changedValues,
2684
+ (values) => [...values],
2685
+ ([oldValue, newValue]) => oldValue === newValue,
2686
+ ),
2687
+ mapToObj(invalidValues),
2380
2688
  )
2381
2689
  ) {
2382
2690
  transactions = 1;
@@ -2387,23 +2695,43 @@ const createStore = () => {
2387
2695
  ),
2388
2696
  ),
2389
2697
  );
2698
+ collForEach(changedValues, ([oldValue], valueId) =>
2699
+ setOrDelValue(store, valueId, oldValue),
2700
+ );
2390
2701
  transactions = -1;
2391
- cellsTouched = false;
2702
+ cellsTouched = valuesTouched = false;
2392
2703
  }
2393
- callListeners(finishTransactionListeners[0], void 0, cellsTouched);
2704
+ callListeners(
2705
+ finishTransactionListeners[0],
2706
+ void 0,
2707
+ cellsTouched,
2708
+ valuesTouched,
2709
+ );
2394
2710
  callInvalidCellListeners(0);
2395
2711
  if (cellsTouched) {
2396
- callListenersForChanges(0);
2712
+ callTabularListenersForChanges(0);
2713
+ }
2714
+ callInvalidValueListeners(0);
2715
+ if (valuesTouched) {
2716
+ callKeyedValuesListenersForChanges(0);
2397
2717
  }
2398
- callListeners(finishTransactionListeners[1], void 0, cellsTouched);
2718
+ callListeners(
2719
+ finishTransactionListeners[1],
2720
+ void 0,
2721
+ cellsTouched,
2722
+ valuesTouched,
2723
+ );
2399
2724
  transactions = 0;
2400
2725
  arrayForEach(
2401
2726
  [
2402
- changedCells,
2403
- invalidCells,
2404
2727
  changedTableIds,
2405
2728
  changedRowIds,
2406
2729
  changedCellIds,
2730
+ changedCells,
2731
+ invalidCells,
2732
+ changedValueIds,
2733
+ changedValues,
2734
+ invalidValues,
2407
2735
  ],
2408
2736
  collClear,
2409
2737
  );
@@ -2427,6 +2755,7 @@ const createStore = () => {
2427
2755
  );
2428
2756
  const forEachCell = (tableId, rowId, cellCallback) =>
2429
2757
  mapForEach(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)), cellCallback);
2758
+ const forEachValue = (valueCallback) => mapForEach(valuesMap, valueCallback);
2430
2759
  const addSortedRowIdsListener = (
2431
2760
  tableId,
2432
2761
  cellId,
@@ -2467,6 +2796,7 @@ const createStore = () => {
2467
2796
  },
2468
2797
  sortedRowIdsListeners[mutator ? 1 : 0],
2469
2798
  [tableId, cellId],
2799
+ [getTableIds],
2470
2800
  );
2471
2801
  };
2472
2802
  const addWillFinishTransactionListener = (listener) =>
@@ -2474,9 +2804,7 @@ const createStore = () => {
2474
2804
  const addDidFinishTransactionListener = (listener) =>
2475
2805
  addListener(listener, finishTransactionListeners[1]);
2476
2806
  const callListener = (listenerId) => {
2477
- callListenerImpl(listenerId, [getTableIds, getRowIds, getCellIds], (ids) =>
2478
- isUndefined(ids[2]) ? [] : pairNew(getCell(...ids)),
2479
- );
2807
+ callListenerImpl(listenerId);
2480
2808
  return store;
2481
2809
  };
2482
2810
  const delListener = (listenerId) => {
@@ -2493,6 +2821,10 @@ const createStore = () => {
2493
2821
  cellIds: pairCollSize2(cellIdsListeners, collSize3),
2494
2822
  cell: pairCollSize2(cellListeners, collSize4),
2495
2823
  invalidCell: pairCollSize2(invalidCellListeners, collSize4),
2824
+ values: pairCollSize2(valuesListeners),
2825
+ valueIds: pairCollSize2(valueIdsListeners),
2826
+ value: pairCollSize2(valueListeners),
2827
+ invalidValue: pairCollSize2(invalidValueListeners),
2496
2828
  transaction: pairCollSize2(finishTransactionListeners),
2497
2829
  });
2498
2830
  const store = {
@@ -2504,11 +2836,20 @@ const createStore = () => {
2504
2836
  getRow,
2505
2837
  getCellIds,
2506
2838
  getCell,
2839
+ getValues,
2840
+ getValueIds,
2841
+ getValue,
2507
2842
  hasTables,
2508
2843
  hasTable,
2509
2844
  hasRow,
2510
2845
  hasCell,
2846
+ hasValues,
2847
+ hasValue,
2848
+ getTablesJson,
2849
+ getValuesJson,
2511
2850
  getJson,
2851
+ getTablesSchemaJson,
2852
+ getValuesSchemaJson,
2512
2853
  getSchemaJson,
2513
2854
  setTables,
2514
2855
  setTable,
@@ -2516,19 +2857,30 @@ const createStore = () => {
2516
2857
  addRow,
2517
2858
  setPartialRow,
2518
2859
  setCell,
2860
+ setValues,
2861
+ setPartialValues,
2862
+ setValue,
2863
+ setTablesJson,
2864
+ setValuesJson,
2519
2865
  setJson,
2866
+ setTablesSchema,
2867
+ setValuesSchema,
2520
2868
  setSchema,
2521
2869
  delTables,
2522
2870
  delTable,
2523
2871
  delRow,
2524
2872
  delCell,
2525
- delSchema,
2873
+ delValues,
2874
+ delValue,
2875
+ delTablesSchema,
2876
+ delValuesSchema,
2526
2877
  transaction,
2527
2878
  startTransaction,
2528
2879
  finishTransaction,
2529
2880
  forEachTable,
2530
2881
  forEachRow,
2531
2882
  forEachCell,
2883
+ forEachValue,
2532
2884
  addSortedRowIdsListener,
2533
2885
  addWillFinishTransactionListener,
2534
2886
  addDidFinishTransactionListener,
@@ -2541,19 +2893,35 @@ const createStore = () => {
2541
2893
  {
2542
2894
  [TABLES]: [0, tablesListeners],
2543
2895
  [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],
2896
+ [TABLE]: [1, tableListeners, [getTableIds]],
2897
+ [ROW_IDS]: [1, rowIdsListeners, [getTableIds]],
2898
+ [ROW]: [2, rowListeners, [getTableIds, getRowIds]],
2899
+ [CELL_IDS]: [2, cellIdsListeners, [getTableIds, getRowIds]],
2900
+ [CELL]: [
2901
+ 3,
2902
+ cellListeners,
2903
+ [getTableIds, getRowIds, getCellIds],
2904
+ (ids) => pairNew(getCell(...ids)),
2905
+ ],
2549
2906
  InvalidCell: [3, invalidCellListeners],
2907
+ [VALUES]: [0, valuesListeners],
2908
+ [VALUE_IDS]: [0, valueIdsListeners],
2909
+ [VALUE]: [
2910
+ 1,
2911
+ valueListeners,
2912
+ [getValueIds],
2913
+ (ids) => pairNew(getValue(ids[0])),
2914
+ ],
2915
+ InvalidValue: [1, invalidValueListeners],
2550
2916
  },
2551
- ([argumentCount, idSetNode], listenable) => {
2917
+ ([argumentCount, idSetNode, pathGetters, extraArgsGetter], listenable) => {
2552
2918
  store[ADD + listenable + LISTENER] = (...args) =>
2553
2919
  addListener(
2554
2920
  args[argumentCount],
2555
2921
  idSetNode[args[argumentCount + 1] ? 1 : 0],
2556
2922
  argumentCount > 0 ? arraySlice(args, 0, argumentCount) : void 0,
2923
+ pathGetters,
2924
+ extraArgsGetter,
2557
2925
  );
2558
2926
  },
2559
2927
  );