tinybase 3.0.0-beta.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +1 -1
- package/lib/checkpoints.d.ts +18 -3
- package/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/debug/checkpoints.d.ts +18 -3
- package/lib/debug/checkpoints.js +97 -49
- package/lib/debug/indexes.js +31 -16
- package/lib/debug/metrics.js +31 -16
- package/lib/debug/persisters.d.ts +33 -23
- package/lib/debug/persisters.js +10 -5
- package/lib/debug/queries.js +2 -2
- package/lib/debug/relationships.js +31 -16
- package/lib/debug/store.d.ts +2053 -381
- package/lib/debug/store.js +444 -106
- package/lib/debug/tinybase.js +512 -138
- package/lib/debug/tools.d.ts +109 -38
- package/lib/debug/tools.js +759 -453
- package/lib/debug/ui-react.d.ts +1218 -138
- package/lib/debug/ui-react.js +163 -12
- package/lib/es6/checkpoints.d.ts +18 -3
- package/lib/es6/checkpoints.js +1 -1
- package/lib/es6/checkpoints.js.gz +0 -0
- package/lib/es6/indexes.js +1 -1
- package/lib/es6/indexes.js.gz +0 -0
- package/lib/es6/metrics.js +1 -1
- package/lib/es6/metrics.js.gz +0 -0
- package/lib/es6/persisters.d.ts +33 -23
- package/lib/es6/persisters.js +1 -1
- package/lib/es6/persisters.js.gz +0 -0
- package/lib/es6/relationships.js +1 -1
- package/lib/es6/relationships.js.gz +0 -0
- package/lib/es6/store.d.ts +2053 -381
- package/lib/es6/store.js +1 -1
- package/lib/es6/store.js.gz +0 -0
- package/lib/es6/tinybase.js +1 -1
- package/lib/es6/tinybase.js.gz +0 -0
- package/lib/es6/tools.d.ts +109 -38
- package/lib/es6/tools.js +1 -1
- package/lib/es6/tools.js.gz +0 -0
- package/lib/es6/ui-react.d.ts +1218 -138
- package/lib/es6/ui-react.js +1 -1
- package/lib/es6/ui-react.js.gz +0 -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/persisters.d.ts +33 -23
- package/lib/persisters.js +1 -1
- package/lib/persisters.js.gz +0 -0
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.d.ts +2053 -381
- 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/tools.d.ts +109 -38
- package/lib/tools.js +1 -1
- package/lib/tools.js.gz +0 -0
- package/lib/ui-react.d.ts +1218 -138
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.js.gz +0 -0
- package/lib/umd/checkpoints.d.ts +18 -3
- 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/persisters.d.ts +33 -23
- package/lib/umd/persisters.js +1 -1
- package/lib/umd/persisters.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.d.ts +2053 -381
- 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/lib/umd/tools.d.ts +109 -38
- package/lib/umd/tools.js +1 -1
- package/lib/umd/tools.js.gz +0 -0
- package/lib/umd/ui-react.d.ts +1218 -138
- package/lib/umd/ui-react.js +1 -1
- package/lib/umd/ui-react.js.gz +0 -0
- package/lib/umd-es6/checkpoints.d.ts +18 -3
- package/lib/umd-es6/checkpoints.js +1 -1
- package/lib/umd-es6/checkpoints.js.gz +0 -0
- package/lib/umd-es6/indexes.js +1 -1
- package/lib/umd-es6/indexes.js.gz +0 -0
- package/lib/umd-es6/metrics.js +1 -1
- package/lib/umd-es6/metrics.js.gz +0 -0
- package/lib/umd-es6/persisters.d.ts +33 -23
- package/lib/umd-es6/persisters.js +1 -1
- package/lib/umd-es6/persisters.js.gz +0 -0
- package/lib/umd-es6/relationships.js +1 -1
- package/lib/umd-es6/relationships.js.gz +0 -0
- package/lib/umd-es6/store.d.ts +2053 -381
- package/lib/umd-es6/store.js +1 -1
- package/lib/umd-es6/store.js.gz +0 -0
- package/lib/umd-es6/tinybase.js +1 -1
- package/lib/umd-es6/tinybase.js.gz +0 -0
- package/lib/umd-es6/tools.d.ts +109 -38
- package/lib/umd-es6/tools.js +1 -1
- package/lib/umd-es6/tools.js.gz +0 -0
- package/lib/umd-es6/ui-react.d.ts +1218 -138
- package/lib/umd-es6/ui-react.js +1 -1
- package/lib/umd-es6/ui-react.js.gz +0 -0
- package/package.json +20 -20
- package/readme.md +27 -16
package/bin/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
import{resolve as
|
|
2
|
+
import{resolve as e,dirname as t}from"path";import{writeFileSync as r,readFileSync as s}from"fs";import{createStore as o}from"tinybase";import{createTools as a}from"tinybase/tools";import{fileURLToPath as i}from"url";const n=JSON.parse,m=Object,p=(...e)=>{return t=e=>process.stdout.write(e+"\n"),e.forEach(t);var t},c=e=>n(s(e,"utf8")),f=()=>{var e,t;p("","tinybase <command>","","Usage:",""),e=l,t=([,e,t],r)=>p(` tinybase ${r} ${e}`," - "+t,""),((e,t)=>{e.map(t)})(m.entries(e),(([e,r])=>t(r,e))),p("See also http://tinybase.org/guides/developer-tools/command-line/","")},l={help:[f,"","print this message"],version:[()=>p(c(e(t(i(import.meta.url)),"../package.json")).version),"","get the current TinyBase version"],getStoreApi:[async(t,s,i)=>{try{const m=c(t),f=a(o().setSchema(...(n=m,Array.isArray(n)?m:[m]))),[l,u]=await f.getPrettyStoreApi(s),d=e(i,s+".d.ts"),h=e(i,s+".ts");r(d,l,"utf8"),r(h,u,"utf8"),p(" Definition: "+d,"Implementation: "+h)}catch{process.stderr.write("ERROR: provide a valid schemaFile, storeName, and outputDir\n")}var n},"<schemaFile> <storeName> <outputDir>","generate .d.ts and .ts files from a schema file"]};(()=>{const[,,e,...t]=process.argv;(l[e]?.[0]??f)(...t)})();
|
package/lib/checkpoints.d.ts
CHANGED
|
@@ -115,6 +115,8 @@ export type CheckpointsListenerStats = {
|
|
|
115
115
|
* method), and add listeners for when the list checkpoints changes (with the
|
|
116
116
|
* addCheckpointIdsListener method).
|
|
117
117
|
*
|
|
118
|
+
* Checkpoints work for both changes to tabular data and to keyed value data.
|
|
119
|
+
*
|
|
118
120
|
* Every checkpoint can be given a label which can be used to describe the
|
|
119
121
|
* actions that changed the Store before this checkpoint. This can be useful for
|
|
120
122
|
* interfaces that let users 'Undo [last action]'.
|
|
@@ -127,7 +129,9 @@ export type CheckpointsListenerStats = {
|
|
|
127
129
|
* registering and removing a listener for them.
|
|
128
130
|
*
|
|
129
131
|
* ```js
|
|
130
|
-
* const store = createStore()
|
|
132
|
+
* const store = createStore()
|
|
133
|
+
* .setTables({pets: {fido: {sold: false}}})
|
|
134
|
+
* .setValue('open', true);
|
|
131
135
|
*
|
|
132
136
|
* const checkpoints = createCheckpoints(store);
|
|
133
137
|
* checkpoints.setSize(200);
|
|
@@ -145,14 +149,25 @@ export type CheckpointsListenerStats = {
|
|
|
145
149
|
* console.log(checkpoints.getCheckpointIds());
|
|
146
150
|
* // -> [[], '0', ['1']]
|
|
147
151
|
*
|
|
152
|
+
* store.setValue('open', false);
|
|
153
|
+
* checkpoints.addCheckpoint('closed');
|
|
154
|
+
* console.log(checkpoints.getCheckpointIds());
|
|
155
|
+
* // -> [['0'], '2', []]
|
|
156
|
+
*
|
|
157
|
+
* checkpoints.goBackward();
|
|
158
|
+
* console.log(store.getValue('open'));
|
|
159
|
+
* // -> true
|
|
160
|
+
* console.log(checkpoints.getCheckpointIds());
|
|
161
|
+
* // -> [[], '0', ['2']]
|
|
162
|
+
*
|
|
148
163
|
* const listenerId = checkpoints.addCheckpointIdsListener(() => {
|
|
149
164
|
* console.log(checkpoints.getCheckpointIds());
|
|
150
165
|
* });
|
|
151
166
|
* store.setCell('pets', 'fido', 'species', 'dog');
|
|
152
167
|
* // -> [['0'], undefined, []]
|
|
153
168
|
* checkpoints.addCheckpoint();
|
|
154
|
-
* // -> [['0'], '
|
|
155
|
-
* // Previous redo of
|
|
169
|
+
* // -> [['0'], '3', []]
|
|
170
|
+
* // Previous redo of checkpoints '1' and '2' are now not possible.
|
|
156
171
|
*
|
|
157
172
|
* checkpoints.delListener(listenerId);
|
|
158
173
|
* checkpoints.destroy();
|
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),s=(e,...t)=>e.push(...t),o=e=>e.pop(),l=e=>e.shift(),c=e=>null==e,i=(e,t,n)=>c(e)?n?.():t(e),a=(e,t)=>e?.has(t)??!1,d=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),
|
|
1
|
+
const e=(e,t)=>e.includes(t),t=(e,t)=>e.forEach(t),n=e=>e.length,r=e=>0==n(e),s=(e,...t)=>e.push(...t),o=e=>e.pop(),l=e=>e.shift(),c=e=>null==e,i=(e,t,n)=>c(e)?n?.():t(e),a=(e,t)=>e?.has(t)??!1,d=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),f=(e,t,n)=>c(n)?(h(e,t),e):e?.set(t,n),g=(e,t,n)=>(a(e,t)||f(e,t,n()),C(e,t)),k=(e,t,r,s,o=0)=>i((r?g:C)(e,t[o],o>n(t)-2?r:p),(l=>{if(o>n(t)-2)return s?.(l)&&f(e,t[o]),l;const c=k(l,t,r,s,o+1);return d(l)&&f(e,t[o]),c})),L=e=>new Set(Array.isArray(e)||c(e)?e:[e]),v=/^\d+$/,w=Object.freeze,S=(S=>{const y=new WeakMap;return S=>(y.has(S)||y.set(S,(S=>{let y,z,E,V=100,A=p(),I=p(),M=1;const b=p(),j=p(),[x,B,F]=(e=>{let r;const[o,a]=(()=>{const e=[];let t=0;return[()=>l(e)??""+t++,t=>{v.test(t)&&n(e)<1e3&&s(e,t)}]})(),g=p();return[(e,t,n,s=[],l=(()=>[]))=>{r??=_;const c=o();var i;return f(g,c,[e,t,n,s,l]),i=c,k(t,n??[""],L)?.add(i),c},(e,o,...l)=>t(((e,r=[""])=>{const o=[],l=(e,c)=>c==n(r)?s(o,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),o})(e,o),(e=>u(e,(e=>C(g,e)[0](r,...o??[],...l))))),e=>i(C(g,e),(([,t,n])=>(k(t,n??[""],void 0,(t=>(h(t,e),d(t)?1:0))),f(g,e),a(e),n))),e=>i(C(g,e),(([e,,s=[],o,l])=>{const i=(...a)=>{const d=n(a);d==n(s)?e(r,...a,...l(a)):c(s[d])?t(o[d]?.(...a)??[],(e=>i(...a,e))):i(...a,s[d])};i()}))]})(),O=p(),T=p(),W=[],$=[],m=(e,t)=>{M=0,S.transaction((()=>{const[n,r]=C(O,t);u(n,((t,n)=>u(t,((t,r)=>u(t,((t,s)=>((e,t,n,r,s)=>c(s)?e.delCell(t,n,r,!0):e.setCell(t,n,r,s))(S,n,r,s,t[e]))))))),u(r,((t,n)=>((e,t,n)=>c(n)?e.delValue(t):e.setValue(t,n))(S,n,t[e])))})),M=1},q=e=>{f(O,e),f(T,e),B(j,[e])},D=(e,r)=>t(((e,t)=>e.splice(0,t))(e,r??n(e)),q),G=()=>D(W,n(W)-V),H=()=>i(y,(()=>{s(W,y),G(),D($),y=void 0,E=1})),J=()=>{y=o(W),E=1},K=S.addCellListener(null,null,null,((e,t,n,r,s,o)=>{if(M){H();const e=g(A,t,p),l=g(e,n,p),c=g(l,r,(()=>[o,void 0]));c[1]=s,c[0]===s&&d(f(l,r))&&d(f(e,n))&&d(f(A,t))&&J(),U()}})),N=S.addValueListener(null,((e,t,n,r)=>{if(M){H();const e=g(I,t,(()=>[r,void 0]));e[1]=n,e[0]===n&&d(f(I,t))&&J(),U()}})),P=(e="")=>(c(y)&&(y=""+z++,f(O,y,[A,I]),Y(y,e),A=p(),I=p(),E=1),y),Q=()=>{r(W)||(((e,...t)=>{e.unshift(...t)})($,P()),m(0,y),y=o(W),E=1)},R=()=>{r($)||(s(W,y),y=l($),m(1,y),E=1)},U=()=>{E&&(B(b),E=0)},X=e=>{const t=P(e);return U(),t},Y=(e,t)=>(Z(e)&&C(T,e)!==t&&(f(T,e,t),B(j,[e])),_),Z=e=>a(O,e),_={setSize:e=>(V=e,G(),_),addCheckpoint:X,setCheckpoint:Y,getStore:()=>S,getCheckpointIds:()=>[[...W],y,[...$]],forEachCheckpoint:e=>{return t=e,u(T,((e,n)=>t(n,e)));var t},hasCheckpoint:Z,getCheckpoint:e=>C(T,e),goBackward:()=>(Q(),U(),_),goForward:()=>(R(),U(),_),goTo:t=>{const n=e(W,t)?Q:e($,t)?R:null;for(;!c(n)&&t!=y;)n();return U(),_},addCheckpointIdsListener:e=>x(e,b),addCheckpointListener:(e,t)=>x(t,j,[e]),delListener:e=>(F(e),_),clear:()=>(D(W),D($),c(y)||q(y),y=void 0,z=0,X(),_),destroy:()=>{S.delListener(K),S.delListener(N)},getListenerStats:()=>({})};return w(_.clear())})(S)),y.get(S))})();export{S as createCheckpoints};
|
package/lib/checkpoints.js.gz
CHANGED
|
Binary file
|
|
@@ -115,6 +115,8 @@ export type CheckpointsListenerStats = {
|
|
|
115
115
|
* method), and add listeners for when the list checkpoints changes (with the
|
|
116
116
|
* addCheckpointIdsListener method).
|
|
117
117
|
*
|
|
118
|
+
* Checkpoints work for both changes to tabular data and to keyed value data.
|
|
119
|
+
*
|
|
118
120
|
* Every checkpoint can be given a label which can be used to describe the
|
|
119
121
|
* actions that changed the Store before this checkpoint. This can be useful for
|
|
120
122
|
* interfaces that let users 'Undo [last action]'.
|
|
@@ -127,7 +129,9 @@ export type CheckpointsListenerStats = {
|
|
|
127
129
|
* registering and removing a listener for them.
|
|
128
130
|
*
|
|
129
131
|
* ```js
|
|
130
|
-
* const store = createStore()
|
|
132
|
+
* const store = createStore()
|
|
133
|
+
* .setTables({pets: {fido: {sold: false}}})
|
|
134
|
+
* .setValue('open', true);
|
|
131
135
|
*
|
|
132
136
|
* const checkpoints = createCheckpoints(store);
|
|
133
137
|
* checkpoints.setSize(200);
|
|
@@ -145,14 +149,25 @@ export type CheckpointsListenerStats = {
|
|
|
145
149
|
* console.log(checkpoints.getCheckpointIds());
|
|
146
150
|
* // -> [[], '0', ['1']]
|
|
147
151
|
*
|
|
152
|
+
* store.setValue('open', false);
|
|
153
|
+
* checkpoints.addCheckpoint('closed');
|
|
154
|
+
* console.log(checkpoints.getCheckpointIds());
|
|
155
|
+
* // -> [['0'], '2', []]
|
|
156
|
+
*
|
|
157
|
+
* checkpoints.goBackward();
|
|
158
|
+
* console.log(store.getValue('open'));
|
|
159
|
+
* // -> true
|
|
160
|
+
* console.log(checkpoints.getCheckpointIds());
|
|
161
|
+
* // -> [[], '0', ['2']]
|
|
162
|
+
*
|
|
148
163
|
* const listenerId = checkpoints.addCheckpointIdsListener(() => {
|
|
149
164
|
* console.log(checkpoints.getCheckpointIds());
|
|
150
165
|
* });
|
|
151
166
|
* store.setCell('pets', 'fido', 'species', 'dog');
|
|
152
167
|
* // -> [['0'], undefined, []]
|
|
153
168
|
* checkpoints.addCheckpoint();
|
|
154
|
-
* // -> [['0'], '
|
|
155
|
-
* // Previous redo of
|
|
169
|
+
* // -> [['0'], '3', []]
|
|
170
|
+
* // Previous redo of checkpoints '1' and '2' are now not possible.
|
|
156
171
|
*
|
|
157
172
|
* checkpoints.delListener(listenerId);
|
|
158
173
|
* checkpoints.destroy();
|
package/lib/debug/checkpoints.js
CHANGED
|
@@ -61,6 +61,13 @@ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
|
|
|
61
61
|
},
|
|
62
62
|
);
|
|
63
63
|
|
|
64
|
+
const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
|
|
65
|
+
isUndefined(cell)
|
|
66
|
+
? store.delCell(tableId, rowId, cellId, true)
|
|
67
|
+
: store.setCell(tableId, rowId, cellId, cell);
|
|
68
|
+
const setOrDelValue = (store, valueId, value) =>
|
|
69
|
+
isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
|
|
70
|
+
|
|
64
71
|
const setNew = (entryOrEntries) =>
|
|
65
72
|
new Set(
|
|
66
73
|
isArray(entryOrEntries) || isUndefined(entryOrEntries)
|
|
@@ -108,10 +115,22 @@ const getListenerFunctions = (getThing) => {
|
|
|
108
115
|
let thing;
|
|
109
116
|
const [getId, releaseId] = getPoolFunctions();
|
|
110
117
|
const allListeners = mapNew();
|
|
111
|
-
const addListener = (
|
|
118
|
+
const addListener = (
|
|
119
|
+
listener,
|
|
120
|
+
idSetNode,
|
|
121
|
+
path,
|
|
122
|
+
pathGetters = [],
|
|
123
|
+
extraArgsGetter = () => [],
|
|
124
|
+
) => {
|
|
112
125
|
thing ??= getThing();
|
|
113
126
|
const id = getId();
|
|
114
|
-
mapSet(allListeners, id, [
|
|
127
|
+
mapSet(allListeners, id, [
|
|
128
|
+
listener,
|
|
129
|
+
idSetNode,
|
|
130
|
+
path,
|
|
131
|
+
pathGetters,
|
|
132
|
+
extraArgsGetter,
|
|
133
|
+
]);
|
|
115
134
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
116
135
|
return id;
|
|
117
136
|
};
|
|
@@ -131,35 +150,34 @@ const getListenerFunctions = (getThing) => {
|
|
|
131
150
|
releaseId(id);
|
|
132
151
|
return idOrNulls;
|
|
133
152
|
});
|
|
134
|
-
const callListener = (id
|
|
135
|
-
ifNotUndefined(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
153
|
+
const callListener = (id) =>
|
|
154
|
+
ifNotUndefined(
|
|
155
|
+
mapGet(allListeners, id),
|
|
156
|
+
([listener, , path = [], pathGetters, extraArgsGetter]) => {
|
|
157
|
+
const callWithIds = (...ids) => {
|
|
158
|
+
const index = arrayLength(ids);
|
|
159
|
+
index == arrayLength(path)
|
|
160
|
+
? listener(thing, ...ids, ...extraArgsGetter(ids))
|
|
161
|
+
: isUndefined(path[index])
|
|
162
|
+
? arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
|
|
163
|
+
callWithIds(...ids, id2),
|
|
164
|
+
)
|
|
165
|
+
: callWithIds(...ids, path[index]);
|
|
166
|
+
};
|
|
167
|
+
callWithIds();
|
|
168
|
+
},
|
|
169
|
+
);
|
|
148
170
|
return [addListener, callListeners, delListener, callListener];
|
|
149
171
|
};
|
|
150
172
|
|
|
151
173
|
const object = Object;
|
|
152
174
|
const objFreeze = object.freeze;
|
|
153
175
|
|
|
154
|
-
const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
|
|
155
|
-
isUndefined(cell)
|
|
156
|
-
? store.delCell(tableId, rowId, cellId, true)
|
|
157
|
-
: store.setCell(tableId, rowId, cellId, cell);
|
|
158
|
-
|
|
159
176
|
const createCheckpoints = getCreateFunction((store) => {
|
|
160
177
|
let backwardIdsSize = 100;
|
|
161
178
|
let currentId;
|
|
162
|
-
let
|
|
179
|
+
let cellsDelta = mapNew();
|
|
180
|
+
let valuesDelta = mapNew();
|
|
163
181
|
let listening = 1;
|
|
164
182
|
let nextCheckpointId;
|
|
165
183
|
let checkpointsChanged;
|
|
@@ -174,15 +192,19 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
174
192
|
const forwardIds = [];
|
|
175
193
|
const updateStore = (oldOrNew, checkpointId) => {
|
|
176
194
|
listening = 0;
|
|
177
|
-
store.transaction(() =>
|
|
178
|
-
|
|
195
|
+
store.transaction(() => {
|
|
196
|
+
const [cellsDelta2, valuesDelta2] = mapGet(deltas, checkpointId);
|
|
197
|
+
collForEach(cellsDelta2, (table, tableId) =>
|
|
179
198
|
collForEach(table, (row, rowId) =>
|
|
180
199
|
collForEach(row, (oldNew, cellId) =>
|
|
181
200
|
setOrDelCell(store, tableId, rowId, cellId, oldNew[oldOrNew]),
|
|
182
201
|
),
|
|
183
202
|
),
|
|
184
|
-
)
|
|
185
|
-
|
|
203
|
+
);
|
|
204
|
+
collForEach(valuesDelta2, (oldNew, valueId) =>
|
|
205
|
+
setOrDelValue(store, valueId, oldNew[oldOrNew]),
|
|
206
|
+
);
|
|
207
|
+
});
|
|
186
208
|
listening = 1;
|
|
187
209
|
};
|
|
188
210
|
const clearCheckpointId = (checkpointId) => {
|
|
@@ -197,32 +219,56 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
197
219
|
);
|
|
198
220
|
const trimBackwardsIds = () =>
|
|
199
221
|
clearCheckpointIds(backwardIds, arrayLength(backwardIds) - backwardIdsSize);
|
|
200
|
-
const
|
|
222
|
+
const storeChanged = () =>
|
|
223
|
+
ifNotUndefined(currentId, () => {
|
|
224
|
+
arrayPush(backwardIds, currentId);
|
|
225
|
+
trimBackwardsIds();
|
|
226
|
+
clearCheckpointIds(forwardIds);
|
|
227
|
+
currentId = void 0;
|
|
228
|
+
checkpointsChanged = 1;
|
|
229
|
+
});
|
|
230
|
+
const storeUnchanged = () => {
|
|
231
|
+
currentId = arrayPop(backwardIds);
|
|
232
|
+
checkpointsChanged = 1;
|
|
233
|
+
};
|
|
234
|
+
const cellListenerId = store.addCellListener(
|
|
201
235
|
null,
|
|
202
236
|
null,
|
|
203
237
|
null,
|
|
204
238
|
(_store, tableId, rowId, cellId, newCell, oldCell) => {
|
|
205
239
|
if (listening) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
trimBackwardsIds();
|
|
209
|
-
clearCheckpointIds(forwardIds);
|
|
210
|
-
currentId = void 0;
|
|
211
|
-
checkpointsChanged = 1;
|
|
212
|
-
});
|
|
213
|
-
const table = mapEnsure(delta, tableId, mapNew);
|
|
240
|
+
storeChanged();
|
|
241
|
+
const table = mapEnsure(cellsDelta, tableId, mapNew);
|
|
214
242
|
const row = mapEnsure(table, rowId, mapNew);
|
|
215
243
|
const oldNew = mapEnsure(row, cellId, () => [oldCell, void 0]);
|
|
216
244
|
oldNew[1] = newCell;
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
245
|
+
if (
|
|
246
|
+
oldNew[0] === newCell &&
|
|
247
|
+
collIsEmpty(mapSet(row, cellId)) &&
|
|
248
|
+
collIsEmpty(mapSet(table, rowId)) &&
|
|
249
|
+
collIsEmpty(mapSet(cellsDelta, tableId))
|
|
250
|
+
) {
|
|
251
|
+
storeUnchanged();
|
|
252
|
+
}
|
|
253
|
+
callListenersIfChanged();
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
);
|
|
257
|
+
const valueListenerId = store.addValueListener(
|
|
258
|
+
null,
|
|
259
|
+
(_store, valueId, newValue, oldValue) => {
|
|
260
|
+
if (listening) {
|
|
261
|
+
storeChanged();
|
|
262
|
+
const oldNew = mapEnsure(valuesDelta, valueId, () => [
|
|
263
|
+
oldValue,
|
|
264
|
+
void 0,
|
|
265
|
+
]);
|
|
266
|
+
oldNew[1] = newValue;
|
|
267
|
+
if (
|
|
268
|
+
oldNew[0] === newValue &&
|
|
269
|
+
collIsEmpty(mapSet(valuesDelta, valueId))
|
|
270
|
+
) {
|
|
271
|
+
storeUnchanged();
|
|
226
272
|
}
|
|
227
273
|
callListenersIfChanged();
|
|
228
274
|
}
|
|
@@ -231,9 +277,10 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
231
277
|
const addCheckpointImpl = (label = EMPTY_STRING) => {
|
|
232
278
|
if (isUndefined(currentId)) {
|
|
233
279
|
currentId = EMPTY_STRING + nextCheckpointId++;
|
|
234
|
-
mapSet(deltas, currentId,
|
|
280
|
+
mapSet(deltas, currentId, [cellsDelta, valuesDelta]);
|
|
235
281
|
setCheckpoint(currentId, label);
|
|
236
|
-
|
|
282
|
+
cellsDelta = mapNew();
|
|
283
|
+
valuesDelta = mapNew();
|
|
237
284
|
checkpointsChanged = 1;
|
|
238
285
|
}
|
|
239
286
|
return currentId;
|
|
@@ -309,8 +356,8 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
309
356
|
addListener(listener, checkpointIdsListeners);
|
|
310
357
|
const addCheckpointListener = (checkpointId, listener) =>
|
|
311
358
|
addListener(listener, checkpointListeners, [checkpointId]);
|
|
312
|
-
const delListener = (
|
|
313
|
-
delListenerImpl(
|
|
359
|
+
const delListener = (listenerId) => {
|
|
360
|
+
delListenerImpl(listenerId);
|
|
314
361
|
return checkpoints;
|
|
315
362
|
};
|
|
316
363
|
const clear = () => {
|
|
@@ -325,7 +372,8 @@ const createCheckpoints = getCreateFunction((store) => {
|
|
|
325
372
|
return checkpoints;
|
|
326
373
|
};
|
|
327
374
|
const destroy = () => {
|
|
328
|
-
store.delListener(
|
|
375
|
+
store.delListener(cellListenerId);
|
|
376
|
+
store.delListener(valueListenerId);
|
|
329
377
|
};
|
|
330
378
|
const getListenerStats = () => ({
|
|
331
379
|
checkpointIds: collSize2(checkpointIdsListeners),
|
package/lib/debug/indexes.js
CHANGED
|
@@ -272,10 +272,22 @@ const getListenerFunctions = (getThing) => {
|
|
|
272
272
|
let thing;
|
|
273
273
|
const [getId, releaseId] = getPoolFunctions();
|
|
274
274
|
const allListeners = mapNew();
|
|
275
|
-
const addListener = (
|
|
275
|
+
const addListener = (
|
|
276
|
+
listener,
|
|
277
|
+
idSetNode,
|
|
278
|
+
path,
|
|
279
|
+
pathGetters = [],
|
|
280
|
+
extraArgsGetter = () => [],
|
|
281
|
+
) => {
|
|
276
282
|
thing ??= getThing();
|
|
277
283
|
const id = getId();
|
|
278
|
-
mapSet(allListeners, id, [
|
|
284
|
+
mapSet(allListeners, id, [
|
|
285
|
+
listener,
|
|
286
|
+
idSetNode,
|
|
287
|
+
path,
|
|
288
|
+
pathGetters,
|
|
289
|
+
extraArgsGetter,
|
|
290
|
+
]);
|
|
279
291
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
280
292
|
return id;
|
|
281
293
|
};
|
|
@@ -295,20 +307,23 @@ const getListenerFunctions = (getThing) => {
|
|
|
295
307
|
releaseId(id);
|
|
296
308
|
return idOrNulls;
|
|
297
309
|
});
|
|
298
|
-
const callListener = (id
|
|
299
|
-
ifNotUndefined(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
const callListener = (id) =>
|
|
311
|
+
ifNotUndefined(
|
|
312
|
+
mapGet(allListeners, id),
|
|
313
|
+
([listener, , path = [], pathGetters, extraArgsGetter]) => {
|
|
314
|
+
const callWithIds = (...ids) => {
|
|
315
|
+
const index = arrayLength(ids);
|
|
316
|
+
index == arrayLength(path)
|
|
317
|
+
? listener(thing, ...ids, ...extraArgsGetter(ids))
|
|
318
|
+
: isUndefined(path[index])
|
|
319
|
+
? arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
|
|
320
|
+
callWithIds(...ids, id2),
|
|
321
|
+
)
|
|
322
|
+
: callWithIds(...ids, path[index]);
|
|
323
|
+
};
|
|
324
|
+
callWithIds();
|
|
325
|
+
},
|
|
326
|
+
);
|
|
312
327
|
return [addListener, callListeners, delListener, callListener];
|
|
313
328
|
};
|
|
314
329
|
|
package/lib/debug/metrics.js
CHANGED
|
@@ -341,10 +341,22 @@ const getListenerFunctions = (getThing) => {
|
|
|
341
341
|
let thing;
|
|
342
342
|
const [getId, releaseId] = getPoolFunctions();
|
|
343
343
|
const allListeners = mapNew();
|
|
344
|
-
const addListener = (
|
|
344
|
+
const addListener = (
|
|
345
|
+
listener,
|
|
346
|
+
idSetNode,
|
|
347
|
+
path,
|
|
348
|
+
pathGetters = [],
|
|
349
|
+
extraArgsGetter = () => [],
|
|
350
|
+
) => {
|
|
345
351
|
thing ??= getThing();
|
|
346
352
|
const id = getId();
|
|
347
|
-
mapSet(allListeners, id, [
|
|
353
|
+
mapSet(allListeners, id, [
|
|
354
|
+
listener,
|
|
355
|
+
idSetNode,
|
|
356
|
+
path,
|
|
357
|
+
pathGetters,
|
|
358
|
+
extraArgsGetter,
|
|
359
|
+
]);
|
|
348
360
|
setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
|
|
349
361
|
return id;
|
|
350
362
|
};
|
|
@@ -364,20 +376,23 @@ const getListenerFunctions = (getThing) => {
|
|
|
364
376
|
releaseId(id);
|
|
365
377
|
return idOrNulls;
|
|
366
378
|
});
|
|
367
|
-
const callListener = (id
|
|
368
|
-
ifNotUndefined(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
const callListener = (id) =>
|
|
380
|
+
ifNotUndefined(
|
|
381
|
+
mapGet(allListeners, id),
|
|
382
|
+
([listener, , path = [], pathGetters, extraArgsGetter]) => {
|
|
383
|
+
const callWithIds = (...ids) => {
|
|
384
|
+
const index = arrayLength(ids);
|
|
385
|
+
index == arrayLength(path)
|
|
386
|
+
? listener(thing, ...ids, ...extraArgsGetter(ids))
|
|
387
|
+
: isUndefined(path[index])
|
|
388
|
+
? arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
|
|
389
|
+
callWithIds(...ids, id2),
|
|
390
|
+
)
|
|
391
|
+
: callWithIds(...ids, path[index]);
|
|
392
|
+
};
|
|
393
|
+
callWithIds();
|
|
394
|
+
},
|
|
395
|
+
);
|
|
381
396
|
return [addListener, callListeners, delListener, callListener];
|
|
382
397
|
};
|
|
383
398
|
|