tinybase 2.1.0 → 2.2.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 (105) hide show
  1. package/bin/cli.js +2 -0
  2. package/lib/checkpoints.d.ts +0 -2
  3. package/lib/checkpoints.js +1 -1
  4. package/lib/checkpoints.js.gz +0 -0
  5. package/lib/debug/checkpoints.d.ts +0 -2
  6. package/lib/debug/checkpoints.js +4 -2
  7. package/lib/debug/indexes.d.ts +0 -2
  8. package/lib/debug/indexes.js +2 -1
  9. package/lib/debug/metrics.d.ts +0 -2
  10. package/lib/debug/metrics.js +2 -1
  11. package/lib/debug/queries.d.ts +0 -2
  12. package/lib/debug/relationships.d.ts +0 -2
  13. package/lib/debug/relationships.js +2 -1
  14. package/lib/debug/store.d.ts +1 -1
  15. package/lib/debug/store.js +12 -13
  16. package/lib/debug/tinybase.js +14 -14
  17. package/lib/debug/tools.d.ts +290 -0
  18. package/lib/debug/tools.js +955 -0
  19. package/lib/es6/checkpoints.d.ts +0 -2
  20. package/lib/es6/checkpoints.js +1 -1
  21. package/lib/es6/checkpoints.js.gz +0 -0
  22. package/lib/es6/indexes.d.ts +0 -2
  23. package/lib/es6/metrics.d.ts +0 -2
  24. package/lib/es6/queries.d.ts +0 -2
  25. package/lib/es6/relationships.d.ts +0 -2
  26. package/lib/es6/store.d.ts +1 -1
  27. package/lib/es6/store.js +1 -1
  28. package/lib/es6/store.js.gz +0 -0
  29. package/lib/es6/tinybase.js +1 -1
  30. package/lib/es6/tinybase.js.gz +0 -0
  31. package/lib/es6/tools.d.ts +290 -0
  32. package/lib/es6/tools.js +1 -0
  33. package/lib/es6/tools.js.gz +0 -0
  34. package/lib/indexes.d.ts +0 -2
  35. package/lib/metrics.d.ts +0 -2
  36. package/lib/queries.d.ts +0 -2
  37. package/lib/relationships.d.ts +0 -2
  38. package/lib/store.d.ts +1 -1
  39. package/lib/store.js +1 -1
  40. package/lib/store.js.gz +0 -0
  41. package/lib/tinybase.js +1 -1
  42. package/lib/tinybase.js.gz +0 -0
  43. package/lib/tools.d.ts +290 -0
  44. package/lib/tools.js +1 -0
  45. package/lib/tools.js.gz +0 -0
  46. package/lib/umd/checkpoints.d.ts +0 -2
  47. package/lib/umd/checkpoints.js +1 -1
  48. package/lib/umd/checkpoints.js.gz +0 -0
  49. package/lib/umd/common.js +1 -1
  50. package/lib/umd/common.js.gz +0 -0
  51. package/lib/umd/indexes.d.ts +0 -2
  52. package/lib/umd/indexes.js +1 -1
  53. package/lib/umd/indexes.js.gz +0 -0
  54. package/lib/umd/metrics.d.ts +0 -2
  55. package/lib/umd/metrics.js +1 -1
  56. package/lib/umd/metrics.js.gz +0 -0
  57. package/lib/umd/persisters.js +1 -1
  58. package/lib/umd/persisters.js.gz +0 -0
  59. package/lib/umd/queries.d.ts +0 -2
  60. package/lib/umd/queries.js +1 -1
  61. package/lib/umd/queries.js.gz +0 -0
  62. package/lib/umd/relationships.d.ts +0 -2
  63. package/lib/umd/relationships.js +1 -1
  64. package/lib/umd/relationships.js.gz +0 -0
  65. package/lib/umd/store.d.ts +1 -1
  66. package/lib/umd/store.js +1 -1
  67. package/lib/umd/store.js.gz +0 -0
  68. package/lib/umd/tinybase.js +1 -1
  69. package/lib/umd/tinybase.js.gz +0 -0
  70. package/lib/umd/tools.d.ts +290 -0
  71. package/lib/umd/tools.js +1 -0
  72. package/lib/umd/tools.js.gz +0 -0
  73. package/lib/umd/ui-react.js +1 -1
  74. package/lib/umd/ui-react.js.gz +0 -0
  75. package/lib/umd-es6/checkpoints.d.ts +0 -2
  76. package/lib/umd-es6/checkpoints.js +1 -1
  77. package/lib/umd-es6/checkpoints.js.gz +0 -0
  78. package/lib/umd-es6/common.js +1 -1
  79. package/lib/umd-es6/common.js.gz +0 -0
  80. package/lib/umd-es6/indexes.d.ts +0 -2
  81. package/lib/umd-es6/indexes.js +1 -1
  82. package/lib/umd-es6/indexes.js.gz +0 -0
  83. package/lib/umd-es6/metrics.d.ts +0 -2
  84. package/lib/umd-es6/metrics.js +1 -1
  85. package/lib/umd-es6/metrics.js.gz +0 -0
  86. package/lib/umd-es6/persisters.js +1 -1
  87. package/lib/umd-es6/persisters.js.gz +0 -0
  88. package/lib/umd-es6/queries.d.ts +0 -2
  89. package/lib/umd-es6/queries.js +1 -1
  90. package/lib/umd-es6/queries.js.gz +0 -0
  91. package/lib/umd-es6/relationships.d.ts +0 -2
  92. package/lib/umd-es6/relationships.js +1 -1
  93. package/lib/umd-es6/relationships.js.gz +0 -0
  94. package/lib/umd-es6/store.d.ts +1 -1
  95. package/lib/umd-es6/store.js +1 -1
  96. package/lib/umd-es6/store.js.gz +0 -0
  97. package/lib/umd-es6/tinybase.js +1 -1
  98. package/lib/umd-es6/tinybase.js.gz +0 -0
  99. package/lib/umd-es6/tools.d.ts +290 -0
  100. package/lib/umd-es6/tools.js +1 -0
  101. package/lib/umd-es6/tools.js.gz +0 -0
  102. package/lib/umd-es6/ui-react.js +1 -1
  103. package/lib/umd-es6/ui-react.js.gz +0 -0
  104. package/package.json +36 -27
  105. package/readme.md +12 -12
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #! /usr/bin/env node
2
+ (()=>{const[,,o,...s]=process.argv;if("pwd"!==o)return console.dir(s),void console.log("Commands: [pwd]");console.log(process.cwd())})();
@@ -913,8 +913,6 @@ export interface Checkpoints {
913
913
  * The createCheckpoints function creates a Checkpoints object, and is the main
914
914
  * entry point into the checkpoints module.
915
915
  *
916
- * It is trivially simple.
917
- *
918
916
  * A given Store can only have one Checkpoints object associated with it. If you
919
917
  * call this function twice on the same Store, your second call will return a
920
918
  * reference to the Checkpoints object created by the first.
@@ -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),g=(e,t,n)=>c(n)?(h(e,t),e):e?.set(t,n),k=(e,t,n)=>(a(e,t)||g(e,t,n()),C(e,t)),f=(e,t,r,s,o=0)=>i((r?k:C)(e,t[o],o>n(t)-2?r:p),(l=>{if(o>n(t)-2)return s?.(l)&&g(e,t[o]),l;const c=f(l,t,r,s,o+1);return d(l)&&g(e,t[o]),c})),v=e=>new Set(Array.isArray(e)||c(e)?e:[e]),L=/^\d+$/,w=e=>{let r;const[o,a]=(()=>{const e=[];let t=0;return[()=>l(e)??""+t++,t=>{L.test(t)&&n(e)<1e3&&s(e,t)}]})(),k=p();return[(t,n,s)=>{r??=e();const l=o();var c,i;return g(k,l,[t,n,s]),c=f(n,s??[""],v),i=l,c?.add(i),l},(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(k,e)[0](r,...o??[],...l))))),e=>i(C(k,e),(([,t,n])=>(f(t,n??[""],void 0,(t=>(h(t,e),d(t)?1:0))),g(k,e),a(e),n))),(e,s,o)=>i(C(k,e),(([e,,l=[]])=>{const i=(...a)=>{const d=n(a);d==n(l)?e(r,...a,...o(a)):c(l[d])?t(s[d](...a),(e=>i(...a,e))):i(...a,l[d])};i()}))]},S=Object.freeze,y=(e=>{const t=new WeakMap;return n=>(t.has(n)||t.set(n,e(n)),t.get(n))})((h=>{let f,v,L,y=100,z=p(),E=1;const A=p(),I=p(),[M,b,j]=w((()=>Q)),x=p(),B=p(),F=[],O=[],T=(e,t)=>{E=0,h.transaction((()=>u(C(x,t),((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))(h,n,r,s,t[e]))))))))),E=1},W=e=>{g(x,e),g(B,e),b(I,[e])},$=(e,r)=>t(((e,t)=>e.splice(0,t))(e,r??n(e)),W),m=()=>$(F,n(F)-y),q=h.addCellListener(null,null,null,((e,t,n,r,l,c)=>{if(E){i(f,(()=>{s(F,f),m(),$(O),f=void 0,L=1}));const e=k(z,t,p),a=k(e,n,p),u=k(a,r,(()=>[c,void 0]));u[1]=l,u[0]===l&&d(g(a,r))&&d(g(e,n))&&d(g(z,t))&&(f=o(F),L=1),J()}})),D=(e="")=>(c(f)&&(f=""+v++,g(x,f,z),N(f,e),z=p(),L=1),f),G=()=>{r(F)||(O.unshift(D()),T(0,f),f=o(F),L=1)},H=()=>{r(O)||(s(F,f),f=l(O),T(1,f),L=1)},J=()=>{L&&(b(A),L=0)},K=e=>{const t=D(e);return J(),t},N=(e,t)=>(P(e)&&C(B,e)!==t&&(g(B,e,t),b(I,[e])),Q),P=e=>a(x,e),Q={setSize:e=>(y=e,m(),Q),addCheckpoint:K,setCheckpoint:N,getStore:()=>h,getCheckpointIds:()=>[[...F],f,[...O]],forEachCheckpoint:e=>{return t=e,u(B,((e,n)=>t(n,e)));var t},hasCheckpoint:P,getCheckpoint:e=>C(B,e),goBackward:()=>(G(),J(),Q),goForward:()=>(H(),J(),Q),goTo:t=>{const n=e(F,t)?G:e(O,t)?H:null;for(;!c(n)&&t!=f;)n();return J(),Q},addCheckpointIdsListener:e=>M(e,A),addCheckpointListener:(e,t)=>M(t,I,[e]),delListener:e=>(j(e),Q),clear:()=>($(F),$(O),c(f)||W(f),f=void 0,v=0,K(),Q),destroy:()=>{h.delListener(q)},getListenerStats:()=>({})};return S(Q.clear())}));export{y as createCheckpoints};
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),g=(e,t,n)=>c(n)?(h(e,t),e):e?.set(t,n),k=(e,t,n)=>(a(e,t)||g(e,t,n()),C(e,t)),f=(e,t,r,s,o=0)=>i((r?k:C)(e,t[o],o>n(t)-2?r:p),(l=>{if(o>n(t)-2)return s?.(l)&&g(e,t[o]),l;const c=f(l,t,r,s,o+1);return d(l)&&g(e,t[o]),c})),v=e=>new Set(Array.isArray(e)||c(e)?e:[e]),L=/^\d+$/,w=e=>{let r;const[o,a]=(()=>{const e=[];let t=0;return[()=>l(e)??""+t++,t=>{L.test(t)&&n(e)<1e3&&s(e,t)}]})(),k=p();return[(t,n,s)=>{r??=e();const l=o();var c,i;return g(k,l,[t,n,s]),c=f(n,s??[""],v),i=l,c?.add(i),l},(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(k,e)[0](r,...o??[],...l))))),e=>i(C(k,e),(([,t,n])=>(f(t,n??[""],void 0,(t=>(h(t,e),d(t)?1:0))),g(k,e),a(e),n))),(e,s,o)=>i(C(k,e),(([e,,l=[]])=>{const i=(...a)=>{const d=n(a);d==n(l)?e(r,...a,...o(a)):c(l[d])?t(s[d](...a),(e=>i(...a,e))):i(...a,l[d])};i()}))]},S=Object.freeze,y=(e=>{const t=new WeakMap;return n=>(t.has(n)||t.set(n,e(n)),t.get(n))})((h=>{let f,v,L,y=100,z=p(),E=1;const A=p(),I=p(),[M,b,j]=w((()=>Q)),x=p(),B=p(),F=[],O=[],T=(e,t)=>{E=0,h.transaction((()=>u(C(x,t),((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))(h,n,r,s,t[e]))))))))),E=1},W=e=>{g(x,e),g(B,e),b(I,[e])},$=(e,r)=>t(((e,t)=>e.splice(0,t))(e,r??n(e)),W),m=()=>$(F,n(F)-y),q=h.addCellListener(null,null,null,((e,t,n,r,l,c)=>{if(E){i(f,(()=>{s(F,f),m(),$(O),f=void 0,L=1}));const e=k(z,t,p),a=k(e,n,p),u=k(a,r,(()=>[c,void 0]));u[1]=l,u[0]===l&&d(g(a,r))&&d(g(e,n))&&d(g(z,t))&&(f=o(F),L=1),J()}})),D=(e="")=>(c(f)&&(f=""+v++,g(x,f,z),N(f,e),z=p(),L=1),f),G=()=>{r(F)||(((e,...t)=>{e.unshift(...t)})(O,D()),T(0,f),f=o(F),L=1)},H=()=>{r(O)||(s(F,f),f=l(O),T(1,f),L=1)},J=()=>{L&&(b(A),L=0)},K=e=>{const t=D(e);return J(),t},N=(e,t)=>(P(e)&&C(B,e)!==t&&(g(B,e,t),b(I,[e])),Q),P=e=>a(x,e),Q={setSize:e=>(y=e,m(),Q),addCheckpoint:K,setCheckpoint:N,getStore:()=>h,getCheckpointIds:()=>[[...F],f,[...O]],forEachCheckpoint:e=>{return t=e,u(B,((e,n)=>t(n,e)));var t},hasCheckpoint:P,getCheckpoint:e=>C(B,e),goBackward:()=>(G(),J(),Q),goForward:()=>(H(),J(),Q),goTo:t=>{const n=e(F,t)?G:e(O,t)?H:null;for(;!c(n)&&t!=f;)n();return J(),Q},addCheckpointIdsListener:e=>M(e,A),addCheckpointListener:(e,t)=>M(t,I,[e]),delListener:e=>(j(e),Q),clear:()=>($(F),$(O),c(f)||W(f),f=void 0,v=0,K(),Q),destroy:()=>{h.delListener(q)},getListenerStats:()=>({})};return S(Q.clear())}));export{y as createCheckpoints};
Binary file
@@ -913,8 +913,6 @@ export interface Checkpoints {
913
913
  * The createCheckpoints function creates a Checkpoints object, and is the main
914
914
  * entry point into the checkpoints module.
915
915
  *
916
- * It is trivially simple.
917
- *
918
916
  * A given Store can only have one Checkpoints object associated with it. If you
919
917
  * call this function twice on the same Store, your second call will return a
920
918
  * reference to the Checkpoints object created by the first.
@@ -8,12 +8,14 @@ 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 arrayUnshift = (array, ...values) => array.unshift(...values);
11
12
  const arrayShift = (array) => array.shift();
12
13
 
13
14
  const isUndefined = (thing) => thing == void 0;
14
15
  const ifNotUndefined = (value, then, otherwise) =>
15
16
  isUndefined(value) ? otherwise?.() : then(value);
16
17
  const isArray = (thing) => Array.isArray(thing);
18
+ const test = (regex, subject) => regex.test(subject);
17
19
 
18
20
  const collSizeN = (collSizer) => (coll) =>
19
21
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -84,7 +86,7 @@ const getPoolFunctions = () => {
84
86
  return [
85
87
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
86
88
  (id) => {
87
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
89
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
88
90
  arrayPush(pool, id);
89
91
  }
90
92
  },
@@ -238,7 +240,7 @@ const createCheckpoints = getCreateFunction((store) => {
238
240
  };
239
241
  const goBackwardImpl = () => {
240
242
  if (!arrayIsEmpty(backwardIds)) {
241
- forwardIds.unshift(addCheckpointImpl());
243
+ arrayUnshift(forwardIds, addCheckpointImpl());
242
244
  updateStore(0, currentId);
243
245
  currentId = arrayPop(backwardIds);
244
246
  checkpointsChanged = 1;
@@ -935,8 +935,6 @@ export interface Indexes {
935
935
  * The createIndexes function creates an Indexes object, and is the main entry
936
936
  * point into the indexes module.
937
937
  *
938
- * It is trivially simple.
939
- *
940
938
  * A given Store can only have one Indexes object associated with it. If you
941
939
  * call this function twice on the same Store, your second call will return a
942
940
  * reference to the Indexes object created by the first.
@@ -26,6 +26,7 @@ const ifNotUndefined = (value, then, otherwise) =>
26
26
  isUndefined(value) ? otherwise?.() : then(value);
27
27
  const isString = (thing) => getTypeOf(thing) == STRING;
28
28
  const isArray = (thing) => Array.isArray(thing);
29
+ const test = (regex, subject) => regex.test(subject);
29
30
 
30
31
  const collSizeN = (collSizer) => (coll) =>
31
32
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -249,7 +250,7 @@ const getPoolFunctions = () => {
249
250
  return [
250
251
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
251
252
  (id) => {
252
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
253
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
253
254
  arrayPush(pool, id);
254
255
  }
255
256
  },
@@ -796,8 +796,6 @@ export interface Metrics {
796
796
  * The createMetrics function creates a Metrics object, and is the main entry
797
797
  * point into the metrics module.
798
798
  *
799
- * It is trivially simple.
800
- *
801
799
  * A given Store can only have one Metrics object associated with it. If you
802
800
  * call this function twice on the same Store, your second call will return a
803
801
  * reference to the Metrics object created by the first.
@@ -28,6 +28,7 @@ const ifNotUndefined = (value, then, otherwise) =>
28
28
  const isString = (thing) => getTypeOf(thing) == STRING;
29
29
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
30
30
  const isArray = (thing) => Array.isArray(thing);
31
+ const test = (regex, subject) => regex.test(subject);
31
32
  const getUndefined = () => void 0;
32
33
 
33
34
  const collSizeN = (collSizer) => (coll) =>
@@ -318,7 +319,7 @@ const getPoolFunctions = () => {
318
319
  return [
319
320
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
320
321
  (id) => {
321
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
322
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
322
323
  arrayPush(pool, id);
323
324
  }
324
325
  },
@@ -2992,8 +2992,6 @@ export interface Queries {
2992
2992
  * The createQueries function creates a Queries object, and is the main entry
2993
2993
  * point into the queries module.
2994
2994
  *
2995
- * It is trivially simple.
2996
- *
2997
2995
  * A given Store can only have one Queries object associated with it. If you
2998
2996
  * call this function twice on the same Store, your second call will return a
2999
2997
  * reference to the Queries object created by the first.
@@ -1170,8 +1170,6 @@ export interface Relationships {
1170
1170
  * The createRelationships function creates a Relationships object, and is the
1171
1171
  * main entry point into the relationships module.
1172
1172
  *
1173
- * It is trivially simple.
1174
- *
1175
1173
  * A given Store can only have one Relationships object associated with it. If
1176
1174
  * you call this function twice on the same Store, your second call will return
1177
1175
  * a reference to the Relationships object created by the first.
@@ -18,6 +18,7 @@ const ifNotUndefined = (value, then, otherwise) =>
18
18
  isUndefined(value) ? otherwise?.() : then(value);
19
19
  const isString = (thing) => getTypeOf(thing) == STRING;
20
20
  const isArray = (thing) => Array.isArray(thing);
21
+ const test = (regex, subject) => regex.test(subject);
21
22
 
22
23
  const collSizeN = (collSizer) => (coll) =>
23
24
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -239,7 +240,7 @@ const getPoolFunctions = () => {
239
240
  return [
240
241
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
241
242
  (id) => {
242
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
243
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
243
244
  arrayPush(pool, id);
244
245
  }
245
246
  },
@@ -1652,7 +1652,7 @@ export interface Store {
1652
1652
  * ```
1653
1653
  * @category Setter
1654
1654
  */
1655
- setSchema(tablesSchema: Schema): Store;
1655
+ setSchema(schema: Schema): Store;
1656
1656
 
1657
1657
  /**
1658
1658
  * The delTables method lets you remove all of the data in a Store.
@@ -56,6 +56,7 @@ const ifNotUndefined = (value, then, otherwise) =>
56
56
  const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
57
57
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
58
58
  const isArray = (thing) => Array.isArray(thing);
59
+ const test = (regex, subject) => regex.test(subject);
59
60
 
60
61
  const collSizeN = (collSizer) => (coll) =>
61
62
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -75,6 +76,8 @@ const mapKeys = (map) => [...(map?.keys() ?? [])];
75
76
  const mapGet = (map, key) => map?.get(key);
76
77
  const mapForEach = (map, cb) =>
77
78
  collForEach(map, (value, key) => cb(key, value));
79
+ const mapMap = (coll, cb) =>
80
+ arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
78
81
  const mapSet = (map, key, value) =>
79
82
  isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
80
83
  const mapEnsure = (map, key, getDefaultValue) => {
@@ -150,7 +153,7 @@ const getPoolFunctions = () => {
150
153
  return [
151
154
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
152
155
  (id) => {
153
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
156
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
154
157
  arrayPush(pool, id);
155
158
  }
156
159
  },
@@ -464,6 +467,7 @@ const createStore = () => {
464
467
  if (collIsEmpty(mapSet(table, rowId))) {
465
468
  tableIdsChanged(tableId, -1);
466
469
  mapSet(tablesMap, tableId);
470
+ mapSet(tablePoolFunctions, tableId);
467
471
  }
468
472
  }
469
473
  };
@@ -634,18 +638,14 @@ const createStore = () => {
634
638
  const getTable = (tableId) =>
635
639
  mapToObj(mapGet(tablesMap, id(tableId)), mapToObj);
636
640
  const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
637
- const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) => {
638
- const cells = [];
639
- mapForEach(mapGet(tablesMap, id(tableId)), (rowId, row) =>
640
- arrayPush(cells, [
641
- isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
642
- rowId,
643
- ]),
644
- );
645
- return arrayMap(
641
+ const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) =>
642
+ arrayMap(
646
643
  arraySlice(
647
644
  arraySort(
648
- cells,
645
+ mapMap(mapGet(tablesMap, id(tableId)), (row, rowId) => [
646
+ isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
647
+ rowId,
648
+ ]),
649
649
  ([cell1], [cell2]) =>
650
650
  defaultSorter(cell1, cell2) * (descending ? -1 : 1),
651
651
  ),
@@ -654,7 +654,6 @@ const createStore = () => {
654
654
  ),
655
655
  ([, rowId]) => rowId,
656
656
  );
657
- };
658
657
  const getRow = (tableId, rowId) =>
659
658
  mapToObj(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
660
659
  const getCellIds = (tableId, rowId) =>
@@ -809,7 +808,7 @@ const createStore = () => {
809
808
  return;
810
809
  }
811
810
  startTransaction();
812
- const result = actions?.();
811
+ const result = actions();
813
812
  finishTransaction(doRollback);
814
813
  return result;
815
814
  };
@@ -50,6 +50,7 @@ const arraySlice = (array, start, end) => array.slice(start, end);
50
50
  const arrayClear = (array, to) => array.splice(0, to);
51
51
  const arrayPush = (array, ...values) => array.push(...values);
52
52
  const arrayPop = (array) => array.pop();
53
+ const arrayUnshift = (array, ...values) => array.unshift(...values);
53
54
  const arrayShift = (array) => array.shift();
54
55
 
55
56
  const jsonString = (obj) =>
@@ -77,6 +78,7 @@ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
77
78
  const isString = (thing) => getTypeOf(thing) == STRING;
78
79
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
79
80
  const isArray = (thing) => Array.isArray(thing);
81
+ const test = (regex, subject) => regex.test(subject);
80
82
  const getUndefined = () => void 0;
81
83
 
82
84
  const collSizeN = (collSizer) => (coll) =>
@@ -97,6 +99,8 @@ const mapKeys = (map) => [...(map?.keys() ?? [])];
97
99
  const mapGet = (map, key) => map?.get(key);
98
100
  const mapForEach = (map, cb) =>
99
101
  collForEach(map, (value, key) => cb(key, value));
102
+ const mapMap = (coll, cb) =>
103
+ arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
100
104
  const mapSet = (map, key, value) =>
101
105
  isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
102
106
  const mapEnsure = (map, key, getDefaultValue) => {
@@ -317,7 +321,7 @@ const getPoolFunctions = () => {
317
321
  return [
318
322
  () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
319
323
  (id) => {
320
- if (INTEGER.test(id) && arrayLength(pool) < 1e3) {
324
+ if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
321
325
  arrayPush(pool, id);
322
326
  }
323
327
  },
@@ -487,7 +491,7 @@ const createCheckpoints = getCreateFunction((store) => {
487
491
  };
488
492
  const goBackwardImpl = () => {
489
493
  if (!arrayIsEmpty(backwardIds)) {
490
- forwardIds.unshift(addCheckpointImpl());
494
+ arrayUnshift(forwardIds, addCheckpointImpl());
491
495
  updateStore(0, currentId);
492
496
  currentId = arrayPop(backwardIds);
493
497
  checkpointsChanged = 1;
@@ -1995,6 +1999,7 @@ const createStore = () => {
1995
1999
  if (collIsEmpty(mapSet(table, rowId))) {
1996
2000
  tableIdsChanged(tableId, -1);
1997
2001
  mapSet(tablesMap, tableId);
2002
+ mapSet(tablePoolFunctions, tableId);
1998
2003
  }
1999
2004
  }
2000
2005
  };
@@ -2165,18 +2170,14 @@ const createStore = () => {
2165
2170
  const getTable = (tableId) =>
2166
2171
  mapToObj(mapGet(tablesMap, id(tableId)), mapToObj);
2167
2172
  const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
2168
- const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) => {
2169
- const cells = [];
2170
- mapForEach(mapGet(tablesMap, id(tableId)), (rowId, row) =>
2171
- arrayPush(cells, [
2172
- isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
2173
- rowId,
2174
- ]),
2175
- );
2176
- return arrayMap(
2173
+ const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) =>
2174
+ arrayMap(
2177
2175
  arraySlice(
2178
2176
  arraySort(
2179
- cells,
2177
+ mapMap(mapGet(tablesMap, id(tableId)), (row, rowId) => [
2178
+ isUndefined(cellId) ? rowId : mapGet(row, id(cellId)),
2179
+ rowId,
2180
+ ]),
2180
2181
  ([cell1], [cell2]) =>
2181
2182
  defaultSorter(cell1, cell2) * (descending ? -1 : 1),
2182
2183
  ),
@@ -2185,7 +2186,6 @@ const createStore = () => {
2185
2186
  ),
2186
2187
  ([, rowId]) => rowId,
2187
2188
  );
2188
- };
2189
2189
  const getRow = (tableId, rowId) =>
2190
2190
  mapToObj(mapGet(mapGet(tablesMap, id(tableId)), id(rowId)));
2191
2191
  const getCellIds = (tableId, rowId) =>
@@ -2340,7 +2340,7 @@ const createStore = () => {
2340
2340
  return;
2341
2341
  }
2342
2342
  startTransaction();
2343
- const result = actions?.();
2343
+ const result = actions();
2344
2344
  finishTransaction(doRollback);
2345
2345
  return result;
2346
2346
  };
@@ -0,0 +1,290 @@
1
+ /**
2
+ * The tools module of the TinyBase project provides utilities for working with
3
+ * TinyBase during development.
4
+ *
5
+ * This module is not intended to be directly used at runtime in a production
6
+ * environment.
7
+ *
8
+ * @packageDocumentation
9
+ * @module tools
10
+ * @since v2.2.0
11
+ */
12
+
13
+ import {Schema, Store} from './store.d';
14
+ import {Id} from './common.d';
15
+
16
+ /**
17
+ * The StoreStats type describes a set of statistics about the Store, and
18
+ * is used for debugging purposes.
19
+ *
20
+ * A StoreStats object is returned from the getStoreStats method.
21
+ *
22
+ * @category Statistics
23
+ * @since v2.2.0
24
+ */
25
+ export type StoreStats = {
26
+ /**
27
+ * The number of Table objects in the Store.
28
+ */
29
+ totalTables: number;
30
+ /**
31
+ * The number of Row objects in the Store, across all Table objects.
32
+ */
33
+ totalRows: number;
34
+ /**
35
+ * The number of Cell objects in the Store, across all Row objects, across all
36
+ * Table objects.
37
+ */
38
+ totalCells: number;
39
+ /**
40
+ * The string length of the Store when serialized to JSON.
41
+ */
42
+ jsonLength: number;
43
+ /**
44
+ * Additional detailed statistics about the Store if the `detail` flag is
45
+ * specified in the getStoreStats method.
46
+ */
47
+ detail?: StoreStatsDetail;
48
+ };
49
+
50
+ /**
51
+ * The StoreStatsDetail type describes a more detailed set of statistics about
52
+ * the Store, and is used for debugging purposes.
53
+ *
54
+ * A StoreStatsDetail object is added to the StoreStats object (returned from
55
+ * the getStoreStats method) when the `detail` flag is specified.
56
+ *
57
+ * @category Statistics
58
+ * @since v2.2.0
59
+ */
60
+ export type StoreStatsDetail = {
61
+ /**
62
+ * Information about each Table in the Store.
63
+ */
64
+ tables: {[tableId: Id]: StoreStatsTableDetail};
65
+ };
66
+
67
+ /**
68
+ * The StoreStatsTableDetail type describes a detailed set of statistics about a
69
+ * single Table in the Store, and is used for debugging purposes.
70
+ *
71
+ * @category Statistics
72
+ * @since v2.2.0
73
+ */
74
+ export type StoreStatsTableDetail = {
75
+ /**
76
+ * The number of Row objects in the Table.
77
+ */
78
+ tableRows: number;
79
+ /**
80
+ * The number of Cell objects in the Table, across all Row objects.
81
+ */
82
+ tableCells: number;
83
+ rows: {[rowId: Id]: StoreStatsRowDetail};
84
+ };
85
+
86
+ /**
87
+ * The StoreStatsRowDetail type describes statistics about a single Row in the
88
+ * Store, and is used for debugging purposes.
89
+ *
90
+ * @category Statistics
91
+ * @since v2.2.0
92
+ */
93
+ export type StoreStatsRowDetail = {
94
+ /**
95
+ * The number of Cell objects in the Row.
96
+ */
97
+ rowCells: number;
98
+ };
99
+
100
+ /**
101
+ * A Tools object lets you run various utilities on, and get certain information
102
+ * about, Store objects in development.
103
+ *
104
+ * @category Tools
105
+ * @since v2.2.0
106
+ */
107
+ export interface Tools {
108
+ /**
109
+ * The getStoreStats method provides a set of statistics about the Store, and
110
+ * is used for debugging purposes.
111
+ *
112
+ * @param detail An optional boolean that indicates more detailed stats about
113
+ * the inner structure of the Store should be returned.
114
+ * @returns A StoreStats object containing statistics about the Store.
115
+ * @example
116
+ * This example creates a Tools object and gets basic statistics about it.
117
+ * ```js
118
+ * const store = createStore()
119
+ * .setTable('pets', {
120
+ * fido: {species: 'dog', color: 'brown'},
121
+ * felix: {species: 'cat', color: 'black'},
122
+ * cujo: {species: 'dog', color: 'black'},
123
+ * })
124
+ * .setTable('species', {
125
+ * dog: {price: 5},
126
+ * cat: {price: 4},
127
+ * });
128
+ * const tools = createTools(store);
129
+ * console.log(tools.getStoreStats());
130
+ * // -> {totalTables: 2, totalRows: 5, totalCells: 8, jsonLength: 182}
131
+ * ```
132
+ * @example
133
+ * This example creates a Tools object and gets detailed statistics about it.
134
+ * ```js
135
+ * const store = createStore()
136
+ * .setTable('pets', {
137
+ * fido: {species: 'dog', color: 'brown'},
138
+ * felix: {species: 'cat', color: 'black'},
139
+ * cujo: {species: 'dog', color: 'black'},
140
+ * })
141
+ * .setTable('species', {
142
+ * dog: {price: 5},
143
+ * cat: {price: 4},
144
+ * });
145
+ * const stats = createTools(store).getStoreStats(true);
146
+ *
147
+ * console.log(stats.totalTables);
148
+ * // -> 2
149
+ * console.log(stats.totalRows);
150
+ * // -> 5
151
+ * console.log(stats.totalCells);
152
+ * // -> 8
153
+ * console.log(stats.detail.tables.pets.tableRows);
154
+ * // -> 3
155
+ * console.log(stats.detail.tables.pets.tableCells);
156
+ * // -> 6
157
+ * console.log(stats.detail.tables.pets.rows);
158
+ * // -> {fido: {rowCells: 2}, felix: {rowCells: 2}, cujo: {rowCells: 2}}
159
+ * ```
160
+ * @category Statistics
161
+ * @since v2.2.0
162
+ */
163
+ getStoreStats(detail?: boolean): StoreStats;
164
+
165
+ /**
166
+ * The getStoreSchema method returns the Schema of the Store as an object.
167
+ *
168
+ * If the Store does not already have an explicit Schema associated with it,
169
+ * the data in the Store will be scanned to attempt to infer a new Schema.
170
+ *
171
+ * To be successful, this requires all the values of a given Cell across a
172
+ * Table object's Row objects to have a consistent type. If a given Cell Id
173
+ * appears in every Row, then a `default` for that Cell is specified in the
174
+ * Schema, based on the most common value found.
175
+ *
176
+ * @returns A Schema object for the Store.
177
+ * @example
178
+ * This example creates a Tools object and gets basic statistics about a Store
179
+ * that already has a Schema.
180
+ * ```js
181
+ * const store = createStore().setSchema({
182
+ * pets: {
183
+ * species: {type: 'string'},
184
+ * color: {type: 'string'},
185
+ * },
186
+ * species: {
187
+ * price: {type: 'number'},
188
+ * },
189
+ * });
190
+ * const schema = createTools(store).getStoreSchema();
191
+ * console.log(schema.pets);
192
+ * // -> {species: {type: 'string'}, color: {type: 'string'}}
193
+ * ```
194
+ * @example
195
+ * This example creates a Tools object and gets basic statistics about a Store
196
+ * that doesn't already have a Schema.
197
+ * ```js
198
+ * const store = createStore()
199
+ * .setTable('pets', {
200
+ * fido: {species: 'dog', color: 'brown'},
201
+ * felix: {species: 'cat', color: 'black'},
202
+ * cujo: {species: 'dog', color: 'black'},
203
+ * })
204
+ * .setTable('species', {
205
+ * dog: {price: 5, barks: true},
206
+ * cat: {price: 4, purrs: true},
207
+ * });
208
+ * const schema = createTools(store).getStoreSchema();
209
+ * console.log(schema.pets.species);
210
+ * // -> {type: 'string', default: 'dog'}
211
+ * console.log(schema.pets.color);
212
+ * // -> {type: 'string', default: 'black'}
213
+ * console.log(schema.species.price);
214
+ * // -> {type: 'number', default: 5}
215
+ * console.log(schema.species.barks);
216
+ * // -> {type: 'boolean'}
217
+ * console.log(schema.species.purrs);
218
+ * // -> {type: 'boolean'}
219
+ * ```
220
+ * @category Modelling
221
+ * @since v2.2.0
222
+ */
223
+ getStoreSchema(): Schema;
224
+
225
+ /**
226
+ * The getStoreApi method returns a code-generated .d.ts file and a .ts file
227
+ * that wraps the schema of a Store.
228
+ *
229
+ * This is currently in development, and further documentation is to come.
230
+ *
231
+ * @category Modelling
232
+ * @since v2.2.0
233
+ */
234
+ getStoreApi(storeName: string): [string, string];
235
+
236
+ /**
237
+ * The getStoreApi method attempts to return a prettified code-generated .d.ts
238
+ * file and a .ts file that wraps the schema of a Store.
239
+ *
240
+ * This is currently in development, and further documentation is to come.
241
+ *
242
+ * @category Modelling
243
+ * @since v2.2.0
244
+ */
245
+ getPrettyStoreApi(storeName: string): Promise<[string, string]>;
246
+ }
247
+
248
+ /**
249
+ * The createTools function creates a Tools object, and is the main entry point
250
+ * into the tools module.
251
+ *
252
+ * A given Store can only have one Tools object associated with it. If you call
253
+ * this function twice on the same Store, your second call will return a
254
+ * reference to the Tools object created by the first.
255
+ *
256
+ * @param store The Store for which to register tools.
257
+ * @returns A reference to the new Tools object.
258
+ * @example
259
+ * This example creates a Tools object.
260
+ *
261
+ * ```js
262
+ * const store = createStore()
263
+ * .setTable('pets', {
264
+ * fido: {species: 'dog', color: 'brown'},
265
+ * felix: {species: 'cat', color: 'black'},
266
+ * cujo: {species: 'dog', color: 'black'},
267
+ * })
268
+ * .setTable('species', {
269
+ * dog: {price: 5},
270
+ * cat: {price: 4},
271
+ * });
272
+ * const tools = createTools(store);
273
+ * console.log(tools.getStoreStats());
274
+ * // -> {totalTables: 2, totalRows: 5, totalCells: 8, jsonLength: 182}
275
+ * ```
276
+ * @example
277
+ * This example creates a Tools object, and calls the method a second time
278
+ * for the same Store to return the same object.
279
+ *
280
+ * ```js
281
+ * const store = createStore();
282
+ * const tools1 = createTools(store);
283
+ * const tools2 = createTools(store);
284
+ * console.log(tools1 === tools2);
285
+ * // -> true
286
+ * ```
287
+ * @category Creation
288
+ * @since v2.2.0
289
+ */
290
+ export function createTools(store: Store): Tools;