tinybase 2.0.0-beta.4 → 2.0.0-beta.5
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.
- package/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/debug/checkpoints.js +19 -7
- package/lib/debug/indexes.js +18 -7
- package/lib/debug/metrics.js +18 -7
- package/lib/debug/queries.d.ts +40 -38
- package/lib/debug/queries.js +24 -25
- package/lib/debug/relationships.js +18 -7
- package/lib/debug/store.js +42 -22
- package/lib/debug/tinybase.js +67 -47
- package/lib/debug/ui-react.d.ts +1 -0
- package/lib/indexes.js +1 -1
- package/lib/indexes.js.gz +0 -0
- package/lib/metrics.js +1 -1
- package/lib/metrics.js.gz +0 -0
- package/lib/queries.d.ts +40 -38
- package/lib/queries.js +1 -1
- package/lib/queries.js.gz +0 -0
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.js +1 -1
- package/lib/store.js.gz +0 -0
- package/lib/tinybase.js +1 -1
- package/lib/tinybase.js.gz +0 -0
- package/lib/ui-react.d.ts +1 -0
- package/lib/umd/checkpoints.js +1 -1
- package/lib/umd/checkpoints.js.gz +0 -0
- package/lib/umd/indexes.js +1 -1
- package/lib/umd/indexes.js.gz +0 -0
- package/lib/umd/metrics.js +1 -1
- package/lib/umd/metrics.js.gz +0 -0
- package/lib/umd/queries.js +1 -1
- package/lib/umd/queries.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.js +1 -1
- package/lib/umd/store.js.gz +0 -0
- package/lib/umd/tinybase.js +1 -1
- package/lib/umd/tinybase.js.gz +0 -0
- package/package.json +9 -9
- package/readme.md +2 -2
package/lib/checkpoints.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=(e,t)=>e.includes(t),t=(e,t)=>e.forEach(t),n=e=>e.length,r=e=>0==n(e),o=(e,...t)=>e.push(...t),s=e=>e.pop(),l=e=>null==e,
|
|
1
|
+
const e=(e,t)=>e.includes(t),t=(e,t)=>e.forEach(t),n=e=>e.length,r=e=>0==n(e),o=(e,...t)=>e.push(...t),s=e=>e.pop(),l=e=>e.shift(),c=e=>null==e,i=(e,t,n)=>c(e)?n?.():t(e),d=(e,t)=>e?.has(t)??!1,a=e=>c(e)||0==(e=>e.size)(e),u=(e,t)=>e?.forEach(t),h=(e,t)=>e?.delete(t),p=e=>new Map(e),C=(e,t)=>e?.get(t),g=(e,t,n)=>c(n)?(h(e,t),e):e?.set(t,n),k=(e,t,n)=>(d(e,t)||g(e,t,n()),C(e,t)),f=(e,t,r,o,s=0)=>i((r?k:C)(e,t[s],s>n(t)-2?r:p),(l=>{if(s>n(t)-2)return o?.(l)&&g(e,t[s]),l;const c=f(l,t,r,o,s+1);return a(l)&&g(e,t[s]),c})),v=e=>new Set(e),L=/^\d+$/,w=e=>{let r;const[s,d]=(()=>{const e=[];let t=0;return[()=>l(e)??""+t++,t=>{L.test(t)&&n(e)<1e3&&o(e,t)}]})(),k=p();return[(t,n,o)=>{r??=e();const l=s();var c,i;return g(k,l,[t,n,o]),c=f(n,o??[""],v),i=l,c?.add(i),l},(e,s,...l)=>t(((e,r=[""])=>{const s=[],l=(e,c)=>c==n(r)?o(s,e):null===r[c]?u(e,(e=>l(e,c+1))):t([r[c],null],(t=>l(C(e,t),c+1)));return l(e,0),s})(e,s),(e=>u(e,(e=>C(k,e)[0](r,...s??[],...l))))),e=>i(C(k,e),(([,t,n])=>(f(t,n??[""],void 0,(t=>(h(t,e),a(t)?1:0))),g(k,e),d(e),n))),(e,o,s)=>i(C(k,e),(([e,,l=[]])=>{const i=(...d)=>{const a=n(d);a==n(l)?e(r,...d,...s(d)):c(l[a])?t(o[a](...d),(e=>i(...d,e))):i(...d,l[a])};i()}))]},S=Object.freeze,z=(e=>{const t=new WeakMap;return n=>(t.has(n)||t.set(n,e(n)),t.get(n))})((h=>{let f,v,L,z=100,E=p(),I=1;const M=p(),b=p(),[j,x,y]=w((()=>Q)),B=p(),F=p(),O=[],T=[],W=(e,t)=>{I=0,h.transaction((()=>u(C(B,t),((t,n)=>u(t,((t,r)=>u(t,((t,o)=>((e,t,n,r,o)=>c(o)?e.delCell(t,n,r,!0):e.setCell(t,n,r,o))(h,n,r,o,t[e]))))))))),I=1},$=e=>{g(B,e),g(F,e),x(b,[e])},m=(e,r)=>t(((e,t)=>e.splice(0,t))(e,r??n(e)),$),q=()=>m(O,n(O)-z),A=h.addCellListener(null,null,null,((e,t,n,r,l,c)=>{if(I){i(f,(()=>{o(O,f),q(),m(T),f=void 0,L=1}));const e=k(E,t,p),d=k(e,n,p),u=k(d,r,(()=>[c,void 0]));u[1]=l,u[0]===l&&a(g(d,r))&&a(g(e,n))&&a(g(E,t))&&(f=s(O),L=1),J()}})),D=(e="")=>(c(f)&&(f=""+v++,g(B,f,E),N(f,e),E=p(),L=1),f),G=()=>{r(O)||(T.unshift(D()),W(0,f),f=s(O),L=1)},H=()=>{r(T)||(o(O,f),f=l(T),W(1,f),L=1)},J=()=>{L&&(x(M),L=0)},K=e=>{const t=D(e);return J(),t},N=(e,t)=>(P(e)&&C(F,e)!==t&&(g(F,e,t),x(b,[e])),Q),P=e=>d(B,e),Q={setSize:e=>(z=e,q(),Q),addCheckpoint:K,setCheckpoint:N,getStore:()=>h,getCheckpointIds:()=>[[...O],f,[...T]],forEachCheckpoint:e=>{return t=e,u(F,((e,n)=>t(n,e)));var t},hasCheckpoint:P,getCheckpoint:e=>C(F,e),goBackward:()=>(G(),J(),Q),goForward:()=>(H(),J(),Q),goTo:t=>{const n=e(O,t)?G:e(T,t)?H:null;for(;!c(n)&&t!=f;)n();return J(),Q},addCheckpointIdsListener:e=>j(e,M),addCheckpointListener:(e,t)=>j(t,b,[e]),delListener:e=>(y(e),Q),clear:()=>(m(O),m(T),c(f)||$(f),f=void 0,v=0,K(),Q),destroy:()=>{h.delListener(A)},getListenerStats:()=>({})};return S(Q.clear())}));export{z as createCheckpoints};
|
package/lib/checkpoints.js.gz
CHANGED
|
Binary file
|
package/lib/debug/checkpoints.js
CHANGED
|
@@ -8,6 +8,7 @@ const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
|
8
8
|
const arrayClear = (array, to) => array.splice(0, to);
|
|
9
9
|
const arrayPush = (array, ...values) => array.push(...values);
|
|
10
10
|
const arrayPop = (array) => array.pop();
|
|
11
|
+
const arrayShift = (array) => array.shift();
|
|
11
12
|
|
|
12
13
|
const isUndefined = (thing) => thing == void 0;
|
|
13
14
|
const ifNotUndefined = (value, then, otherwise) =>
|
|
@@ -70,6 +71,20 @@ const getCreateFunction = (getFunction) => {
|
|
|
70
71
|
};
|
|
71
72
|
};
|
|
72
73
|
|
|
74
|
+
const INTEGER = /^\d+$/;
|
|
75
|
+
const getPoolFunctions = () => {
|
|
76
|
+
const pool = [];
|
|
77
|
+
let nextId = 0;
|
|
78
|
+
return [
|
|
79
|
+
() => arrayShift(pool) ?? EMPTY_STRING + nextId++,
|
|
80
|
+
(id) => {
|
|
81
|
+
if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
|
|
82
|
+
arrayPush(pool, id);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
};
|
|
87
|
+
|
|
73
88
|
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
74
89
|
const leaves = [];
|
|
75
90
|
const deep = (node, p) =>
|
|
@@ -83,12 +98,11 @@ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
|
83
98
|
};
|
|
84
99
|
const getListenerFunctions = (getThing) => {
|
|
85
100
|
let thing;
|
|
86
|
-
|
|
87
|
-
const listenerPool = [];
|
|
101
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
88
102
|
const allListeners = mapNew();
|
|
89
103
|
const addListener = (listener, idSetNode, path) => {
|
|
90
104
|
thing ??= getThing();
|
|
91
|
-
const id =
|
|
105
|
+
const id = getId();
|
|
92
106
|
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
93
107
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
94
108
|
return id;
|
|
@@ -106,9 +120,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
106
120
|
return collIsEmpty(idSet) ? 1 : 0;
|
|
107
121
|
});
|
|
108
122
|
mapSet(allListeners, id);
|
|
109
|
-
|
|
110
|
-
arrayPush(listenerPool, id);
|
|
111
|
-
}
|
|
123
|
+
releaseId(id);
|
|
112
124
|
return idOrNulls;
|
|
113
125
|
});
|
|
114
126
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
|
@@ -229,7 +241,7 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
229
241
|
const goForwardImpl = () => {
|
|
230
242
|
if (!arrayIsEmpty(forwardIds)) {
|
|
231
243
|
arrayPush(backwardIds, currentId);
|
|
232
|
-
currentId = forwardIds
|
|
244
|
+
currentId = arrayShift(forwardIds);
|
|
233
245
|
updateStore(1, currentId);
|
|
234
246
|
checkpointsChanged = 1;
|
|
235
247
|
}
|
package/lib/debug/indexes.js
CHANGED
|
@@ -14,7 +14,7 @@ const arrayLength = (array) => array.length;
|
|
|
14
14
|
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
15
15
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
16
16
|
const arrayPush = (array, ...values) => array.push(...values);
|
|
17
|
-
const
|
|
17
|
+
const arrayShift = (array) => array.shift();
|
|
18
18
|
|
|
19
19
|
const isUndefined = (thing) => thing == void 0;
|
|
20
20
|
const ifNotUndefined = (value, then, otherwise) =>
|
|
@@ -224,6 +224,20 @@ const getCreateFunction = (getFunction) => {
|
|
|
224
224
|
|
|
225
225
|
const defaultSorter = (sortKey1, sortKey2) => (sortKey1 < sortKey2 ? -1 : 1);
|
|
226
226
|
|
|
227
|
+
const INTEGER = /^\d+$/;
|
|
228
|
+
const getPoolFunctions = () => {
|
|
229
|
+
const pool = [];
|
|
230
|
+
let nextId = 0;
|
|
231
|
+
return [
|
|
232
|
+
() => arrayShift(pool) ?? EMPTY_STRING + nextId++,
|
|
233
|
+
(id) => {
|
|
234
|
+
if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
|
|
235
|
+
arrayPush(pool, id);
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
};
|
|
240
|
+
|
|
227
241
|
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
228
242
|
const leaves = [];
|
|
229
243
|
const deep = (node, p) =>
|
|
@@ -237,12 +251,11 @@ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
|
237
251
|
};
|
|
238
252
|
const getListenerFunctions = (getThing) => {
|
|
239
253
|
let thing;
|
|
240
|
-
|
|
241
|
-
const listenerPool = [];
|
|
254
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
242
255
|
const allListeners = mapNew();
|
|
243
256
|
const addListener = (listener, idSetNode, path) => {
|
|
244
257
|
thing ??= getThing();
|
|
245
|
-
const id =
|
|
258
|
+
const id = getId();
|
|
246
259
|
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
247
260
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
248
261
|
return id;
|
|
@@ -260,9 +273,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
260
273
|
return collIsEmpty(idSet) ? 1 : 0;
|
|
261
274
|
});
|
|
262
275
|
mapSet(allListeners, id);
|
|
263
|
-
|
|
264
|
-
arrayPush(listenerPool, id);
|
|
265
|
-
}
|
|
276
|
+
releaseId(id);
|
|
266
277
|
return idOrNulls;
|
|
267
278
|
});
|
|
268
279
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
package/lib/debug/metrics.js
CHANGED
|
@@ -13,7 +13,7 @@ const arrayLength = (array) => array.length;
|
|
|
13
13
|
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
14
14
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
15
15
|
const arrayPush = (array, ...values) => array.push(...values);
|
|
16
|
-
const
|
|
16
|
+
const arrayShift = (array) => array.shift();
|
|
17
17
|
|
|
18
18
|
const mathMax = Math.max;
|
|
19
19
|
const mathMin = Math.min;
|
|
@@ -294,6 +294,20 @@ const getCreateFunction = (getFunction) => {
|
|
|
294
294
|
};
|
|
295
295
|
};
|
|
296
296
|
|
|
297
|
+
const INTEGER = /^\d+$/;
|
|
298
|
+
const getPoolFunctions = () => {
|
|
299
|
+
const pool = [];
|
|
300
|
+
let nextId = 0;
|
|
301
|
+
return [
|
|
302
|
+
() => arrayShift(pool) ?? EMPTY_STRING + nextId++,
|
|
303
|
+
(id) => {
|
|
304
|
+
if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
|
|
305
|
+
arrayPush(pool, id);
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
];
|
|
309
|
+
};
|
|
310
|
+
|
|
297
311
|
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
298
312
|
const leaves = [];
|
|
299
313
|
const deep = (node, p) =>
|
|
@@ -307,12 +321,11 @@ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
|
307
321
|
};
|
|
308
322
|
const getListenerFunctions = (getThing) => {
|
|
309
323
|
let thing;
|
|
310
|
-
|
|
311
|
-
const listenerPool = [];
|
|
324
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
312
325
|
const allListeners = mapNew();
|
|
313
326
|
const addListener = (listener, idSetNode, path) => {
|
|
314
327
|
thing ??= getThing();
|
|
315
|
-
const id =
|
|
328
|
+
const id = getId();
|
|
316
329
|
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
317
330
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
318
331
|
return id;
|
|
@@ -330,9 +343,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
330
343
|
return collIsEmpty(idSet) ? 1 : 0;
|
|
331
344
|
});
|
|
332
345
|
mapSet(allListeners, id);
|
|
333
|
-
|
|
334
|
-
arrayPush(listenerPool, id);
|
|
335
|
-
}
|
|
346
|
+
releaseId(id);
|
|
336
347
|
return idOrNulls;
|
|
337
348
|
});
|
|
338
349
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
package/lib/debug/queries.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* The queries module of the TinyBase project provides the ability to create and
|
|
3
3
|
* track queries of the data in Store objects.
|
|
4
4
|
*
|
|
5
|
-
* The main entry point to
|
|
6
|
-
* returns a new Queries object.
|
|
7
|
-
* definitions, access
|
|
8
|
-
* when
|
|
5
|
+
* The main entry point to using the queries module is the createQueries
|
|
6
|
+
* function, which returns a new Queries object. That object in turn has methods
|
|
7
|
+
* that let you create new query definitions, access their results directly, and
|
|
8
|
+
* register listeners for when those results change.
|
|
9
9
|
*
|
|
10
10
|
* @packageDocumentation
|
|
11
11
|
* @module queries
|
|
@@ -385,18 +385,18 @@ export type GetTableCell = {
|
|
|
385
385
|
* The Select type describes a function that lets you specify a Cell or
|
|
386
386
|
* calculated value for including into the query's result.
|
|
387
387
|
*
|
|
388
|
-
* The Select function is provided
|
|
389
|
-
*
|
|
390
|
-
*
|
|
388
|
+
* The Select function is provided to the third `query` parameter of the
|
|
389
|
+
* setQueryDefinition method. A query definition must call the Select function
|
|
390
|
+
* at least once, otherwise it will be meaningless and return no data.
|
|
391
391
|
*
|
|
392
392
|
* @example
|
|
393
393
|
* This example shows a query that selects two Cells from the main query Table.
|
|
394
394
|
*
|
|
395
395
|
* ```js
|
|
396
396
|
* const store = createStore().setTable('pets', {
|
|
397
|
-
* fido: {species: 'dog', color: 'brown'},
|
|
398
|
-
* felix: {species: 'cat', color: 'black'},
|
|
399
|
-
* cujo: {species: 'dog', color: 'black'},
|
|
397
|
+
* fido: {species: 'dog', color: 'brown', legs: 4},
|
|
398
|
+
* felix: {species: 'cat', color: 'black', legs: 4},
|
|
399
|
+
* cujo: {species: 'dog', color: 'black', legs: 4},
|
|
400
400
|
* });
|
|
401
401
|
*
|
|
402
402
|
* const queries = createQueries(store);
|
|
@@ -572,9 +572,9 @@ export type SelectedAs = {
|
|
|
572
572
|
|
|
573
573
|
/**
|
|
574
574
|
* The Join type describes a function that lets you specify a Cell or calculated
|
|
575
|
-
* value to join the main query Table to
|
|
575
|
+
* value to join the main query Table to other Tables, by their Row Id.
|
|
576
576
|
*
|
|
577
|
-
* The Join function is provided
|
|
577
|
+
* The Join function is provided to the third `query` parameter of the
|
|
578
578
|
* setQueryDefinition method.
|
|
579
579
|
*
|
|
580
580
|
* You can join zero, one, or many Tables. You can join the same underlying
|
|
@@ -856,8 +856,8 @@ export type JoinedAs = {as: (joinedTableId: Id) => void};
|
|
|
856
856
|
* The Where type describes a function that lets you specify conditions to
|
|
857
857
|
* filter results, based on the underlying Cells of the main or joined Tables.
|
|
858
858
|
*
|
|
859
|
-
* The Where function is provided
|
|
860
|
-
*
|
|
859
|
+
* The Where function is provided to the third `query` parameter of the
|
|
860
|
+
* setQueryDefinition method.
|
|
861
861
|
*
|
|
862
862
|
* If you do not specify a Where clause, you should expect every non-empty Row
|
|
863
863
|
* of the main Table to appear in the query's results.
|
|
@@ -867,10 +867,10 @@ export type JoinedAs = {as: (joinedTableId: Id) => void};
|
|
|
867
867
|
* wish to create an 'or' expression, use the single parameter version of the
|
|
868
868
|
* type that allows arbitrary programmatic conditions.
|
|
869
869
|
*
|
|
870
|
-
* The Where
|
|
871
|
-
* conditions that should be met by underlying Cell values (whether
|
|
872
|
-
* not), and the latter describes conditions based on calculated and
|
|
873
|
-
* values - after Group clauses have been applied.
|
|
870
|
+
* The Where keyword differs from the Having keyword in that the former
|
|
871
|
+
* describes conditions that should be met by underlying Cell values (whether
|
|
872
|
+
* selected or not), and the latter describes conditions based on calculated and
|
|
873
|
+
* aggregated values - after Group clauses have been applied.
|
|
874
874
|
*
|
|
875
875
|
* @example
|
|
876
876
|
* This example shows a query that filters the results from a single Table by
|
|
@@ -1006,8 +1006,8 @@ export type Where = {
|
|
|
1006
1006
|
* The Group type describes a function that lets you specify that the values of
|
|
1007
1007
|
* a Cell in multiple result Rows should be aggregated together.
|
|
1008
1008
|
*
|
|
1009
|
-
* The Group function is provided
|
|
1010
|
-
*
|
|
1009
|
+
* The Group function is provided to the third `query` parameter of the
|
|
1010
|
+
* setQueryDefinition method. When called, it should refer to a Cell Id (or
|
|
1011
1011
|
* aliased Id) specified in one of the Select functions, and indicate how the
|
|
1012
1012
|
* values should be aggregated.
|
|
1013
1013
|
*
|
|
@@ -1225,18 +1225,18 @@ export type GroupedAs = {as: (groupedCellId: Id) => void};
|
|
|
1225
1225
|
* The Having type describes a function that lets you specify conditions to
|
|
1226
1226
|
* filter results, based on the grouped Cells resulting from a Group clause.
|
|
1227
1227
|
*
|
|
1228
|
-
* The Having function is provided
|
|
1229
|
-
*
|
|
1228
|
+
* The Having function is provided to the third `query` parameter of the
|
|
1229
|
+
* setQueryDefinition method.
|
|
1230
1230
|
*
|
|
1231
1231
|
* A Having condition has to be true for a Row to be included in the results.
|
|
1232
1232
|
* Each Having class is additive, as though combined with a logical 'and'. If
|
|
1233
1233
|
* you wish to create an 'or' expression, use the single parameter version of
|
|
1234
1234
|
* the type that allows arbitrary programmatic conditions.
|
|
1235
1235
|
*
|
|
1236
|
-
* The Where
|
|
1237
|
-
* conditions that should be met by underlying Cell values (whether
|
|
1238
|
-
* not), and the latter describes conditions based on calculated and
|
|
1239
|
-
* values - after Group clauses have been applied.
|
|
1236
|
+
* The Where keyword differs from the Having keyword in that the former
|
|
1237
|
+
* describes conditions that should be met by underlying Cell values (whether
|
|
1238
|
+
* selected or not), and the latter describes conditions based on calculated and
|
|
1239
|
+
* aggregated values - after Group clauses have been applied.
|
|
1240
1240
|
*
|
|
1241
1241
|
* Whilst it is technically possible to use a Having clause even if the results
|
|
1242
1242
|
* have not been grouped with a Group clause, you should expect it to be less
|
|
@@ -1269,8 +1269,8 @@ export type GroupedAs = {as: (groupedCellId: Id) => void};
|
|
|
1269
1269
|
* queries.forEachResultRow('query', (rowId) => {
|
|
1270
1270
|
* console.log({[rowId]: queries.getResultRow('query', rowId)});
|
|
1271
1271
|
* });
|
|
1272
|
-
* // -> {
|
|
1273
|
-
* // -> {
|
|
1272
|
+
* // -> {0: {species: 'cat', minPrice: 3, maxPrice: 4}}
|
|
1273
|
+
* // -> {1: {species: 'parrot', minPrice: 3, maxPrice: 3}}
|
|
1274
1274
|
* ```
|
|
1275
1275
|
* @example
|
|
1276
1276
|
* This example shows a query that filters the results from a grouped Table with
|
|
@@ -1421,7 +1421,9 @@ export type Having = {
|
|
|
1421
1421
|
* queries.delListener(listenerId);
|
|
1422
1422
|
* queries.destroy();
|
|
1423
1423
|
* ```
|
|
1424
|
-
* @see Queries guides
|
|
1424
|
+
* @see Making Queries guides
|
|
1425
|
+
* @see Car Analysis demo
|
|
1426
|
+
* @see Movie Database demo
|
|
1425
1427
|
* @category Queries
|
|
1426
1428
|
* @since v2.0.0
|
|
1427
1429
|
*/
|
|
@@ -1436,11 +1438,11 @@ export interface Queries {
|
|
|
1436
1438
|
* The definition must specify this 'main' Table (by its Id) to be aggregated.
|
|
1437
1439
|
* Other Tables can be joined to that using Join clauses.
|
|
1438
1440
|
*
|
|
1439
|
-
* The third `
|
|
1440
|
-
* query. That callback is provided with a `
|
|
1441
|
-
*
|
|
1442
|
-
* see how that is used in the simple example below. The following
|
|
1443
|
-
* clause types are supported:
|
|
1441
|
+
* The third `query` parameter is a callback that you provide to define the
|
|
1442
|
+
* query. That callback is provided with a `keywords` object that contains the
|
|
1443
|
+
* functions you use to define the query, like `select`, `join`, and so on.
|
|
1444
|
+
* You can see how that is used in the simple example below. The following
|
|
1445
|
+
* five clause types are supported:
|
|
1444
1446
|
*
|
|
1445
1447
|
* - The Select type describes a function that lets you specify a Cell or
|
|
1446
1448
|
* calculated value for including into the query's result.
|
|
@@ -1456,14 +1458,14 @@ export interface Queries {
|
|
|
1456
1458
|
*
|
|
1457
1459
|
* Full documentation and examples are provided in the sections for each of
|
|
1458
1460
|
* those clause types.
|
|
1459
|
-
*
|
|
1461
|
+
*
|
|
1460
1462
|
* Additionally, you can use the getResultSortedRowIds method and
|
|
1461
1463
|
* addResultSortedRowIdsListener method to sort and paginate the results.
|
|
1462
1464
|
*
|
|
1463
1465
|
* @param queryId The Id of the query to define.
|
|
1464
1466
|
* @param tableId The Id of the main Table the query will be based on.
|
|
1465
|
-
* @param
|
|
1466
|
-
the
|
|
1467
|
+
* @param query A callback which can take a `keywords` object and which uses
|
|
1468
|
+
the functions it contains to define the query.
|
|
1467
1469
|
* @returns A reference to the Queries object.
|
|
1468
1470
|
* @example
|
|
1469
1471
|
* This example creates a Store, creates a Queries object, and defines a
|
|
@@ -1492,7 +1494,7 @@ export interface Queries {
|
|
|
1492
1494
|
setQueryDefinition(
|
|
1493
1495
|
queryId: Id,
|
|
1494
1496
|
tableId: Id,
|
|
1495
|
-
|
|
1497
|
+
query: (keywords: {
|
|
1496
1498
|
select: Select;
|
|
1497
1499
|
join: Join;
|
|
1498
1500
|
where: Where;
|
package/lib/debug/queries.js
CHANGED
|
@@ -348,10 +348,16 @@ const createQueries = getCreateFunction((store) => {
|
|
|
348
348
|
),
|
|
349
349
|
);
|
|
350
350
|
const resetPreStores = (queryId) => {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
351
|
+
ifNotUndefined(
|
|
352
|
+
mapGet(preStoreListenerIds, queryId),
|
|
353
|
+
(queryPreStoreListenerIds) => {
|
|
354
|
+
mapForEach(queryPreStoreListenerIds, (preStore2, listenerIds) =>
|
|
355
|
+
collForEach(listenerIds, (listenerId) =>
|
|
356
|
+
preStore2.delListener(listenerId),
|
|
357
|
+
),
|
|
358
|
+
);
|
|
359
|
+
collClear(queryPreStoreListenerIds);
|
|
360
|
+
},
|
|
355
361
|
);
|
|
356
362
|
arrayForEach([resultStore, preStore], (store2) => store2.delTable(queryId));
|
|
357
363
|
};
|
|
@@ -511,12 +517,18 @@ const createQueries = getCreateFunction((store) => {
|
|
|
511
517
|
}
|
|
512
518
|
},
|
|
513
519
|
);
|
|
514
|
-
(
|
|
520
|
+
if (
|
|
521
|
+
collIsEmpty(selectedRowIds) ||
|
|
515
522
|
!arrayEvery(havings, (having2) =>
|
|
516
523
|
having2((cellId) => groupRow[cellId]),
|
|
517
524
|
)
|
|
518
|
-
|
|
519
|
-
|
|
525
|
+
) {
|
|
526
|
+
resultStore.delRow(queryId, groupRowId);
|
|
527
|
+
} else if (isUndefined(groupRowId)) {
|
|
528
|
+
leaf[2] = resultStore.addRow(queryId, groupRow);
|
|
529
|
+
} else {
|
|
530
|
+
resultStore.setRow(queryId, groupRowId, groupRow);
|
|
531
|
+
}
|
|
520
532
|
},
|
|
521
533
|
);
|
|
522
534
|
addPreStoreListener(
|
|
@@ -556,18 +568,10 @@ const createQueries = getCreateFunction((store) => {
|
|
|
556
568
|
});
|
|
557
569
|
if (changedLeaf) {
|
|
558
570
|
writeGroupRow(
|
|
559
|
-
visitTree(
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
([, selectedRowIds, groupRowId]) => {
|
|
564
|
-
collDel(selectedRowIds, selectedRowId);
|
|
565
|
-
if (collIsEmpty(selectedRowIds)) {
|
|
566
|
-
resultStore.delRow(queryId, groupRowId);
|
|
567
|
-
return 1;
|
|
568
|
-
}
|
|
569
|
-
},
|
|
570
|
-
),
|
|
571
|
+
visitTree(tree, oldPath, void 0, ([, selectedRowIds]) => {
|
|
572
|
+
collDel(selectedRowIds, selectedRowId);
|
|
573
|
+
return collIsEmpty(selectedRowIds);
|
|
574
|
+
}),
|
|
571
575
|
changedGroupedSelectedCells,
|
|
572
576
|
selectedRowId,
|
|
573
577
|
1,
|
|
@@ -590,12 +594,7 @@ const createQueries = getCreateFunction((store) => {
|
|
|
590
594
|
selectedCellId,
|
|
591
595
|
)),
|
|
592
596
|
);
|
|
593
|
-
return [
|
|
594
|
-
mapNew(),
|
|
595
|
-
setNew(),
|
|
596
|
-
resultStore.addRow(queryId, groupRow, 1),
|
|
597
|
-
groupRow,
|
|
598
|
-
];
|
|
597
|
+
return [mapNew(), setNew(), void 0, groupRow];
|
|
599
598
|
},
|
|
600
599
|
([, selectedRowIds]) => {
|
|
601
600
|
setAdd(selectedRowIds, selectedRowId);
|
|
@@ -7,7 +7,7 @@ const arrayLength = (array) => array.length;
|
|
|
7
7
|
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
8
8
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
9
9
|
const arrayPush = (array, ...values) => array.push(...values);
|
|
10
|
-
const
|
|
10
|
+
const arrayShift = (array) => array.shift();
|
|
11
11
|
|
|
12
12
|
const isUndefined = (thing) => thing == void 0;
|
|
13
13
|
const ifNotUndefined = (value, then, otherwise) =>
|
|
@@ -215,6 +215,20 @@ const getCreateFunction = (getFunction) => {
|
|
|
215
215
|
};
|
|
216
216
|
};
|
|
217
217
|
|
|
218
|
+
const INTEGER = /^\d+$/;
|
|
219
|
+
const getPoolFunctions = () => {
|
|
220
|
+
const pool = [];
|
|
221
|
+
let nextId = 0;
|
|
222
|
+
return [
|
|
223
|
+
() => arrayShift(pool) ?? EMPTY_STRING + nextId++,
|
|
224
|
+
(id) => {
|
|
225
|
+
if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
|
|
226
|
+
arrayPush(pool, id);
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
];
|
|
230
|
+
};
|
|
231
|
+
|
|
218
232
|
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
219
233
|
const leaves = [];
|
|
220
234
|
const deep = (node, p) =>
|
|
@@ -228,12 +242,11 @@ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
|
228
242
|
};
|
|
229
243
|
const getListenerFunctions = (getThing) => {
|
|
230
244
|
let thing;
|
|
231
|
-
|
|
232
|
-
const listenerPool = [];
|
|
245
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
233
246
|
const allListeners = mapNew();
|
|
234
247
|
const addListener = (listener, idSetNode, path) => {
|
|
235
248
|
thing ??= getThing();
|
|
236
|
-
const id =
|
|
249
|
+
const id = getId();
|
|
237
250
|
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
238
251
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
239
252
|
return id;
|
|
@@ -251,9 +264,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
251
264
|
return collIsEmpty(idSet) ? 1 : 0;
|
|
252
265
|
});
|
|
253
266
|
mapSet(allListeners, id);
|
|
254
|
-
|
|
255
|
-
arrayPush(listenerPool, id);
|
|
256
|
-
}
|
|
267
|
+
releaseId(id);
|
|
257
268
|
return idOrNulls;
|
|
258
269
|
});
|
|
259
270
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
package/lib/debug/store.js
CHANGED
|
@@ -31,7 +31,7 @@ const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
|
31
31
|
const arrayFilter = (array, cb) => array.filter(cb);
|
|
32
32
|
const arraySlice = (array, start, end) => array.slice(start, end);
|
|
33
33
|
const arrayPush = (array, ...values) => array.push(...values);
|
|
34
|
-
const
|
|
34
|
+
const arrayShift = (array) => array.shift();
|
|
35
35
|
|
|
36
36
|
const jsonString = (obj) =>
|
|
37
37
|
JSON.stringify(obj, (_key, value) =>
|
|
@@ -136,6 +136,20 @@ const objIsEmpty = (obj) => arrayIsEmpty(objIds(obj));
|
|
|
136
136
|
const setNew = (entries) => new Set(entries);
|
|
137
137
|
const setAdd = (set, value) => set?.add(value);
|
|
138
138
|
|
|
139
|
+
const INTEGER = /^\d+$/;
|
|
140
|
+
const getPoolFunctions = () => {
|
|
141
|
+
const pool = [];
|
|
142
|
+
let nextId = 0;
|
|
143
|
+
return [
|
|
144
|
+
() => arrayShift(pool) ?? EMPTY_STRING + nextId++,
|
|
145
|
+
(id) => {
|
|
146
|
+
if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
|
|
147
|
+
arrayPush(pool, id);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
};
|
|
152
|
+
|
|
139
153
|
const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
140
154
|
const leaves = [];
|
|
141
155
|
const deep = (node, p) =>
|
|
@@ -149,12 +163,11 @@ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
|
|
|
149
163
|
};
|
|
150
164
|
const getListenerFunctions = (getThing) => {
|
|
151
165
|
let thing;
|
|
152
|
-
|
|
153
|
-
const listenerPool = [];
|
|
166
|
+
const [getId, releaseId] = getPoolFunctions();
|
|
154
167
|
const allListeners = mapNew();
|
|
155
168
|
const addListener = (listener, idSetNode, path) => {
|
|
156
169
|
thing ??= getThing();
|
|
157
|
-
const id =
|
|
170
|
+
const id = getId();
|
|
158
171
|
mapSet(allListeners, id, [listener, idSetNode, path]);
|
|
159
172
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
160
173
|
return id;
|
|
@@ -172,9 +185,7 @@ const getListenerFunctions = (getThing) => {
|
|
|
172
185
|
return collIsEmpty(idSet) ? 1 : 0;
|
|
173
186
|
});
|
|
174
187
|
mapSet(allListeners, id);
|
|
175
|
-
|
|
176
|
-
arrayPush(listenerPool, id);
|
|
177
|
-
}
|
|
188
|
+
releaseId(id);
|
|
178
189
|
return idOrNulls;
|
|
179
190
|
});
|
|
180
191
|
const callListener = (id, idNullGetters, extraArgsGetter) =>
|
|
@@ -240,7 +251,6 @@ const idsChanged = (changedIds, id2, added) =>
|
|
|
240
251
|
const createStore = () => {
|
|
241
252
|
let hasSchema;
|
|
242
253
|
let cellsTouched;
|
|
243
|
-
let nextRowId = 0;
|
|
244
254
|
let transactions = 0;
|
|
245
255
|
const changedTableIds = mapNew();
|
|
246
256
|
const changedRowIds = mapNew();
|
|
@@ -249,6 +259,7 @@ const createStore = () => {
|
|
|
249
259
|
const invalidCells = mapNew();
|
|
250
260
|
const schemaMap = mapNew();
|
|
251
261
|
const schemaRowCache = mapNew();
|
|
262
|
+
const tablePoolFunctions = mapNew();
|
|
252
263
|
const tablesMap = mapNew();
|
|
253
264
|
const tablesListeners = pairNewMap();
|
|
254
265
|
const tableIdsListeners = pairNewMap();
|
|
@@ -411,18 +422,26 @@ const createStore = () => {
|
|
|
411
422
|
addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
|
|
412
423
|
),
|
|
413
424
|
);
|
|
414
|
-
const getNewRowId = (
|
|
415
|
-
const
|
|
416
|
-
|
|
425
|
+
const getNewRowId = (tableId) => {
|
|
426
|
+
const [getId] = mapEnsure(tablePoolFunctions, tableId, getPoolFunctions);
|
|
427
|
+
const rowId = getId();
|
|
428
|
+
if (!collHas(mapGet(tablesMap, tableId), rowId)) {
|
|
417
429
|
return rowId;
|
|
418
430
|
}
|
|
419
|
-
return getNewRowId(
|
|
431
|
+
return getNewRowId(tableId);
|
|
420
432
|
};
|
|
421
433
|
const getOrCreateTable = (tableId) =>
|
|
422
434
|
mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
|
|
423
435
|
const delValidTable = (tableId) => setValidTable(tableId, {});
|
|
424
|
-
const delValidRow = (tableId, tableMap, rowId) =>
|
|
436
|
+
const delValidRow = (tableId, tableMap, rowId) => {
|
|
437
|
+
const [, releaseId] = mapEnsure(
|
|
438
|
+
tablePoolFunctions,
|
|
439
|
+
tableId,
|
|
440
|
+
getPoolFunctions,
|
|
441
|
+
);
|
|
442
|
+
releaseId(rowId);
|
|
425
443
|
setValidRow(tableId, tableMap, rowId, {}, true);
|
|
444
|
+
};
|
|
426
445
|
const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
|
|
427
446
|
const defaultCell = mapGet(mapGet(schemaRowCache, tableId)?.[0], cellId);
|
|
428
447
|
if (!isUndefined(defaultCell) && !forceDel) {
|
|
@@ -668,16 +687,17 @@ const createStore = () => {
|
|
|
668
687
|
tableId,
|
|
669
688
|
rowId,
|
|
670
689
|
);
|
|
671
|
-
const addRow = (tableId, row
|
|
690
|
+
const addRow = (tableId, row) =>
|
|
672
691
|
transaction(() => {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
692
|
+
let rowId = void 0;
|
|
693
|
+
if (validateRow(tableId, rowId, row)) {
|
|
694
|
+
tableId = id(tableId);
|
|
695
|
+
setValidRow(
|
|
696
|
+
tableId,
|
|
697
|
+
getOrCreateTable(tableId),
|
|
698
|
+
(rowId = getNewRowId(tableId)),
|
|
699
|
+
row,
|
|
700
|
+
);
|
|
681
701
|
}
|
|
682
702
|
return rowId;
|
|
683
703
|
});
|