tinybase 1.0.4 → 1.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/indexes.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * @module indexes
12
12
  */
13
13
 
14
- import {GetCell, Store} from './store.d';
14
+ import {GetCell, RowCallback, Store} from './store.d';
15
15
  import {Id, IdOrNull, Ids, SortKey} from './common.d';
16
16
 
17
17
  /**
@@ -43,6 +43,42 @@ export type Index = {[sliceId: Id]: Slice};
43
43
  */
44
44
  export type Slice = Ids;
45
45
 
46
+ /**
47
+ * The IndexCallback type describes a function that takes an Index's Id and a
48
+ * callback to loop over each Slice within it.
49
+ *
50
+ * A IndexCallback is provided when using the forEachIndex method, so that you
51
+ * can do something based on every Index in the Indexes object. See that method
52
+ * for specific examples.
53
+ *
54
+ * @param indexId The Id of the Index that the callback can operate on.
55
+ * @param forEachRow A function that will let you iterate over the Slice objects
56
+ * in this Index.
57
+ * @category Callback
58
+ */
59
+ export type IndexCallback = (
60
+ indexId: Id,
61
+ forEachSlice: (sliceCallback: SliceCallback) => void,
62
+ ) => void;
63
+
64
+ /**
65
+ * The SliceCallback type describes a function that takes a Slice's Id and a
66
+ * callback to loop over each Row within it.
67
+ *
68
+ * A SliceCallback is provided when using the forEachSlice method, so that you
69
+ * can do something based on every Slice in an Index. See that method for
70
+ * specific examples.
71
+ *
72
+ * @param sliceId The Id of the Slice that the callback can operate on.
73
+ * @param forEachRow A function that will let you iterate over the Row objects
74
+ * in this Slice.
75
+ * @category Callback
76
+ */
77
+ export type SliceCallback = (
78
+ sliceId: Id,
79
+ forEachRow: (rowCallback: RowCallback) => void,
80
+ ) => void;
81
+
46
82
  /**
47
83
  * The SliceIdsListener type describes a function that is used to listen to
48
84
  * changes to the Slice Ids in an Index.
@@ -362,6 +398,83 @@ export interface Indexes {
362
398
  */
363
399
  getIndexIds(): Ids;
364
400
 
401
+ /**
402
+ * The forEachIndex method takes a function that it will then call for each
403
+ * Index in a specified Indexes object.
404
+ *
405
+ * This method is useful for iterating over the structure of the Indexes
406
+ * object in a functional style. The `indexCallback` parameter is a
407
+ * IndexCallback function that will be called with the Id of each Index, and
408
+ * with a function that can then be used to iterate over each Slice of the
409
+ * Index, should you wish.
410
+ *
411
+ * @param indexCallback The function that should be called for every Index.
412
+ * @example
413
+ * This example iterates over each Index in an Indexes object, and lists each
414
+ * Slice Id within them.
415
+ *
416
+ * ```js
417
+ * const store = createStore().setTable('pets', {
418
+ * fido: {species: 'dog', color: 'brown'},
419
+ * felix: {species: 'cat', color: 'black'},
420
+ * cujo: {species: 'dog', color: 'black'},
421
+ * });
422
+ * const indexes = createIndexes(store)
423
+ * .setIndexDefinition('bySpecies', 'pets', 'species')
424
+ * .setIndexDefinition('byColor', 'pets', 'color');
425
+ *
426
+ * indexes.forEachIndex((indexId, forEachSlice) => {
427
+ * console.log(indexId);
428
+ * forEachSlice((sliceId) => console.log(`- ${sliceId}`));
429
+ * });
430
+ * // -> 'bySpecies'
431
+ * // -> '- dog'
432
+ * // -> '- cat'
433
+ * // -> 'byColor'
434
+ * // -> '- brown'
435
+ * // -> '- black'
436
+ * ```
437
+ * @category Iterator
438
+ */
439
+ forEachIndex(indexCallback: IndexCallback): void;
440
+
441
+ /**
442
+ * The forEachSlice method takes a function that it will then call for each
443
+ * Slice in a specified Index.
444
+ *
445
+ * This method is useful for iterating over the Slice structure of the Index
446
+ * in a functional style. The `rowCallback` parameter is a RowCallback
447
+ * function that will be called with the Id and value of each Row in the
448
+ * Slice.
449
+ *
450
+ * @param indexId The Id of the Index to iterate over.
451
+ * @param sliceCallback The function that should be called for every Slice.
452
+ * @example
453
+ * This example iterates over each Row in a Slice, and lists its Id.
454
+ *
455
+ * ```js
456
+ * const store = createStore().setTable('pets', {
457
+ * fido: {species: 'dog'},
458
+ * felix: {species: 'cat'},
459
+ * cujo: {species: 'dog'},
460
+ * });
461
+ * const indexes = createIndexes(store);
462
+ * indexes.setIndexDefinition('bySpecies', 'pets', 'species');
463
+ *
464
+ * indexes.forEachSlice('bySpecies', (sliceId, forEachRow) => {
465
+ * console.log(sliceId);
466
+ * forEachRow((rowId) => console.log(`- ${rowId}`));
467
+ * });
468
+ * // -> 'dog'
469
+ * // -> '- fido'
470
+ * // -> '- cujo'
471
+ * // -> 'cat'
472
+ * // -> '- felix'
473
+ * ```
474
+ * @category Iterator
475
+ */
476
+ forEachSlice(indexId: Id, sliceCallback: SliceCallback): void;
477
+
365
478
  /**
366
479
  * The hasIndex method returns a boolean indicating whether a given Index
367
480
  * exists in the Indexes object.
package/lib/indexes.js CHANGED
@@ -1 +1 @@
1
- const e=e=>typeof e,t=e(""),s=(e,t)=>e.every(((s,n)=>0==n||t(e[n-1],s)<=0)),n=(e,t)=>e.sort(t),o=(e,t)=>e.forEach(t),r=e=>e.length,d=e=>0==r(e),c=e=>e.slice(1),l=e=>null==e,i=(e,t,s)=>l(e)?s?.():t(e),a=(e,t)=>e?.has(t)??!1,u=e=>l(e)||0==(e=>e.size)(e),g=e=>e.clear(),I=(e,t)=>e?.forEach(t),h=(e,t)=>e?.delete(t),f=e=>new Map(e),w=e=>[...e?.keys()??[]],S=(e,t)=>e?.get(t),p=(e,t)=>I(e,((e,s)=>t(s,e))),L=(e,t,s)=>l(s)?(h(e,t),e):e?.set(t,s),v=(e,t,s,n)=>(a(e,t)||(n?.(s),e.set(t,s)),S(e,t)),x=e=>new Set(e),R=(e,t)=>e?.add(t),b=(s,n)=>e(s)==t?e=>e(s):s??(()=>n??""),y=(e,t)=>e<t?-1:1,T=(e,t,s)=>r(s)<2?R(d(s)?e:v(e,s[0],x()),t):T(v(e,s[0],f()),t,c(s)),k=e=>{const t=(s,n,...r)=>i(s,(s=>d(r)?e(s,n):o([r[0],null],(e=>t(S(s,e),n,...c(r))))));return t},z=Object.freeze,D=(e=>{const t=new WeakMap;return s=>(t.has(s)||t.set(s,e(s)),t.get(s))})((e=>{const t=f(),d=f(),[c,v,D,E,M,j,C,O,W]=((e,t,s)=>{const n=e.hasRow,r=f(),d=f(),c=f(),u=f(),h=f(),v=t=>i(S(h,t),(s=>{I(s,e.delListener),L(h,t)})),R=e=>{L(r,e),L(d,e),L(c,e),L(u,e),v(e)};return[()=>e,()=>w(r),e=>a(d,e),e=>S(r,e),e=>S(d,e),(e,t)=>L(d,e,t),(i,w,R,b,y)=>{const T=f(),k=f();L(r,i,w),a(d,i)||(L(d,i,t()),L(c,i,f()),L(u,i,f()));const z=S(c,i),D=S(u,i),E=t=>{const o=s=>e.getCell(w,t,s),r=S(z,t),d=n(w,t)?s(b(o,t)):void 0;if(r!=d&&L(T,t,[r,d]),!l(y)){const e=S(D,t),s=n(w,t)?y(o,t):void 0;e!=s&&L(k,t,s)}},M=e=>{R((()=>{I(T,(([,e],t)=>L(z,t,e))),I(k,((e,t)=>L(D,t,e)))}),T,k,z,D,e),g(T),g(k)};p(z,E),e.hasTable(w)&&o(e.getRowIds(w),(e=>{a(z,e)||E(e)})),M(!0),v(i),L(h,i,x([e.addRowListener(w,null,((e,t,s)=>E(s))),e.addTableListener(w,(()=>M()))]))},R,()=>p(h,R)]})(e,f,(e=>l(e)?"":e+"")),[m,q,A]=(e=>{let t,s=0;const n=[],d=f();return[(o,r,c=[])=>{t??=e();const l=n.pop()??""+s++;return L(d,l,[o,r,c]),T(r,l,c),l},(e,s=[],...n)=>k(I)(e,(e=>i(S(d,e),(([e])=>e(t,...s,...n)))),...s),e=>i(S(d,e),(([,t,s])=>(k(h)(t,e,...s),L(d,e),r(n)<1e3&&n.push(e),s)),(()=>[])),(e,s,n)=>i(S(d,e),(([e,,d])=>{const c=(...i)=>{const a=r(i);a==r(d)?e(t,...i,...n(i)):l(d[a])?o(s[a](...i),(e=>c(...i,e))):c(...i,d[a])};c()}))]})((()=>B)),B={setIndexDefinition:(e,o,r,c,g,w=y)=>{const v=l(g)?void 0:([e],[t])=>g(e,t);return C(e,o,((o,r,g,b,y,T)=>{let k=0;const z=x(),D=x(),E=M(e);if(I(r,(([e,t],s)=>{l(e)||(R(z,e),i(S(E,e),(t=>{h(t,s),u(t)&&(L(E,e),k=1)}))),l(t)||(R(z,t),a(E,t)||(L(E,t,x()),k=1),R(S(E,t),s),l(c)||R(D,t))})),o(),u(y)||(T?p(E,(e=>R(D,e))):p(g,(e=>i(S(b,e),(e=>R(D,e))))),I(D,(e=>{const t=(t,s)=>w(S(y,t),S(y,s),e),o=[...S(E,e)];s(o,t)||(L(E,e,x(n(o,t))),R(z,e))}))),(k||T)&&!l(v)){const t=[...E];s(t,v)||(j(e,f(n(t,v))),k=1)}k&&q(t,[e]),I(z,(t=>q(d,[e,t])))}),b(r),i(c,b)),B},delIndexDefinition:e=>(O(e),B),getStore:c,getIndexIds:v,hasIndex:D,hasSlice:(e,t)=>a(M(e),t),getTableId:E,getSliceIds:e=>w(M(e)),getSliceRowIds:(e,t)=>[...S(M(e),t)?.values()??[]],addSliceIdsListener:(e,s)=>m(s,t,[e]),addSliceRowIdsListener:(e,t,s)=>m(s,d,[e,t]),delListener:e=>(A(e),B),destroy:W,getListenerStats:()=>({})};return z(B)}));export{D as createIndexes};
1
+ const e=e=>typeof e,t=e(""),s=(e,t)=>e.every(((s,n)=>0==n||t(e[n-1],s)<=0)),n=(e,t)=>e.sort(t),o=(e,t)=>e.forEach(t),r=e=>e.length,c=e=>0==r(e),d=e=>e.slice(1),l=e=>null==e,i=(e,t,s)=>l(e)?s?.():t(e),a=(e,t)=>e?.has(t)??!1,h=e=>l(e)||0==(e=>e.size)(e),u=e=>e.clear(),I=(e,t)=>e?.forEach(t),f=(e,t)=>e?.delete(t),g=e=>new Map(e),S=e=>[...e?.keys()??[]],w=(e,t)=>e?.get(t),p=(e,t)=>I(e,((e,s)=>t(s,e))),L=(e,t,s)=>l(s)?(f(e,t),e):e?.set(t,s),x=(e,t,s,n)=>(a(e,t)||(n?.(s),e.set(t,s)),w(e,t)),v=e=>new Set(e),E=(e,t)=>e?.add(t),R=(s,n)=>e(s)==t?e=>e(s):s??(()=>n??""),b=(e,t)=>e<t?-1:1,y=(e,t,s)=>r(s)<2?E(c(s)?e:x(e,s[0],v()),t):y(x(e,s[0],g()),t,d(s)),T=e=>{const t=(s,n,...r)=>i(s,(s=>c(r)?e(s,n):o([r[0],null],(e=>t(w(s,e),n,...d(r))))));return t},k=Object.freeze,z=(e=>{const t=new WeakMap;return s=>(t.has(s)||t.set(s,e(s)),t.get(s))})((e=>{const t=g(),c=g(),[d,x,z,C,D,M,j,O,W,m]=((e,t,s)=>{const n=e.hasRow,r=g(),c=g(),d=g(),h=g(),f=g(),x=t=>i(w(f,t),(s=>{I(s,e.delListener),L(f,t)})),E=e=>{L(r,e),L(c,e),L(d,e),L(h,e),x(e)};return[()=>e,()=>S(r),e=>p(c,e),e=>a(c,e),e=>w(r,e),e=>w(c,e),(e,t)=>L(c,e,t),(i,S,E,R,b)=>{const y=g(),T=g();L(r,i,S),a(c,i)||(L(c,i,t()),L(d,i,g()),L(h,i,g()));const k=w(d,i),z=w(h,i),C=t=>{const o=s=>e.getCell(S,t,s),r=w(k,t),c=n(S,t)?s(R(o,t)):void 0;if(r!=c&&L(y,t,[r,c]),!l(b)){const e=w(z,t),s=n(S,t)?b(o,t):void 0;e!=s&&L(T,t,s)}},D=e=>{E((()=>{I(y,(([,e],t)=>L(k,t,e))),I(T,((e,t)=>L(z,t,e)))}),y,T,k,z,e),u(y),u(T)};p(k,C),e.hasTable(S)&&o(e.getRowIds(S),(e=>{a(k,e)||C(e)})),D(!0),x(i),L(f,i,v([e.addRowListener(S,null,((e,t,s)=>C(s))),e.addTableListener(S,(()=>D()))]))},E,()=>p(f,E)]})(e,g,(e=>l(e)?"":e+"")),[q,A,B]=(e=>{let t,s=0;const n=[],c=g();return[(o,r,d=[])=>{t??=e();const l=n.pop()??""+s++;return L(c,l,[o,r,d]),y(r,l,d),l},(e,s=[],...n)=>T(I)(e,(e=>i(w(c,e),(([e])=>e(t,...s,...n)))),...s),e=>i(w(c,e),(([,t,s])=>(T(f)(t,e,...s),L(c,e),r(n)<1e3&&n.push(e),s)),(()=>[])),(e,s,n)=>i(w(c,e),(([e,,c])=>{const d=(...i)=>{const a=r(i);a==r(c)?e(t,...i,...n(i)):l(c[a])?o(s[a](...i),(e=>d(...i,e))):d(...i,c[a])};d()}))]})((()=>G)),F=(t,s,n)=>{const o=D(t);I(n,((t,n)=>s(n,(s=>I(t,(t=>s(t,(s=>e.forEachCell(o,t,s)))))))))},G={setIndexDefinition:(e,o,r,d,u,S=b)=>{const x=l(u)?void 0:([e],[t])=>u(e,t);return O(e,o,((o,r,u,R,b,y)=>{let T=0;const k=v(),z=v(),C=M(e);if(I(r,(([e,t],s)=>{l(e)||(E(k,e),i(w(C,e),(t=>{f(t,s),h(t)&&(L(C,e),T=1)}))),l(t)||(E(k,t),a(C,t)||(L(C,t,v()),T=1),E(w(C,t),s),l(d)||E(z,t))})),o(),h(b)||(y?p(C,(e=>E(z,e))):p(u,(e=>i(w(R,e),(e=>E(z,e))))),I(z,(e=>{const t=(t,s)=>S(w(b,t),w(b,s),e),o=[...w(C,e)];s(o,t)||(L(C,e,v(n(o,t))),E(k,e))}))),(T||y)&&!l(x)){const t=[...C];s(t,x)||(j(e,g(n(t,x))),T=1)}T&&A(t,[e]),I(k,(t=>A(c,[e,t])))}),R(r),i(d,R)),G},delIndexDefinition:e=>(W(e),G),getStore:d,getIndexIds:x,forEachIndex:e=>z(((t,s)=>e(t,(e=>F(t,e,s))))),forEachSlice:(e,t)=>F(e,t,M(e)),hasIndex:C,hasSlice:(e,t)=>a(M(e),t),getTableId:D,getSliceIds:e=>S(M(e)),getSliceRowIds:(e,t)=>[...w(M(e),t)?.values()??[]],addSliceIdsListener:(e,s)=>q(s,t,[e]),addSliceRowIdsListener:(e,t,s)=>q(s,c,[e,t]),delListener:e=>(B(e),G),destroy:m,getListenerStats:()=>({})};return k(G)}));export{z as createIndexes};
package/lib/indexes.js.gz CHANGED
Binary file
package/lib/metrics.d.ts CHANGED
@@ -22,6 +22,20 @@ import {Id, IdOrNull, Ids} from './common.d';
22
22
  */
23
23
  export type Metric = number;
24
24
 
25
+ /**
26
+ * The MetricCallback type describes a function that takes a Metric's Id and a
27
+ * callback to loop over each Row within it.
28
+ *
29
+ * A MetricCallback is provided when using the forEachMetric method, so that you
30
+ * can do something based on every Metric in the Metrics object. See that method
31
+ * for specific examples.
32
+ *
33
+ * @param metricId The Id of the Metric that the callback can operate on.
34
+ * @param metric The value of the Metric.
35
+ * @category Callback
36
+ */
37
+ export type MetricCallback = (metricId: Id, metric?: Metric) => void;
38
+
25
39
  /**
26
40
  * The Aggregate type describes a custom function that takes an array or numbers
27
41
  * and returns an aggregate that is used as a Metric.
@@ -478,6 +492,38 @@ export interface Metrics {
478
492
  */
479
493
  getMetricIds(): Ids;
480
494
 
495
+ /**
496
+ * The forEachMetric method takes a function that it will then call for each
497
+ * Metric in the Metrics object.
498
+ *
499
+ * This method is useful for iterating over all the Metrics in a functional
500
+ * style. The `metricCallback` parameter is a MetricCallback function that
501
+ * will be called with the Id of each Metric and its value.
502
+ *
503
+ * @param metricCallback The function that should be called for every Metric.
504
+ * @example
505
+ * This example iterates over each Metric in a Metrics object.
506
+ *
507
+ * ```js
508
+ * const store = createStore().setTable('species', {
509
+ * dog: {price: 5},
510
+ * cat: {price: 4},
511
+ * worm: {price: 1},
512
+ * });
513
+ * const metrics = createMetrics(store)
514
+ * .setMetricDefinition('highestPrice', 'species', 'max', 'price')
515
+ * .setMetricDefinition('lowestPrice', 'species', 'min', 'price');
516
+ *
517
+ * metrics.forEachMetric((metricId, metric) => {
518
+ * console.log([metricId, metric]);
519
+ * });
520
+ * // -> ['highestPrice', 5]
521
+ * // -> ['lowestPrice', 1]
522
+ * ```
523
+ * @category Iterator
524
+ */
525
+ forEachMetric(metricCallback: MetricCallback): void;
526
+
481
527
  /**
482
528
  * The hasMetric method returns a boolean indicating whether a given Metric
483
529
  * exists in the Metrics object, and has a value.
package/lib/metrics.js CHANGED
@@ -1 +1 @@
1
- const e=e=>typeof e,t=e(""),s=e(e),n=(e,t)=>e.forEach(t),o=e=>c(e,((e,t)=>e+t),0),i=e=>e.length,r=e=>0==i(e),c=(e,t,s)=>e.reduce(t,s),a=e=>e.slice(1),d=Math.max,l=Math.min,u=isFinite,v=e=>null==e,g=(e,t,s)=>v(e)?s?.():t(e),h=()=>{},M=e=>e.size,f=(e,t)=>e?.has(t)??!1,p=e=>e.clear(),m=(e,t)=>e?.forEach(t),w=(e,t)=>e?.delete(t),L=e=>new Map(e),b=(e,t)=>e?.get(t),x=(e,t)=>m(e,((e,s)=>t(s,e))),y=(e,t,s)=>v(s)?(w(e,t),e):e?.set(t,s),I=(e,t,s,n)=>(f(e,t)||(n?.(s),e.set(t,s)),b(e,t)),R=e=>new Set(e),S=(s,n)=>e(s)==t?e=>e(s):s??(()=>n??""),T=(e,t,s)=>i(s)<2?((e,t)=>e?.add(t))(r(s)?e:I(e,s[0],R()),t):T(I(e,s[0],L()),t,a(s)),k=e=>{const t=(s,o,...i)=>g(s,(s=>r(i)?e(s,o):n([i[0],null],(e=>t(b(s,e),o,...a(i))))));return t},z=Object.freeze,D=L([["avg",[(e,t)=>o(e)/t,(e,t,s)=>e+(t-e)/(s+1),(e,t,s)=>e+(e-t)/(s-1),(e,t,s,n)=>e+(t-s)/n]],["max",[e=>d(...e),(e,t)=>d(t,e),(e,t)=>t==e?void 0:e,(e,t,s)=>s==e?void 0:d(t,e)]],["min",[e=>l(...e),(e,t)=>l(t,e),(e,t)=>t==e?void 0:e,(e,t,s)=>s==e?void 0:l(t,e)]],["sum",[e=>o(e),(e,t)=>e+t,(e,t)=>e-t,(e,t,s)=>e-s+t]]]),E=(e=>{const t=new WeakMap;return s=>(t.has(s)||t.set(s,e(s)),t.get(s))})((t=>{const o=L(),[r,c,a,d,l,I,E,N,j]=((e,t,s)=>{const o=e.hasRow,i=L(),r=L(),c=L(),a=L(),d=L(),l=t=>g(b(d,t),(s=>{m(s,e.delListener),y(d,t)})),u=e=>{y(i,e),y(r,e),y(c,e),y(a,e),l(e)};return[()=>e,()=>[...i?.keys()??[]],e=>f(r,e),e=>b(i,e),e=>b(r,e),(e,t)=>y(r,e,t),(u,g,h,M,w)=>{const I=L(),S=L();y(i,u,g),f(r,u)||(y(r,u,t()),y(c,u,L()),y(a,u,L()));const T=b(c,u),k=b(a,u),z=t=>{const n=s=>e.getCell(g,t,s),i=b(T,t),r=o(g,t)?s(M(n,t)):void 0;if(i!=r&&y(I,t,[i,r]),!v(w)){const e=b(k,t),s=o(g,t)?w(n,t):void 0;e!=s&&y(S,t,s)}},D=e=>{h((()=>{m(I,(([,e],t)=>y(T,t,e))),m(S,((e,t)=>y(k,t,e)))}),I,S,T,k,e),p(I),p(S)};x(T,z),e.hasTable(g)&&n(e.getRowIds(g),(e=>{f(T,e)||z(e)})),D(!0),l(u),y(d,u,R([e.addRowListener(g,null,((e,t,s)=>z(s))),e.addTableListener(g,(()=>D()))]))},u,()=>x(d,u)]})(t,h,(e=>isNaN(e)||v(e)||!0===e||!1===e||""===e?void 0:1*e)),[C,F,O]=(e=>{let t,s=0;const o=[],r=L();return[(n,i,c=[])=>{t??=e();const a=o.pop()??""+s++;return y(r,a,[n,i,c]),T(i,a,c),a},(e,s=[],...n)=>k(m)(e,(e=>g(b(r,e),(([e])=>e(t,...s,...n)))),...s),e=>g(b(r,e),(([,t,s])=>(k(w)(t,e,...s),y(r,e),i(o)<1e3&&o.push(e),s)),(()=>[])),(e,s,o)=>g(b(r,e),(([e,,r])=>{const c=(...a)=>{const d=i(a);d==i(r)?e(t,...a,...o(a)):v(r[d])?n(s[d](...a),(e=>c(...a,e))):c(...a,r[d])};c()}))]})((()=>W)),W={setMetricDefinition:(t,n,i,r,c,a,d)=>{const g=e(i)==s?[i,c,a,d]:b(D,i)??b(D,"sum");return E(t,n,((e,s,n,i,r,c)=>{let a=l(t),d=M(i);const[h,f,p,w]=g;var L;c=c||v(a),m(s,(([e,t])=>{c||(a=v(e)?f?.(a,t,d++):v(t)?p?.(a,e,d--):w?.(a,t,e,d)),c=c||v(a)})),e(),v(L=i)||0==M(L)?a=void 0:c&&(a=h((e=>[...e?.values()??[]])(i),M(i))),u(a)||(a=void 0);const b=l(t);a!=b&&(I(t,a),F(o,[t],a,b))}),S(r,1)),W},delMetricDefinition:e=>(N(e),W),getStore:r,getMetricIds:c,hasMetric:a,getTableId:d,getMetric:l,addMetricListener:(e,t)=>C(t,o,[e]),delListener:e=>(O(e),W),destroy:j,getListenerStats:()=>({})};return z(W)}));export{E as createMetrics};
1
+ const e=e=>typeof e,t=e(""),s=e(e),n=(e,t)=>e.forEach(t),o=e=>c(e,((e,t)=>e+t),0),i=e=>e.length,r=e=>0==i(e),c=(e,t,s)=>e.reduce(t,s),a=e=>e.slice(1),d=Math.max,l=Math.min,u=isFinite,h=e=>null==e,v=(e,t,s)=>h(e)?s?.():t(e),g=()=>{},M=e=>e.size,f=(e,t)=>e?.has(t)??!1,p=e=>e.clear(),m=(e,t)=>e?.forEach(t),w=(e,t)=>e?.delete(t),L=e=>new Map(e),b=(e,t)=>e?.get(t),x=(e,t)=>m(e,((e,s)=>t(s,e))),y=(e,t,s)=>h(s)?(w(e,t),e):e?.set(t,s),E=(e,t,s,n)=>(f(e,t)||(n?.(s),e.set(t,s)),b(e,t)),I=e=>new Set(e),R=(s,n)=>e(s)==t?e=>e(s):s??(()=>n??""),S=(e,t,s)=>i(s)<2?((e,t)=>e?.add(t))(r(s)?e:E(e,s[0],I()),t):S(E(e,s[0],L()),t,a(s)),T=e=>{const t=(s,o,...i)=>v(s,(s=>r(i)?e(s,o):n([i[0],null],(e=>t(b(s,e),o,...a(i))))));return t},k=Object.freeze,z=L([["avg",[(e,t)=>o(e)/t,(e,t,s)=>e+(t-e)/(s+1),(e,t,s)=>e+(e-t)/(s-1),(e,t,s,n)=>e+(t-s)/n]],["max",[e=>d(...e),(e,t)=>d(t,e),(e,t)=>t==e?void 0:e,(e,t,s)=>s==e?void 0:d(t,e)]],["min",[e=>l(...e),(e,t)=>l(t,e),(e,t)=>t==e?void 0:e,(e,t,s)=>s==e?void 0:l(t,e)]],["sum",[e=>o(e),(e,t)=>e+t,(e,t)=>e-t,(e,t,s)=>e-s+t]]]),D=(e=>{const t=new WeakMap;return s=>(t.has(s)||t.set(s,e(s)),t.get(s))})((t=>{const o=L(),[r,c,a,d,l,E,D,N,j,C]=((e,t,s)=>{const o=e.hasRow,i=L(),r=L(),c=L(),a=L(),d=L(),l=t=>v(b(d,t),(s=>{m(s,e.delListener),y(d,t)})),u=e=>{y(i,e),y(r,e),y(c,e),y(a,e),l(e)};return[()=>e,()=>[...i?.keys()??[]],e=>x(r,e),e=>f(r,e),e=>b(i,e),e=>b(r,e),(e,t)=>y(r,e,t),(u,v,g,M,w)=>{const E=L(),R=L();y(i,u,v),f(r,u)||(y(r,u,t()),y(c,u,L()),y(a,u,L()));const S=b(c,u),T=b(a,u),k=t=>{const n=s=>e.getCell(v,t,s),i=b(S,t),r=o(v,t)?s(M(n,t)):void 0;if(i!=r&&y(E,t,[i,r]),!h(w)){const e=b(T,t),s=o(v,t)?w(n,t):void 0;e!=s&&y(R,t,s)}},z=e=>{g((()=>{m(E,(([,e],t)=>y(S,t,e))),m(R,((e,t)=>y(T,t,e)))}),E,R,S,T,e),p(E),p(R)};x(S,k),e.hasTable(v)&&n(e.getRowIds(v),(e=>{f(S,e)||k(e)})),z(!0),l(u),y(d,u,I([e.addRowListener(v,null,((e,t,s)=>k(s))),e.addTableListener(v,(()=>z()))]))},u,()=>x(d,u)]})(t,g,(e=>isNaN(e)||h(e)||!0===e||!1===e||""===e?void 0:1*e)),[F,O,W]=(e=>{let t,s=0;const o=[],r=L();return[(n,i,c=[])=>{t??=e();const a=o.pop()??""+s++;return y(r,a,[n,i,c]),S(i,a,c),a},(e,s=[],...n)=>T(m)(e,(e=>v(b(r,e),(([e])=>e(t,...s,...n)))),...s),e=>v(b(r,e),(([,t,s])=>(T(w)(t,e,...s),y(r,e),i(o)<1e3&&o.push(e),s)),(()=>[])),(e,s,o)=>v(b(r,e),(([e,,r])=>{const c=(...a)=>{const d=i(a);d==i(r)?e(t,...a,...o(a)):h(r[d])?n(s[d](...a),(e=>c(...a,e))):c(...a,r[d])};c()}))]})((()=>q)),q={setMetricDefinition:(t,n,i,r,c,a,d)=>{const l=e(i)==s?[i,c,a,d]:b(z,i)??b(z,"sum");return N(t,n,((e,s,n,i,r,c)=>{let a=E(t),d=M(i);const[v,g,f,p]=l;var w;c=c||h(a),m(s,(([e,t])=>{c||(a=h(e)?g?.(a,t,d++):h(t)?f?.(a,e,d--):p?.(a,t,e,d)),c=c||h(a)})),e(),h(w=i)||0==M(w)?a=void 0:c&&(a=v((e=>[...e?.values()??[]])(i),M(i))),u(a)||(a=void 0);const L=E(t);a!=L&&(D(t,a),O(o,[t],a,L))}),R(r,1)),q},delMetricDefinition:e=>(j(e),q),getStore:r,getMetricIds:c,forEachMetric:a,hasMetric:d,getTableId:l,getMetric:E,addMetricListener:(e,t)=>F(t,o,[e]),delListener:e=>(W(e),q),destroy:C,getListenerStats:()=>({})};return k(q)}));export{D as createMetrics};
package/lib/metrics.js.gz CHANGED
Binary file
@@ -11,7 +11,7 @@
11
11
  * @module relationships
12
12
  */
13
13
 
14
- import {GetCell, Store} from './store.d';
14
+ import {GetCell, RowCallback, Store} from './store.d';
15
15
  import {Id, IdOrNull, Ids} from './common.d';
16
16
 
17
17
  /**
@@ -39,6 +39,25 @@ export type Relationship = {
39
39
  linkedRowIds: {[firstRowId: Id]: Ids};
40
40
  };
41
41
 
42
+ /**
43
+ * The RelationshipCallback type describes a function that takes a
44
+ * Relationship's Id and a callback to loop over each local Row within it.
45
+ *
46
+ * A RelationshipCallback is provided when using the forEachRelationship method,
47
+ * so that you can do something based on every Relationship in the Relationships
48
+ * object. See that method for specific examples.
49
+ *
50
+ * @param relationshipId The Id of the Relationship that the callback can
51
+ * operate on.
52
+ * @param forEachRow A function that will let you iterate over the local Row
53
+ * objects in this Relationship.
54
+ * @category Callback
55
+ */
56
+ export type RelationshipCallback = (
57
+ relationshipId: Id,
58
+ forEachRow: (rowCallback: RowCallback) => void,
59
+ ) => void;
60
+
42
61
  /**
43
62
  * The RemoteRowIdListener type describes a function that is used to listen to
44
63
  * changes to the remote Row Id end of a Relationship.
@@ -405,6 +424,49 @@ export interface Relationships {
405
424
  */
406
425
  getRelationshipIds(): Ids;
407
426
 
427
+ /**
428
+ * The forEachRelationship method takes a function that it will then call for
429
+ * each Relationship in a specified Relationships object.
430
+ *
431
+ * This method is useful for iterating over the structure of the Relationships
432
+ * object in a functional style. The `relationshipCallback` parameter is a
433
+ * RelationshipCallback function that will be called with the Id of each
434
+ * Relationship, and with a function that can then be used to iterate over
435
+ * each local Row involved in the Relationship.
436
+ *
437
+ * @param relationshipCallback The function that should be called for every
438
+ * Relationship.
439
+ * @example
440
+ * This example iterates over each Relationship in a Relationships object, and
441
+ * lists each Row Id within them.
442
+ *
443
+ * ```js
444
+ * const store = createStore().setTable('pets', {
445
+ * fido: {species: 'dog', next: 'felix'},
446
+ * felix: {species: 'cat', next: 'cujo'},
447
+ * cujo: {species: 'dog'},
448
+ * });
449
+ * const relationships = createRelationships(store)
450
+ * .setRelationshipDefinition('petSpecies', 'pets', 'species', 'species')
451
+ * .setRelationshipDefinition('petSequence', 'pets', 'pets', 'next');
452
+ *
453
+ * relationships.forEachRelationship((relationshipId, forEachRow) => {
454
+ * console.log(relationshipId);
455
+ * forEachRow((rowId) => console.log(`- ${rowId}`));
456
+ * });
457
+ * // -> 'petSpecies'
458
+ * // -> '- fido'
459
+ * // -> '- felix'
460
+ * // -> '- cujo'
461
+ * // -> 'petSequence'
462
+ * // -> '- fido'
463
+ * // -> '- felix'
464
+ * // -> '- cujo'
465
+ * ```
466
+ * @category Iterator
467
+ */
468
+ forEachRelationship(relationshipCallback: RelationshipCallback): void;
469
+
408
470
  /**
409
471
  * The hasRelationship method returns a boolean indicating whether a given
410
472
  * Relationship exists in the Relationships object.
@@ -1 +1 @@
1
- const e=e=>typeof e,t=e(""),s=(e,t)=>e.forEach(t),n=e=>e.length,o=e=>0==n(e),i=e=>e.slice(1),r=e=>null==e,d=(e,t,s)=>r(e)?s?.():t(e),a=(e,t)=>e?.has(t)??!1,l=e=>[...e?.values()??[]],c=e=>e.clear(),R=(e,t)=>e?.forEach(t),g=(e,t)=>e?.delete(t),h=e=>new Map(e),u=(e,t)=>e?.get(t),L=(e,t)=>R(e,((e,s)=>t(s,e))),w=(e,t,s)=>r(s)?(g(e,t),e):e?.set(t,s),f=(e,t,s,n)=>(a(e,t)||(n?.(s),e.set(t,s)),u(e,t)),p=e=>new Set(e),I=(e,t)=>e?.add(t),b=(s,n)=>e(s)==t?e=>e(s):s??(()=>n??""),v=(e,t,s)=>n(s)<2?I(o(s)?e:f(e,s[0],p()),t):v(f(e,s[0],h()),t,i(s)),k=e=>{const t=(n,r,...a)=>d(n,(n=>o(a)?e(n,r):s([a[0],null],(e=>t(u(n,e),r,...i(a))))));return t},T=Object.freeze,m=(e=>{const t=new WeakMap;return s=>(t.has(s)||t.set(s,e(s)),t.get(s))})((e=>{const t=h(),o=h(),i=h(),f=h(),[m,y,S,z,D,E,M,j,x]=((e,t,n)=>{const o=e.hasRow,i=h(),l=h(),g=h(),f=h(),I=h(),b=t=>d(u(I,t),(s=>{R(s,e.delListener),w(I,t)})),v=e=>{w(i,e),w(l,e),w(g,e),w(f,e),b(e)};return[()=>e,()=>[...i?.keys()??[]],e=>a(l,e),e=>u(i,e),e=>u(l,e),(e,t)=>w(l,e,t),(d,v,k,T,m)=>{const y=h(),S=h();w(i,d,v),a(l,d)||(w(l,d,t()),w(g,d,h()),w(f,d,h()));const z=u(g,d),D=u(f,d),E=t=>{const s=s=>e.getCell(v,t,s),i=u(z,t),d=o(v,t)?n(T(s,t)):void 0;if(i!=d&&w(y,t,[i,d]),!r(m)){const e=u(D,t),n=o(v,t)?m(s,t):void 0;e!=n&&w(S,t,n)}},M=e=>{k((()=>{R(y,(([,e],t)=>w(z,t,e))),R(S,((e,t)=>w(D,t,e)))}),y,S,z,D,e),c(y),c(S)};L(z,E),e.hasTable(v)&&s(e.getRowIds(v),(e=>{a(z,e)||E(e)})),M(!0),b(d),w(I,d,p([e.addRowListener(v,null,((e,t,s)=>E(s))),e.addTableListener(v,(()=>M()))]))},v,()=>L(I,v)]})(e,(()=>[h(),h(),h(),h()]),(e=>r(e)?void 0:e+"")),[C,O,W]=(e=>{let t,o=0;const i=[],a=h();return[(s,n,r=[])=>{t??=e();const d=i.pop()??""+o++;return w(a,d,[s,n,r]),v(n,d,r),d},(e,s=[],...n)=>k(R)(e,(e=>d(u(a,e),(([e])=>e(t,...s,...n)))),...s),e=>d(u(a,e),(([,t,s])=>(k(g)(t,e,...s),w(a,e),n(i)<1e3&&i.push(e),s)),(()=>[])),(e,o,i)=>d(u(a,e),(([e,,d])=>{const a=(...l)=>{const c=n(l);c==n(d)?e(t,...l,...i(l)):r(d[c])?s(o[c](...l),(e=>a(...l,e))):a(...l,d[c])};a()}))]})((()=>F)),q=(e,t,s)=>d(D(e),(([n,,o])=>{if(!a(o,t)){const i=p();if(z(e)!=B(e))I(i,t);else{let e=t;for(;!r(e)&&!a(i,e);)I(i,e),e=u(n,e)}if(s)return i;w(o,t,i)}return u(o,t)})),A=(e,t)=>d(D(e),(([,,e])=>w(e,t))),B=e=>u(t,e),F={setRelationshipDefinition:(e,s,n,l)=>(w(t,e,n),M(e,s,((t,s)=>{const n=p(),l=p(),c=p(),[h,b]=D(e);R(s,(([t,s],o)=>{r(t)||(I(l,t),d(u(b,t),(e=>{var s;g(e,o),(r(s=e)||0==(e=>e.size)(s))&&w(b,t)}))),r(s)||(I(l,s),a(b,s)||w(b,s,p()),I(u(b,s),o)),I(n,o),w(h,o,s),L(u(f,e),(t=>{a(q(e,t),o)&&I(c,t)}))})),t(),R(n,(t=>O(o,[e,t]))),R(l,(t=>O(i,[e,t]))),R(c,(t=>{A(e,t),O(f,[e,t])}))}),b(l)),F),delRelationshipDefinition:e=>(w(t,e),j(e),F),getStore:m,getRelationshipIds:y,hasRelationship:S,getLocalTableId:z,getRemoteTableId:B,getRemoteRowId:(e,t)=>u(D(e)?.[0],t),getLocalRowIds:(e,t)=>l(u(D(e)?.[1],t)),getLinkedRowIds:(e,t)=>r(D(e))?[t]:l(q(e,t,!0)),addRemoteRowIdListener:(e,t,s)=>C(s,o,[e,t]),addLocalRowIdsListener:(e,t,s)=>C(s,i,[e,t]),addLinkedRowIdsListener:(e,t,s)=>(q(e,t),C(s,f,[e,t])),delListener:e=>(A(...W(e)),F),destroy:x,getListenerStats:()=>({})};return T(F)}));export{m as createRelationships};
1
+ const e=e=>typeof e,t=e(""),o=(e,t)=>e.forEach(t),s=e=>e.length,n=e=>0==s(e),i=e=>e.slice(1),r=e=>null==e,a=(e,t,o)=>r(e)?o?.():t(e),d=(e,t)=>e?.has(t)??!1,l=e=>[...e?.values()??[]],c=e=>e.clear(),R=(e,t)=>e?.forEach(t),h=(e,t)=>e?.delete(t),f=e=>new Map(e),g=(e,t)=>e?.get(t),u=(e,t)=>R(e,((e,o)=>t(o,e))),w=(e,t,o)=>r(o)?(h(e,t),e):e?.set(t,o),L=(e,t,o,s)=>(d(e,t)||(s?.(o),e.set(t,o)),g(e,t)),p=e=>new Set(e),I=(e,t)=>e?.add(t),b=(o,s)=>e(o)==t?e=>e(o):o??(()=>s??""),v=(e,t,o)=>s(o)<2?I(n(o)?e:L(e,o[0],p()),t):v(L(e,o[0],f()),t,i(o)),k=e=>{const t=(s,r,...d)=>a(s,(s=>n(d)?e(s,r):o([d[0],null],(e=>t(g(s,e),r,...i(d))))));return t},E=Object.freeze,T=(e=>{const t=new WeakMap;return o=>(t.has(o)||t.set(o,e(o)),t.get(o))})((e=>{const t=f(),n=f(),i=f(),L=f(),[T,m,y,S,z,D,M,j,x,C]=((e,t,s)=>{const n=e.hasRow,i=f(),l=f(),h=f(),L=f(),I=f(),b=t=>a(g(I,t),(o=>{R(o,e.delListener),w(I,t)})),v=e=>{w(i,e),w(l,e),w(h,e),w(L,e),b(e)};return[()=>e,()=>[...i?.keys()??[]],e=>u(l,e),e=>d(l,e),e=>g(i,e),e=>g(l,e),(e,t)=>w(l,e,t),(a,v,k,E,T)=>{const m=f(),y=f();w(i,a,v),d(l,a)||(w(l,a,t()),w(h,a,f()),w(L,a,f()));const S=g(h,a),z=g(L,a),D=t=>{const o=o=>e.getCell(v,t,o),i=g(S,t),a=n(v,t)?s(E(o,t)):void 0;if(i!=a&&w(m,t,[i,a]),!r(T)){const e=g(z,t),s=n(v,t)?T(o,t):void 0;e!=s&&w(y,t,s)}},M=e=>{k((()=>{R(m,(([,e],t)=>w(S,t,e))),R(y,((e,t)=>w(z,t,e)))}),m,y,S,z,e),c(m),c(y)};u(S,D),e.hasTable(v)&&o(e.getRowIds(v),(e=>{d(S,e)||D(e)})),M(!0),b(a),w(I,a,p([e.addRowListener(v,null,((e,t,o)=>D(o))),e.addTableListener(v,(()=>M()))]))},v,()=>u(I,v)]})(e,(()=>[f(),f(),f(),f()]),(e=>r(e)?void 0:e+"")),[O,W,q]=(e=>{let t,n=0;const i=[],d=f();return[(o,s,r=[])=>{t??=e();const a=i.pop()??""+n++;return w(d,a,[o,s,r]),v(s,a,r),a},(e,o=[],...s)=>k(R)(e,(e=>a(g(d,e),(([e])=>e(t,...o,...s)))),...o),e=>a(g(d,e),(([,t,o])=>(k(h)(t,e,...o),w(d,e),s(i)<1e3&&i.push(e),o)),(()=>[])),(e,n,i)=>a(g(d,e),(([e,,a])=>{const d=(...l)=>{const c=s(l);c==s(a)?e(t,...l,...i(l)):r(a[c])?o(n[c](...l),(e=>d(...l,e))):d(...l,a[c])};d()}))]})((()=>G)),A=(e,t,o)=>a(D(e),(([s,,n])=>{if(!d(n,t)){const i=p();if(z(e)!=F(e))I(i,t);else{let e=t;for(;!r(e)&&!d(i,e);)I(i,e),e=g(s,e)}if(o)return i;w(n,t,i)}return g(n,t)})),B=(e,t)=>a(D(e),(([,,e])=>w(e,t))),F=e=>g(t,e),G={setRelationshipDefinition:(e,o,s,l)=>(w(t,e,s),j(e,o,((t,o)=>{const s=p(),l=p(),c=p(),[f,b]=D(e);R(o,(([t,o],n)=>{r(t)||(I(l,t),a(g(b,t),(e=>{var o;h(e,n),(r(o=e)||0==(e=>e.size)(o))&&w(b,t)}))),r(o)||(I(l,o),d(b,o)||w(b,o,p()),I(g(b,o),n)),I(s,n),w(f,n,o),u(g(L,e),(t=>{d(A(e,t),n)&&I(c,t)}))})),t(),R(s,(t=>W(n,[e,t]))),R(l,(t=>W(i,[e,t]))),R(c,(t=>{B(e,t),W(L,[e,t])}))}),b(l)),G),delRelationshipDefinition:e=>(w(t,e),x(e),G),getStore:T,getRelationshipIds:m,forEachRelationship:t=>y((o=>t(o,(t=>e.forEachRow(z(o),t))))),hasRelationship:S,getLocalTableId:z,getRemoteTableId:F,getRemoteRowId:(e,t)=>g(D(e)?.[0],t),getLocalRowIds:(e,t)=>l(g(D(e)?.[1],t)),getLinkedRowIds:(e,t)=>r(D(e))?[t]:l(A(e,t,!0)),addRemoteRowIdListener:(e,t,o)=>O(o,n,[e,t]),addLocalRowIdsListener:(e,t,o)=>O(o,i,[e,t]),addLinkedRowIdsListener:(e,t,o)=>(A(e,t),O(o,L,[e,t])),delListener:e=>(B(...q(e)),G),destroy:C,getListenerStats:()=>({})};return E(G)}));export{T as createRelationships};
Binary file