tinybase 0.9.3 → 1.0.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.
Files changed (60) hide show
  1. package/LICENSE +1 -1
  2. package/lib/debug/checkpoints.d.ts +3 -0
  3. package/lib/debug/common.d.ts +56 -0
  4. package/lib/debug/indexes.d.ts +7 -58
  5. package/lib/debug/metrics.d.ts +6 -2
  6. package/lib/debug/persisters.d.ts +15 -8
  7. package/lib/debug/relationships.d.ts +3 -1
  8. package/lib/debug/store.d.ts +13 -10
  9. package/lib/debug/tinybase.js +16 -8
  10. package/lib/debug/ui-react.d.ts +29 -2
  11. package/lib/debug/ui-react.js +8 -2
  12. package/package.json +28 -12
  13. package/readme.md +2 -2
  14. package/lib/checkpoints.d.ts +0 -876
  15. package/lib/checkpoints.js +0 -1
  16. package/lib/checkpoints.js.gz +0 -0
  17. package/lib/common.d.ts +0 -59
  18. package/lib/debug/checkpoints.js +0 -326
  19. package/lib/debug/indexes.js +0 -390
  20. package/lib/debug/metrics.js +0 -391
  21. package/lib/debug/persisters.js +0 -191
  22. package/lib/debug/relationships.js +0 -418
  23. package/lib/debug/store.js +0 -725
  24. package/lib/indexes.d.ts +0 -829
  25. package/lib/indexes.js +0 -1
  26. package/lib/indexes.js.gz +0 -0
  27. package/lib/metrics.d.ts +0 -753
  28. package/lib/metrics.js +0 -1
  29. package/lib/metrics.js.gz +0 -0
  30. package/lib/persisters.d.ts +0 -704
  31. package/lib/persisters.js +0 -1
  32. package/lib/persisters.js.gz +0 -0
  33. package/lib/relationships.d.ts +0 -1114
  34. package/lib/relationships.js +0 -1
  35. package/lib/relationships.js.gz +0 -0
  36. package/lib/store.d.ts +0 -2503
  37. package/lib/store.js +0 -1
  38. package/lib/store.js.gz +0 -0
  39. package/lib/tinybase.d.ts +0 -13
  40. package/lib/tinybase.js +0 -1
  41. package/lib/tinybase.js.gz +0 -0
  42. package/lib/ui-react.d.ts +0 -7158
  43. package/lib/ui-react.js +0 -1
  44. package/lib/ui-react.js.gz +0 -0
  45. package/lib/umd/checkpoints.js +0 -1
  46. package/lib/umd/checkpoints.js.gz +0 -0
  47. package/lib/umd/indexes.js +0 -1
  48. package/lib/umd/indexes.js.gz +0 -0
  49. package/lib/umd/metrics.js +0 -1
  50. package/lib/umd/metrics.js.gz +0 -0
  51. package/lib/umd/persisters.js +0 -1
  52. package/lib/umd/persisters.js.gz +0 -0
  53. package/lib/umd/relationships.js +0 -1
  54. package/lib/umd/relationships.js.gz +0 -0
  55. package/lib/umd/store.js +0 -1
  56. package/lib/umd/store.js.gz +0 -0
  57. package/lib/umd/tinybase.js +0 -1
  58. package/lib/umd/tinybase.js.gz +0 -0
  59. package/lib/umd/ui-react.js +0 -1
  60. package/lib/umd/ui-react.js.gz +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022-
3
+ Copyright (c) James Pearce, 2021-
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -142,6 +142,9 @@ export type CheckpointsListenerStats = {
142
142
  * checkpoints.delListener(listenerId);
143
143
  * checkpoints.destroy();
144
144
  * ```
145
+ * @see Relationships And Checkpoints guides
146
+ * @see Todo App demos
147
+ * @see TinyDraw demo
145
148
  * @category Checkpoints
146
149
  */
147
150
  export interface Checkpoints {
@@ -57,3 +57,59 @@ export type ParameterizedCallback<Parameter> = (parameter?: Parameter) => void;
57
57
  * @category Callback
58
58
  */
59
59
  export type Callback = () => void;
60
+
61
+ /**
62
+ * The SortKey type represents a value that can be used by a sort function.
63
+ *
64
+ * @category Parameter
65
+ */
66
+ export type SortKey = string | number | boolean;
67
+
68
+ /**
69
+ * The defaultSorter function is provided as a convenience to sort keys
70
+ * alphanumerically, and can be provided to the `sliceIdSorter` and
71
+ * `rowIdSorter` parameters of the setIndexDefinition method in the indexes
72
+ * module, for example.
73
+ *
74
+ * @param sortKey1 The first item of the pair to compare.
75
+ * @param sortKey2 The second item of the pair to compare.
76
+ * @returns A number indicating how to sort the pair.
77
+ * @example
78
+ * This example creates an Indexes object.
79
+ *
80
+ * ```js
81
+ * const store = createStore();
82
+ * const indexes = createIndexes(store);
83
+ * console.log(indexes.getIndexIds());
84
+ * // -> []
85
+ * ```
86
+ * @example
87
+ * This example creates a Store, creates an Indexes object, and defines an
88
+ * Index based on the first letter of the pets' names. The Slice Ids (and Row
89
+ * Ids within them) are alphabetically sorted using the defaultSorter function.
90
+ *
91
+ * ```js
92
+ * const store = createStore().setTable('pets', {
93
+ * fido: {species: 'dog'},
94
+ * felix: {species: 'cat'},
95
+ * cujo: {species: 'dog'},
96
+ * });
97
+ *
98
+ * const indexes = createIndexes(store);
99
+ * indexes.setIndexDefinition(
100
+ * 'byFirst', // indexId
101
+ * 'pets', // tableId
102
+ * (_, rowId) => rowId[0], // each Row's Slice Id
103
+ * (_, rowId) => rowId, // each Row's sort key
104
+ * defaultSorter, // sort Slice Ids
105
+ * defaultSorter, // sort Row Ids by sort key
106
+ * );
107
+ *
108
+ * console.log(indexes.getSliceIds('byFirst'));
109
+ * // -> ['c', 'f']
110
+ * console.log(indexes.getSliceRowIds('byFirst', 'f'));
111
+ * // -> ['felix', 'fido']
112
+ * ```
113
+ * @category Convenience
114
+ */
115
+ export function defaultSorter(sortKey1: SortKey, sortKey2: SortKey): number;
@@ -3,8 +3,8 @@
3
3
  * and track indexes of the data in Store objects.
4
4
  *
5
5
  * The main entry point to this module is the createIndexes function, which
6
- * returns a new Indexes object. From there, you can create new index
7
- * definitions, access the contents of those indexes directly, and register
6
+ * returns a new Indexes object. From there, you can create new Index
7
+ * definitions, access the contents of those Indexes directly, and register
8
8
  * listeners for when they change.
9
9
  *
10
10
  * @packageDocumentation
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import {GetCell, Store} from './store.d';
15
- import {Id, IdOrNull, Ids} from './common.d';
15
+ import {Id, IdOrNull, Ids, SortKey} from './common.d';
16
16
 
17
17
  /**
18
18
  * The Index type represents the concept of a map of Slice objects, keyed by Id.
@@ -43,13 +43,6 @@ export type Index = {[sliceId: Id]: Slice};
43
43
  */
44
44
  export type Slice = Ids;
45
45
 
46
- /**
47
- * The SortKey type represents a value that can be used by a sort function.
48
- *
49
- * @category Parameter
50
- */
51
- export type SortKey = string | number | boolean;
52
-
53
46
  /**
54
47
  * The SliceIdsListener type describes a function that is used to listen to
55
48
  * changes to the Slice Ids in an Index.
@@ -157,6 +150,10 @@ export type IndexesListenerStats = {
157
150
  * indexes.delListener(listenerId);
158
151
  * indexes.destroy();
159
152
  * ```
153
+ * @see Metrics And Indexes guides
154
+ * @see Rolling Dice demos
155
+ * @see Country demo
156
+ * @see Todo App demos
160
157
  * @category Indexes
161
158
  */
162
159
  export interface Indexes {
@@ -779,51 +776,3 @@ export interface Indexes {
779
776
  * @category Creation
780
777
  */
781
778
  export function createIndexes(store: Store): Indexes;
782
-
783
- /**
784
- * The defaultSorter function is provided as a convenience to sort keys
785
- * alphanumerically, and can be provided to the `sliceIdSorter` and
786
- * `rowIdSorter` parameters of the setIndexDefinition method, for example.
787
- *
788
- * @param sortKey1 The first item of the pair to compare.
789
- * @param sortKey2 The second item of the pair to compare.
790
- * @returns A number indicating how to sort the pair.
791
- * @example
792
- * This example creates an Indexes object.
793
- *
794
- * ```js
795
- * const store = createStore();
796
- * const indexes = createIndexes(store);
797
- * console.log(indexes.getIndexIds());
798
- * // -> []
799
- * ```
800
- * @example
801
- * This example creates a Store, creates an Indexes object, and defines an
802
- * Index based on the first letter of the pets' names. The Slice Ids (and Row
803
- * Ids within them) are alphabetically sorted using the defaultSorter function.
804
- *
805
- * ```js
806
- * const store = createStore().setTable('pets', {
807
- * fido: {species: 'dog'},
808
- * felix: {species: 'cat'},
809
- * cujo: {species: 'dog'},
810
- * });
811
- *
812
- * const indexes = createIndexes(store);
813
- * indexes.setIndexDefinition(
814
- * 'byFirst', // indexId
815
- * 'pets', // tableId
816
- * (_, rowId) => rowId[0], // each Row's Slice Id
817
- * (_, rowId) => rowId, // each Row's sort key
818
- * defaultSorter, // sort Slice Ids
819
- * defaultSorter, // sort Row Ids by sort key
820
- * );
821
- *
822
- * console.log(indexes.getSliceIds('byFirst'));
823
- * // -> ['c', 'f']
824
- * console.log(indexes.getSliceRowIds('byFirst', 'f'));
825
- * // -> ['felix', 'fido']
826
- * ```
827
- * @category Convenience
828
- */
829
- export function defaultSorter(sortKey1: SortKey, sortKey2: SortKey): number;
@@ -3,8 +3,8 @@
3
3
  * and track metrics and aggregates of the data in Store objects.
4
4
  *
5
5
  * The main entry point to this module is the createMetrics function, which
6
- * returns a new Metrics object. From there, you can create new metric
7
- * definitions, access the values of those metrics directly, and register
6
+ * returns a new Metrics object. From there, you can create new Metric
7
+ * definitions, access the values of those Metrics directly, and register
8
8
  * listeners for when they change.
9
9
  *
10
10
  * @packageDocumentation
@@ -226,6 +226,10 @@ export type MetricsListenerStats = {
226
226
  * metrics.delListener(listenerId);
227
227
  * metrics.destroy();
228
228
  * ```
229
+ * @see Metrics And Indexes guides
230
+ * @see Rolling Dice demos
231
+ * @see Country demo
232
+ * @see Todo App demos
229
233
  * @category Metrics
230
234
  */
231
235
  export interface Metrics {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The persisters module of the TinyBase project provides a simple framework
3
- * for saving and loading Store data, to and from different destinations, or
2
+ * The persisters module of the TinyBase project provides a simple framework for
3
+ * saving and loading Store data, to and from different destinations, or
4
4
  * underlying storage types.
5
5
  *
6
6
  * Several entry points are provided, each of which returns a new Persister
@@ -19,12 +19,16 @@
19
19
  * createCustomPersister function can also be used to easily create a fully
20
20
  * customized way to save and load Store data.
21
21
  *
22
+ * @see Persisting Data guide
23
+ * @see Countries demo
24
+ * @see Todo App demos
25
+ * @see TinyDraw demo
22
26
  * @packageDocumentation
23
27
  * @module persisters
24
28
  */
25
29
 
26
30
  import {Store, Tables} from './store.d';
27
- import {Callback} from './common';
31
+ import {Callback} from './common.d';
28
32
 
29
33
  /**
30
34
  * The PersisterStats type describes the number of times a Persister object has
@@ -243,6 +247,7 @@ export interface Persister {
243
247
  * console.log(store.getTables());
244
248
  * // -> {pets: {toto: {species: 'dog'}}}
245
249
  *
250
+ * persister.destroy();
246
251
  * sessionStorage.clear();
247
252
  * ```
248
253
  * @category Load
@@ -284,6 +289,7 @@ export interface Persister {
284
289
  * // -> {pets: {toto: {species: 'dog'}}}
285
290
  * // Storage change has not been automatically loaded.
286
291
  *
292
+ * persister.destroy();
287
293
  * sessionStorage.clear();
288
294
  * ```
289
295
  * @category Load
@@ -650,8 +656,9 @@ export function createFilePersister(store: Store, filePath: string): Persister;
650
656
  * layer.
651
657
  *
652
658
  * The other creation functions (such as the createSessionPersister function and
653
- * createFilePersister function, for example) all use this under the covers. See
654
- * those implementations for ideas on how to implement your own Persister types.
659
+ * createFilePersister function, for example) all use this function under the
660
+ * covers. See those implementations for ideas on how to implement your own
661
+ * Persister types.
655
662
  *
656
663
  * @param store The Store to persist.
657
664
  * @param getPersisted An asynchronous function which will fetch JSON from the
@@ -664,9 +671,9 @@ export function createFilePersister(store: Store, filePath: string): Persister;
664
671
  * from the underlying changes to the persistence layer.
665
672
  * @returns A reference to the new Persister object.
666
673
  * @example
667
- * This example creates a Persister object and persists the Store to a local
668
- * string called `storeJson` and would automatically load by polling for changes
669
- * every second.
674
+ * This example creates a custom Persister object and persists the Store to a
675
+ * local string called `storeJson` and which would automatically load by polling
676
+ * for changes every second.
670
677
  *
671
678
  * ```js
672
679
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * The main entry point to this module is the createRelationships function,
6
6
  * which returns a new Relationships object. From there, you can create new
7
- * relationship definitions, access the associations within those relationships
7
+ * Relationship definitions, access the associations within those Relationships
8
8
  * directly, and register listeners for when they change.
9
9
  *
10
10
  * @packageDocumentation
@@ -222,6 +222,8 @@ export type RelationshipsListenerStats = {
222
222
  * relationships.delListener(listenerId2);
223
223
  * relationships.destroy();
224
224
  * ```
225
+ * @see Relationships And Checkpoints guides
226
+ * @see TinyDraw demo
225
227
  * @category Relationships
226
228
  */
227
229
  export interface Relationships {
@@ -17,11 +17,10 @@ import {Id, IdOrNull, Ids, Json} from './common.d';
17
17
  * The Tables type is the data structure representing all of the data in a
18
18
  * Store.
19
19
  *
20
- * A Tables object can be provided to the createStore function when first
21
- * creating the Store. It is also used when setting all of the tables together
22
- * with the setTables method, and when getting them back out again with the
23
- * getTables method. A Tables object is a regular JavaScript object containing
24
- * individual Table objects, keyed by their Id.
20
+ * A Tables object is used when setting all of the tables together with the
21
+ * setTables method, and when getting them back out again with the getTables
22
+ * method. A Tables object is a regular JavaScript object containing individual
23
+ * Table objects, keyed by their Id.
25
24
  *
26
25
  * @example
27
26
  * ```js
@@ -371,8 +370,8 @@ export type CellChange = [
371
370
  * Ids and the types of Cell that can exist within them.
372
371
  *
373
372
  * A Schema comprises a JavaScript object describing each Table, in turn a
374
- * nested JavaScript object containing the each Cell and its CellSchema. It is
375
- * provided to the createStore function or to the setSchema method.
373
+ * nested JavaScript object containing information about each Cell and its
374
+ * CellSchema. It is provided to the setSchema method.
376
375
  *
377
376
  * @example
378
377
  * When applied to a Store, this Schema only allows one Table called `pets`, in
@@ -613,6 +612,10 @@ export type StoreListenerStats = {
613
612
  *
614
613
  * store.delListener(listenerId);
615
614
  * ```
615
+ * @see The Basics guides
616
+ * @see Using Schemas guides
617
+ * @see Hello World demos
618
+ * @see Todo App demos
616
619
  * @category Store
617
620
  */
618
621
  export interface Store {
@@ -1339,9 +1342,8 @@ export interface Store {
1339
1342
  * applied or as invalid Table, Row, or Cell objects are removed. These
1340
1343
  * changes will fire any listeners to that data, as expected.
1341
1344
  *
1342
- * You can also specify the Schema at the time of creation, as the second
1343
- * parameter of the createStore function. When no longer needed, you can also
1344
- * completely remove an existing Schema with the delSchema method.
1345
+ * When no longer needed, you can also completely remove an existing Schema
1346
+ * with the delSchema method.
1345
1347
  *
1346
1348
  * @param schema The Schema to be set for the Store.
1347
1349
  * @returns A reference to the Store.
@@ -2498,6 +2500,7 @@ export interface Store {
2498
2500
  * console.log(store.getTables());
2499
2501
  * // -> {pets: {fido: {species: 'dog', sold: false}}}
2500
2502
  * ```
2503
+ * @see The Basics guides
2501
2504
  * @category Creation
2502
2505
  */
2503
2506
  export function createStore(): Store;
@@ -509,6 +509,8 @@ const createCheckpoints = getCreateFunction((store) => {
509
509
  return objFreeze(checkpoints.clear());
510
510
  });
511
511
 
512
+ const defaultSorter = (sortKey1, sortKey2) => (sortKey1 < sortKey2 ? -1 : 1);
513
+
512
514
  const createIndexes = getCreateFunction((store) => {
513
515
  const sliceIdsListeners = mapNew();
514
516
  const sliceRowIdsListeners = mapNew();
@@ -541,7 +543,7 @@ const createIndexes = getCreateFunction((store) => {
541
543
  setDefinition(
542
544
  indexId,
543
545
  tableId,
544
- (change, changedSliceIds, changedSortKeys, sliceIds, sortKeys) => {
546
+ (change, changedSliceIds, changedSortKeys, sliceIds, sortKeys, force) => {
545
547
  let sliceIdsChanged = 0;
546
548
  const changedSlices = setNew();
547
549
  const unsortedSlices = setNew();
@@ -570,12 +572,16 @@ const createIndexes = getCreateFunction((store) => {
570
572
  }
571
573
  });
572
574
  change();
573
- mapForEach(changedSortKeys, (rowId) =>
574
- ifNotUndefined(mapGet(sliceIds, rowId), (sliceId) =>
575
- setAdd(unsortedSlices, sliceId),
576
- ),
577
- );
578
575
  if (!collIsEmpty(sortKeys)) {
576
+ if (force) {
577
+ mapForEach(index, (sliceId) => setAdd(unsortedSlices, sliceId));
578
+ } else {
579
+ mapForEach(changedSortKeys, (rowId) =>
580
+ ifNotUndefined(mapGet(sliceIds, rowId), (sliceId) =>
581
+ setAdd(unsortedSlices, sliceId),
582
+ ),
583
+ );
584
+ }
579
585
  collForEach(unsortedSlices, (sliceId) => {
580
586
  const rowIdArraySorter = (rowId1, rowId2) =>
581
587
  rowIdSorter(
@@ -594,7 +600,7 @@ const createIndexes = getCreateFunction((store) => {
594
600
  }
595
601
  });
596
602
  }
597
- if (sliceIdsChanged) {
603
+ if (sliceIdsChanged || force) {
598
604
  if (!isUndefined(sliceIdArraySorter)) {
599
605
  const indexArray = [...index];
600
606
  if (!arrayIsSorted(indexArray, sliceIdArraySorter)) {
@@ -602,8 +608,11 @@ const createIndexes = getCreateFunction((store) => {
602
608
  indexId,
603
609
  mapNew(arraySort(indexArray, sliceIdArraySorter)),
604
610
  );
611
+ sliceIdsChanged = 1;
605
612
  }
606
613
  }
614
+ }
615
+ if (sliceIdsChanged) {
607
616
  callListeners(sliceIdsListeners, [indexId]);
608
617
  }
609
618
  collForEach(changedSlices, (sliceId) =>
@@ -650,7 +659,6 @@ const createIndexes = getCreateFunction((store) => {
650
659
  };
651
660
  return objFreeze(indexes);
652
661
  });
653
- const defaultSorter = (sortKey1, sortKey2) => (sortKey1 < sortKey2 ? -1 : 1);
654
662
 
655
663
  const aggregators = mapNew([
656
664
  [
@@ -10,11 +10,19 @@
10
10
  * The components in this module provide a further abstraction over those hooks
11
11
  * to ease the composition of user interfaces that use TinyBase.
12
12
  *
13
+ * @see Building UIs guides
14
+ * @see Building UIs With Metrics guide
15
+ * @see Building UIs With Indexes guide
16
+ * @see Building UIs With Relationships guide
17
+ * @see Building UIs With Checkpoints guide
18
+ * @see Countries demo
19
+ * @see Todo App demos
20
+ * @see TinyDraw demo
13
21
  * @packageDocumentation
14
22
  * @module ui-react
15
23
  */
16
24
 
17
- import {Callback, Id, IdOrNull, Ids, ParameterizedCallback} from './common';
25
+ import {Callback, Id, IdOrNull, Ids, ParameterizedCallback} from './common.d';
18
26
  import {
19
27
  Cell,
20
28
  CellIdsListener,
@@ -2213,6 +2221,9 @@ export function useCellListener(
2213
2221
  * an array in the optional second parameter, just as you would for any React
2214
2222
  * hook with dependencies.
2215
2223
  *
2224
+ * This hook ensures the Metrics object is destroyed whenever a new one is
2225
+ * created or the component is unmounted.
2226
+ *
2216
2227
  * @param store A reference to the Store for which to create a new Metrics
2217
2228
  * object.
2218
2229
  * @param create A function for performing the creation steps of the Metrics
@@ -2554,6 +2565,9 @@ export function useMetricListener(
2554
2565
  * an array in the optional second parameter, just as you would for any React
2555
2566
  * hook with dependencies.
2556
2567
  *
2568
+ * This hook ensures the Indexes object is destroyed whenever a new one is
2569
+ * created or the component is unmounted.
2570
+ *
2557
2571
  * @param store A reference to the Store for which to create a new Indexes
2558
2572
  * object.
2559
2573
  * @param create A function for performing the creation steps of the Indexes
@@ -3104,6 +3118,9 @@ export function useSliceRowIdsListener(
3104
3118
  * them in an array in the optional second parameter, just as you would for any
3105
3119
  * React hook with dependencies.
3106
3120
  *
3121
+ * This hook ensures the Relationships object is destroyed whenever a new one is
3122
+ * created or the component is unmounted.
3123
+ *
3107
3124
  * @param store A reference to the Store for which to create a new Relationships
3108
3125
  * object.
3109
3126
  * @param create An optional callback for performing post-creation steps on the
@@ -3900,6 +3917,9 @@ export function useLinkedRowIdsListener(
3900
3917
  * them in an array in the optional second parameter, just as you would for any
3901
3918
  * React hook with dependencies.
3902
3919
  *
3920
+ * This hook ensures the Checkpoints object is destroyed whenever a new one is
3921
+ * created or the component is unmounted.
3922
+ *
3903
3923
  * @param store A reference to the Store for which to create a new Checkpoints
3904
3924
  * object.
3905
3925
  * @param create A function for performing the creation steps of the Checkpoints
@@ -4751,6 +4771,9 @@ export function useCheckpointListener(
4751
4771
  * an array in the fifth parameter. The Persister itself is used as a dependency
4752
4772
  * by default.
4753
4773
  *
4774
+ * This hook ensures the Persister object is destroyed whenever a new one is
4775
+ * created or the component is unmounted.
4776
+ *
4754
4777
  * @param store A reference to the Store for which to create a new Persister
4755
4778
  * object.
4756
4779
  * @param create A function for performing the creation steps of the Persister
@@ -4795,10 +4818,12 @@ export function useCheckpointListener(
4795
4818
  *
4796
4819
  * // ... // !act
4797
4820
  * ReactDOM.render(<App />, app); // !act
4798
- * // No second Checkpoints creation
4821
+ * // No second Persister creation
4799
4822
  *
4800
4823
  * console.log(app.innerHTML);
4801
4824
  * // -> '<span>{\"pets\":{\"fido\":{\"species\":\"dog\"}}}</span>'
4825
+ *
4826
+ * ReactDOM.unmountComponentAtNode(app); // !act
4802
4827
  * ```
4803
4828
  * @example
4804
4829
  * This example creates a Persister at the top level of a React application. The
@@ -4841,6 +4866,8 @@ export function useCheckpointListener(
4841
4866
  * // ... // !act
4842
4867
  * console.log(app.innerHTML);
4843
4868
  * // -> '<span>{\"pets\":{\"cujo\":{\"species\":\"dog\"}}}</span>'
4869
+ *
4870
+ * ReactDOM.unmountComponentAtNode(app); // !act
4844
4871
  * ```
4845
4872
  * @category Persister hooks
4846
4873
  */
@@ -48,8 +48,11 @@ const useCheckpointsOrCheckpointsId = (checkpointsOrCheckpointsId) =>
48
48
  useThingOrThingId(checkpointsOrCheckpointsId, 8);
49
49
 
50
50
  const {useCallback, useEffect, useMemo: useMemo$1, useState} = React;
51
- const useCreate = (store, create, createDeps = []) =>
52
- useMemo$1(() => create(store), [store, ...createDeps]);
51
+ const useCreate = (store, create, createDeps = []) => {
52
+ const thing = useMemo$1(() => create(store), [store, ...createDeps]);
53
+ useEffect(() => () => thing.destroy(), [thing]);
54
+ return thing;
55
+ };
53
56
  const useListenable = (listenable, thing, defaulted, ...args) => {
54
57
  const getListenable = thing?.['get' + listenable] ?? (() => defaulted);
55
58
  const immediateListenable = getListenable(...args);
@@ -654,6 +657,9 @@ const useCreatePersister = (
654
657
  setDone(1);
655
658
  return;
656
659
  })();
660
+ return () => {
661
+ persister.destroy();
662
+ };
657
663
  }, [persister, ...thenDeps]);
658
664
  return persister;
659
665
  };
package/package.json CHANGED
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "0.9.3",
3
+ "version": "1.0.2",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
7
7
  "homepage": "https://tinybase.org",
8
8
  "description": "A tiny, reactive JavaScript library for structured state and tabular data.",
9
+ "keywords": [
10
+ "tiny",
11
+ "reactive",
12
+ "state",
13
+ "data",
14
+ "react"
15
+ ],
9
16
  "type": "module",
10
17
  "files": [
11
18
  "lib/**"
@@ -14,6 +21,14 @@
14
21
  ".": "./lib/tinybase.js",
15
22
  "./*": "./lib/*.js"
16
23
  },
24
+ "typesVersions": {
25
+ "*": {
26
+ "*": [
27
+ "./lib/*.d.ts",
28
+ "./lib/tinybase.d.ts"
29
+ ]
30
+ }
31
+ },
17
32
  "browser": {
18
33
  "fs": false
19
34
  },
@@ -33,15 +48,16 @@
33
48
  "compileDocsPagesOnly": "gulp compileDocsPagesOnly",
34
49
  "compileDocsAssetsOnly": "gulp compileDocsAssetsOnly",
35
50
  "compileDocs": "gulp compileDocs",
51
+ "compileForProdAndDocs": "gulp compileForProdAndDocs",
36
52
  "serveDocs": "gulp serveDocs",
37
53
  "preCommit": "gulp preCommit",
38
54
  "prePublishPackage": "gulp prePublishPackage",
39
55
  "publishPackage": "gulp publishPackage"
40
56
  },
41
57
  "devDependencies": {
42
- "@babel/cli": "^7.16.7",
58
+ "@babel/cli": "^7.16.8",
43
59
  "@babel/core": "^7.16.7",
44
- "@babel/preset-env": "^7.16.7",
60
+ "@babel/preset-env": "^7.16.8",
45
61
  "@babel/preset-react": "^7.16.7",
46
62
  "@babel/preset-typescript": "^7.16.7",
47
63
  "@rollup/plugin-replace": "^3.0.1",
@@ -56,24 +72,24 @@
56
72
  "@types/react-dom": "^17.0.11",
57
73
  "@types/react-test-renderer": "^17.0.1",
58
74
  "@types/tmp": "^0.2.3",
59
- "@typescript-eslint/eslint-plugin": "^5.9.0",
60
- "@typescript-eslint/parser": "^5.9.0",
75
+ "@typescript-eslint/eslint-plugin": "^5.9.1",
76
+ "@typescript-eslint/parser": "^5.9.1",
61
77
  "asciichart": "^1.5.25",
62
78
  "babel-eslint": "^10.1.0",
63
79
  "babel-jest": "^27.4.6",
64
80
  "babel-preset-minify": "^0.5.1",
65
81
  "country-flag-emoji-json": "^2.0.0",
66
- "cspell": "^5.14.0",
67
- "esbuild": "^0.14.10",
68
- "eslint": "^8.6.0",
82
+ "cspell": "^5.15.2",
83
+ "esbuild": "^0.14.11",
84
+ "eslint": "^8.7.0",
69
85
  "eslint-config-prettier": "^8.3.0",
70
- "eslint-plugin-jest": "^25.3.4",
71
- "eslint-plugin-jsdoc": "^37.5.1",
86
+ "eslint-plugin-jest": "^25.7.0",
87
+ "eslint-plugin-jsdoc": "^37.6.1",
72
88
  "eslint-plugin-react": "^7.28.0",
73
89
  "eslint-plugin-react-hooks": "^4.3.0",
74
90
  "gulp": "^4.0.2",
75
91
  "gulp-gzip": "^1.4.2",
76
- "http-server": "^14.0.0",
92
+ "http-server": "^14.1.0",
77
93
  "jest": "^27.4.7",
78
94
  "jest-fetch-mock": "^3.0.3",
79
95
  "jest-puppeteer": "^6.0.3",
@@ -83,7 +99,7 @@
83
99
  "react": "^17.0.2",
84
100
  "react-dom": "^17.0.2",
85
101
  "react-test-renderer": "^17.0.2",
86
- "rollup": "^2.63.0",
102
+ "rollup": "^2.64.0",
87
103
  "rollup-plugin-esbuild": "^4.8.2",
88
104
  "rollup-plugin-gzip": "^3.0.0",
89
105
  "rollup-plugin-prettier": "^2.2.2",