tinybase 1.3.5 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/lib/checkpoints.js +1 -1
  2. package/lib/checkpoints.js.gz +0 -0
  3. package/lib/debug/checkpoints.js +67 -54
  4. package/lib/debug/indexes.js +104 -67
  5. package/lib/debug/metrics.js +185 -129
  6. package/lib/debug/persisters.js +2 -1
  7. package/lib/debug/queries.d.ts +3066 -0
  8. package/lib/debug/queries.js +883 -0
  9. package/lib/debug/relationships.d.ts +6 -5
  10. package/lib/debug/relationships.js +102 -66
  11. package/lib/debug/store.d.ts +128 -65
  12. package/lib/debug/store.js +215 -119
  13. package/lib/debug/tinybase.d.ts +1 -0
  14. package/lib/debug/tinybase.js +895 -175
  15. package/lib/debug/ui-react.d.ts +49 -2
  16. package/lib/debug/ui-react.js +85 -74
  17. package/lib/indexes.js +1 -1
  18. package/lib/indexes.js.gz +0 -0
  19. package/lib/metrics.js +1 -1
  20. package/lib/metrics.js.gz +0 -0
  21. package/lib/queries.d.ts +3066 -0
  22. package/lib/queries.js +1 -0
  23. package/lib/queries.js.gz +0 -0
  24. package/lib/relationships.d.ts +6 -5
  25. package/lib/relationships.js +1 -1
  26. package/lib/relationships.js.gz +0 -0
  27. package/lib/store.d.ts +128 -65
  28. package/lib/store.js +1 -1
  29. package/lib/store.js.gz +0 -0
  30. package/lib/tinybase.d.ts +1 -0
  31. package/lib/tinybase.js +1 -1
  32. package/lib/tinybase.js.gz +0 -0
  33. package/lib/ui-react.d.ts +49 -2
  34. package/lib/ui-react.js +1 -1
  35. package/lib/ui-react.js.gz +0 -0
  36. package/lib/umd/checkpoints.js +1 -1
  37. package/lib/umd/checkpoints.js.gz +0 -0
  38. package/lib/umd/indexes.js +1 -1
  39. package/lib/umd/indexes.js.gz +0 -0
  40. package/lib/umd/metrics.js +1 -1
  41. package/lib/umd/metrics.js.gz +0 -0
  42. package/lib/umd/queries.js +1 -0
  43. package/lib/umd/queries.js.gz +0 -0
  44. package/lib/umd/relationships.js +1 -1
  45. package/lib/umd/relationships.js.gz +0 -0
  46. package/lib/umd/store.js +1 -1
  47. package/lib/umd/store.js.gz +0 -0
  48. package/lib/umd/tinybase.js +1 -1
  49. package/lib/umd/tinybase.js.gz +0 -0
  50. package/lib/umd/ui-react.js +1 -1
  51. package/lib/umd/ui-react.js.gz +0 -0
  52. package/package.json +1 -1
  53. package/readme.md +2 -2
@@ -190,6 +190,7 @@ export type RelationshipsListenerStats = {
190
190
  * });
191
191
  *
192
192
  * const relationships = createRelationships(store);
193
+ *
193
194
  * // A local/remote table relationship:
194
195
  * relationships.setRelationshipDefinition(
195
196
  * 'petSpecies', // relationshipId
@@ -197,6 +198,11 @@ export type RelationshipsListenerStats = {
197
198
  * 'species', // remoteTableId to link to
198
199
  * 'species', // cellId containing remote key
199
200
  * );
201
+ * console.log(relationships.getRemoteRowId('petSpecies', 'fido'));
202
+ * // -> 'dog'
203
+ * console.log(relationships.getLocalRowIds('petSpecies', 'dog'));
204
+ * // -> ['fido', 'cujo']
205
+ *
200
206
  * // A linked list relationship:
201
207
  * relationships.setRelationshipDefinition(
202
208
  * 'petSequence', // relationshipId
@@ -204,11 +210,6 @@ export type RelationshipsListenerStats = {
204
210
  * 'pets', // the same remoteTableId to link within
205
211
  * 'next', // cellId containing link key
206
212
  * );
207
- *
208
- * console.log(relationships.getRemoteRowId('petSpecies', 'fido'));
209
- * // -> 'dog'
210
- * console.log(relationships.getLocalRowIds('petSpecies', 'dog'));
211
- * // -> ['fido', 'cujo']
212
213
  * console.log(relationships.getLinkedRowIds('petSequence', 'fido'));
213
214
  * // -> ['fido', 'felix', 'cujo']
214
215
  *
@@ -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 sets = [];
221
+ const deep = (set, p) =>
222
+ p == arrayLength(path)
223
+ ? arrayPush(sets, set)
224
+ : arrayForEach([path[p], null], (id) => deep(mapGet(set, id), p + 1));
225
+ deep(deepIdSet, 0);
226
+ return sets;
192
227
  };
193
228
  const getListenerFunctions = (getThing) => {
194
229
  let thing;
195
230
  let nextId = 0;
196
231
  const listenerPool = [];
197
232
  const allListeners = mapNew();
198
- const addListener = (listener, deepSet, idOrNulls = []) => {
233
+ const addListener = (listener, idSetNode, idOrNulls) => {
199
234
  thing ??= getThing();
200
- const id = arrayPop(listenerPool) ?? '' + nextId++;
201
- mapSet(allListeners, id, [listener, deepSet, idOrNulls]);
202
- addDeepSet(deepSet, id, idOrNulls);
235
+ const id = arrayPop(listenerPool) ?? EMPTY_STRING + nextId++;
236
+ mapSet(allListeners, id, [listener, idSetNode, idOrNulls]);
237
+ setAdd(visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], setNew), id);
203
238
  return id;
204
239
  };
205
- const callListeners = (deepSet, ids = [], ...extraArgs) =>
206
- forDeepSet(collForEach)(
207
- deepSet,
208
- (id) =>
240
+ const callListeners = (idSetNode, ids, ...extraArgs) =>
241
+ arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
242
+ collForEach(set, (id) =>
209
243
  ifNotUndefined(mapGet(allListeners, id), ([listener]) =>
210
- listener(thing, ...ids, ...extraArgs),
244
+ listener(thing, ...(ids ?? []), ...extraArgs),
211
245
  ),
212
- ...ids,
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) => {