tinybase 1.3.6 → 2.0.0-beta.2

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 (61) hide show
  1. package/lib/checkpoints.d.ts +4 -3
  2. package/lib/checkpoints.js +1 -1
  3. package/lib/checkpoints.js.gz +0 -0
  4. package/lib/debug/checkpoints.d.ts +4 -3
  5. package/lib/debug/checkpoints.js +69 -56
  6. package/lib/debug/indexes.d.ts +4 -2
  7. package/lib/debug/indexes.js +106 -69
  8. package/lib/debug/metrics.d.ts +1 -1
  9. package/lib/debug/metrics.js +187 -131
  10. package/lib/debug/persisters.d.ts +6 -0
  11. package/lib/debug/persisters.js +2 -1
  12. package/lib/debug/queries.d.ts +3251 -0
  13. package/lib/debug/queries.js +900 -0
  14. package/lib/debug/relationships.d.ts +12 -10
  15. package/lib/debug/relationships.js +104 -68
  16. package/lib/debug/store.d.ts +415 -74
  17. package/lib/debug/store.js +295 -120
  18. package/lib/debug/tinybase.d.ts +1 -0
  19. package/lib/debug/tinybase.js +985 -176
  20. package/lib/debug/ui-react.d.ts +4325 -1754
  21. package/lib/debug/ui-react.js +413 -85
  22. package/lib/indexes.d.ts +4 -2
  23. package/lib/indexes.js +1 -1
  24. package/lib/indexes.js.gz +0 -0
  25. package/lib/metrics.d.ts +1 -1
  26. package/lib/metrics.js +1 -1
  27. package/lib/metrics.js.gz +0 -0
  28. package/lib/persisters.d.ts +6 -0
  29. package/lib/queries.d.ts +3251 -0
  30. package/lib/queries.js +1 -0
  31. package/lib/queries.js.gz +0 -0
  32. package/lib/relationships.d.ts +12 -10
  33. package/lib/relationships.js +1 -1
  34. package/lib/relationships.js.gz +0 -0
  35. package/lib/store.d.ts +415 -74
  36. package/lib/store.js +1 -1
  37. package/lib/store.js.gz +0 -0
  38. package/lib/tinybase.d.ts +1 -0
  39. package/lib/tinybase.js +1 -1
  40. package/lib/tinybase.js.gz +0 -0
  41. package/lib/ui-react.d.ts +4325 -1754
  42. package/lib/ui-react.js +1 -1
  43. package/lib/ui-react.js.gz +0 -0
  44. package/lib/umd/checkpoints.js +1 -1
  45. package/lib/umd/checkpoints.js.gz +0 -0
  46. package/lib/umd/indexes.js +1 -1
  47. package/lib/umd/indexes.js.gz +0 -0
  48. package/lib/umd/metrics.js +1 -1
  49. package/lib/umd/metrics.js.gz +0 -0
  50. package/lib/umd/queries.js +1 -0
  51. package/lib/umd/queries.js.gz +0 -0
  52. package/lib/umd/relationships.js +1 -1
  53. package/lib/umd/relationships.js.gz +0 -0
  54. package/lib/umd/store.js +1 -1
  55. package/lib/umd/store.js.gz +0 -0
  56. package/lib/umd/tinybase.js +1 -1
  57. package/lib/umd/tinybase.js.gz +0 -0
  58. package/lib/umd/ui-react.js +1 -1
  59. package/lib/umd/ui-react.js.gz +0 -0
  60. package/package.json +4 -4
  61. package/readme.md +2 -2
@@ -137,17 +137,18 @@ export type LinkedRowIdsListener = (
137
137
  */
138
138
  export type RelationshipsListenerStats = {
139
139
  /**
140
- * The number of RemoteRowIdListeners registered with the Relationships
141
- * object.
140
+ * The number of RemoteRowIdListener functions registered with the
141
+ * Relationships object.
142
142
  */
143
143
  remoteRowId?: number;
144
144
  /**
145
- * The number of LocalRowIdsListeners registered with the Relationships
146
- * object.
145
+ * The number of LocalRowIdsListener functions registered with the
146
+ * Relationships object.
147
147
  */
148
148
  localRowIds?: number;
149
149
  /**
150
- * The number of LinkedRowIds registered with the Relationships object.
150
+ * The number of LinkedRowId functions registered with the Relationships
151
+ * object.
151
152
  */
152
153
  linkedRowIds?: number;
153
154
  };
@@ -190,6 +191,7 @@ export type RelationshipsListenerStats = {
190
191
  * });
191
192
  *
192
193
  * const relationships = createRelationships(store);
194
+ *
193
195
  * // A local/remote table relationship:
194
196
  * relationships.setRelationshipDefinition(
195
197
  * 'petSpecies', // relationshipId
@@ -197,6 +199,11 @@ export type RelationshipsListenerStats = {
197
199
  * 'species', // remoteTableId to link to
198
200
  * 'species', // cellId containing remote key
199
201
  * );
202
+ * console.log(relationships.getRemoteRowId('petSpecies', 'fido'));
203
+ * // -> 'dog'
204
+ * console.log(relationships.getLocalRowIds('petSpecies', 'dog'));
205
+ * // -> ['fido', 'cujo']
206
+ *
200
207
  * // A linked list relationship:
201
208
  * relationships.setRelationshipDefinition(
202
209
  * 'petSequence', // relationshipId
@@ -204,11 +211,6 @@ export type RelationshipsListenerStats = {
204
211
  * 'pets', // the same remoteTableId to link within
205
212
  * 'next', // cellId containing link key
206
213
  * );
207
- *
208
- * console.log(relationships.getRemoteRowId('petSpecies', 'fido'));
209
- * // -> 'dog'
210
- * console.log(relationships.getLocalRowIds('petSpecies', 'dog'));
211
- * // -> ['fido', 'cujo']
212
214
  * console.log(relationships.getLinkedRowIds('petSequence', 'fido'));
213
215
  * // -> ['fido', 'felix', 'cujo']
214
216
  *
@@ -2,12 +2,12 @@ const getTypeOf = (thing) => typeof thing;
2
2
  const EMPTY_STRING = '';
3
3
  const STRING = getTypeOf(EMPTY_STRING);
4
4
 
5
+ const arrayEvery = (array, cb) => array.every(cb);
5
6
  const arrayForEach = (array, cb) => array.forEach(cb);
6
7
  const arrayLength = (array) => array.length;
7
8
  const arrayIsEmpty = (array) => arrayLength(array) == 0;
8
9
  const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
9
- const arrayFromSecond = (ids) => ids.slice(1);
10
- const arrayPush = (array, value) => array.push(value);
10
+ const arrayPush = (array, ...values) => array.push(...values);
11
11
  const arrayPop = (array) => array.pop();
12
12
 
13
13
  const isUndefined = (thing) => thing == void 0;
@@ -40,6 +40,27 @@ const mapEnsure = (map, key, getDefaultValue) => {
40
40
  }
41
41
  return mapGet(map, key);
42
42
  };
43
+ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
44
+ ifNotUndefined(
45
+ (ensureLeaf ? mapEnsure : mapGet)(
46
+ node,
47
+ path[p],
48
+ p > arrayLength(path) - 2 ? ensureLeaf : mapNew,
49
+ ),
50
+ (nodeOrLeaf) => {
51
+ if (p > arrayLength(path) - 2) {
52
+ if (pruneLeaf?.(nodeOrLeaf)) {
53
+ mapSet(node, path[p]);
54
+ }
55
+ return nodeOrLeaf;
56
+ }
57
+ const leaf = visitTree(nodeOrLeaf, path, ensureLeaf, pruneLeaf, p + 1);
58
+ if (collIsEmpty(nodeOrLeaf)) {
59
+ mapSet(node, path[p]);
60
+ }
61
+ return leaf;
62
+ },
63
+ );
43
64
 
44
65
  const setNew = (entries) => new Set(entries);
45
66
  const setAdd = (set, value) => set?.add(value);
@@ -58,20 +79,46 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
58
79
  const getTableId = (id) => mapGet(tableIds, id);
59
80
  const getThing = (id) => mapGet(things, id);
60
81
  const setThing = (id, thing) => mapSet(things, id, thing);
61
- const removeStoreListeners = (id) =>
62
- ifNotUndefined(mapGet(storeListenerIds, id), (listenerIds) => {
63
- collForEach(listenerIds, store.delListener);
64
- mapSet(storeListenerIds, id);
82
+ const addStoreListeners = (id, andCall, ...listenerIds) => {
83
+ const set = mapEnsure(storeListenerIds, id, setNew);
84
+ arrayForEach(
85
+ listenerIds,
86
+ (listenerId) =>
87
+ setAdd(set, listenerId) && andCall && store.callListener(listenerId),
88
+ );
89
+ return listenerIds;
90
+ };
91
+ const delStoreListeners = (id, ...listenerIds) =>
92
+ ifNotUndefined(mapGet(storeListenerIds, id), (allListenerIds) => {
93
+ arrayForEach(
94
+ arrayIsEmpty(listenerIds) ? collValues(allListenerIds) : listenerIds,
95
+ (listenerId) => {
96
+ store.delListener(listenerId);
97
+ collDel(allListenerIds, listenerId);
98
+ },
99
+ );
100
+ if (collIsEmpty(allListenerIds)) {
101
+ mapSet(storeListenerIds, id);
102
+ }
65
103
  });
66
- const setDefinition = (id, tableId, onChanged, getRowValue, getSortKey) => {
67
- const changedRowValues = mapNew();
68
- const changedSortKeys = mapNew();
104
+ const setDefinition = (id, tableId) => {
69
105
  mapSet(tableIds, id, tableId);
70
106
  if (!collHas(things, id)) {
71
107
  mapSet(things, id, getDefaultThing());
72
108
  mapSet(allRowValues, id, mapNew());
73
109
  mapSet(allSortKeys, id, mapNew());
74
110
  }
111
+ };
112
+ const setDefinitionAndListen = (
113
+ id,
114
+ tableId,
115
+ onChanged,
116
+ getRowValue,
117
+ getSortKey,
118
+ ) => {
119
+ setDefinition(id, tableId);
120
+ const changedRowValues = mapNew();
121
+ const changedSortKeys = mapNew();
75
122
  const rowValues = mapGet(allRowValues, id);
76
123
  const sortKeys = mapGet(allSortKeys, id);
77
124
  const processRow = (rowId) => {
@@ -121,16 +168,14 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
121
168
  });
122
169
  }
123
170
  processTable(true);
124
- removeStoreListeners(id);
125
- mapSet(
126
- storeListenerIds,
171
+ delStoreListeners(id);
172
+ addStoreListeners(
127
173
  id,
128
- setNew([
129
- store.addRowListener(tableId, null, (_store, _tableId, rowId) =>
130
- processRow(rowId),
131
- ),
132
- store.addTableListener(tableId, () => processTable()),
133
- ]),
174
+ 0,
175
+ store.addRowListener(tableId, null, (_store, _tableId, rowId) =>
176
+ processRow(rowId),
177
+ ),
178
+ store.addTableListener(tableId, () => processTable()),
134
179
  );
135
180
  };
136
181
  const delDefinition = (id) => {
@@ -138,7 +183,7 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
138
183
  mapSet(things, id);
139
184
  mapSet(allRowValues, id);
140
185
  mapSet(allSortKeys, id);
141
- removeStoreListeners(id);
186
+ delStoreListeners(id);
142
187
  };
143
188
  const destroy = () => mapForEach(storeListenerIds, delDefinition);
144
189
  return [
@@ -150,8 +195,11 @@ const getDefinableFunctions = (store, getDefaultThing, validateRowValue) => {
150
195
  getThing,
151
196
  setThing,
152
197
  setDefinition,
198
+ setDefinitionAndListen,
153
199
  delDefinition,
154
200
  destroy,
201
+ addStoreListeners,
202
+ delStoreListeners,
155
203
  ];
156
204
  };
157
205
  const getRowCellFunction = (getRowCell, defaultCellValue) =>
@@ -168,64 +216,51 @@ const getCreateFunction = (getFunction) => {
168
216
  };
169
217
  };
170
218
 
171
- const addDeepSet = (deepSet, value, ids) =>
172
- arrayLength(ids) < 2
173
- ? setAdd(
174
- arrayIsEmpty(ids) ? deepSet : mapEnsure(deepSet, ids[0], setNew),
175
- value,
176
- )
177
- : addDeepSet(
178
- mapEnsure(deepSet, ids[0], mapNew),
179
- value,
180
- arrayFromSecond(ids),
181
- );
182
- const forDeepSet = (valueDo) => {
183
- const deep = (deepIdSet, arg, ...ids) =>
184
- ifNotUndefined(deepIdSet, (deepIdSet2) =>
185
- arrayIsEmpty(ids)
186
- ? valueDo(deepIdSet2, arg)
187
- : arrayForEach([ids[0], null], (id) =>
188
- deep(mapGet(deepIdSet2, id), arg, ...arrayFromSecond(ids)),
189
- ),
190
- );
191
- return deep;
219
+ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
220
+ const leaves = [];
221
+ const deep = (node, p) =>
222
+ p == arrayLength(path)
223
+ ? arrayPush(leaves, node)
224
+ : path[p] === null
225
+ ? collForEach(node, (node2) => deep(node2, p + 1))
226
+ : arrayForEach([path[p], null], (id) => deep(mapGet(node, id), p + 1));
227
+ deep(deepIdSet, 0);
228
+ return leaves;
192
229
  };
193
230
  const getListenerFunctions = (getThing) => {
194
231
  let thing;
195
232
  let nextId = 0;
196
233
  const listenerPool = [];
197
234
  const allListeners = mapNew();
198
- const addListener = (listener, deepSet, idOrNulls = []) => {
235
+ const addListener = (listener, idSetNode, path) => {
199
236
  thing ??= getThing();
200
- const id = arrayPop(listenerPool) ?? '' + nextId++;
201
- mapSet(allListeners, id, [listener, deepSet, idOrNulls]);
202
- addDeepSet(deepSet, id, idOrNulls);
237
+ const id = arrayPop(listenerPool) ?? EMPTY_STRING + nextId++;
238
+ mapSet(allListeners, id, [listener, idSetNode, path]);
239
+ setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
203
240
  return id;
204
241
  };
205
- const callListeners = (deepSet, ids = [], ...extraArgs) =>
206
- forDeepSet(collForEach)(
207
- deepSet,
208
- (id) =>
209
- ifNotUndefined(mapGet(allListeners, id), ([listener]) =>
210
- listener(thing, ...ids, ...extraArgs),
211
- ),
212
- ...ids,
242
+ const callListeners = (idSetNode, ids, ...extraArgs) =>
243
+ arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
244
+ collForEach(set, (id) =>
245
+ mapGet(allListeners, id)[0](thing, ...(ids ?? []), ...extraArgs),
246
+ ),
213
247
  );
214
248
  const delListener = (id) =>
215
- ifNotUndefined(
216
- mapGet(allListeners, id),
217
- ([, deepSet, idOrNulls]) => {
218
- forDeepSet(collDel)(deepSet, id, ...idOrNulls);
219
- mapSet(allListeners, id);
220
- if (arrayLength(listenerPool) < 1e3) {
221
- arrayPush(listenerPool, id);
222
- }
223
- return idOrNulls;
224
- },
225
- () => [],
226
- );
249
+ ifNotUndefined(mapGet(allListeners, id), ([, idSetNode, idOrNulls]) => {
250
+ visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], void 0, (idSet) => {
251
+ collDel(idSet, id);
252
+ return collIsEmpty(idSet) ? 1 : 0;
253
+ });
254
+ mapSet(allListeners, id);
255
+ if (arrayLength(listenerPool) < 1e3) {
256
+ arrayPush(listenerPool, id);
257
+ }
258
+ return idOrNulls;
259
+ });
260
+ const hasListeners = (idSetNode, ids) =>
261
+ !arrayEvery(getWildcardedLeaves(idSetNode, ids), isUndefined);
227
262
  const callListener = (id, idNullGetters, extraArgsGetter) =>
228
- ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls]) => {
263
+ ifNotUndefined(mapGet(allListeners, id), ([listener, , idOrNulls = []]) => {
229
264
  const callWithIds = (...ids) => {
230
265
  const index = arrayLength(ids);
231
266
  index == arrayLength(idOrNulls)
@@ -238,7 +273,7 @@ const getListenerFunctions = (getThing) => {
238
273
  };
239
274
  callWithIds();
240
275
  });
241
- return [addListener, callListeners, delListener, callListener];
276
+ return [addListener, callListeners, delListener, hasListeners, callListener];
242
277
  };
243
278
 
244
279
  const object = Object;
@@ -257,7 +292,8 @@ const createRelationships = getCreateFunction((store) => {
257
292
  getLocalTableId,
258
293
  getRelationship,
259
294
  ,
260
- setDefinition,
295
+ ,
296
+ setDefinitionAndListen,
261
297
  delDefinition,
262
298
  destroy,
263
299
  ] = getDefinableFunctions(
@@ -304,7 +340,7 @@ const createRelationships = getCreateFunction((store) => {
304
340
  getRemoteRowId2,
305
341
  ) => {
306
342
  mapSet(remoteTableIds, relationshipId, remoteTableId);
307
- setDefinition(
343
+ setDefinitionAndListen(
308
344
  relationshipId,
309
345
  localTableId,
310
346
  (change, changedRemoteRowIds) => {