tinybase 4.0.0-beta.0 → 4.0.0-beta.1

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 (103) hide show
  1. package/lib/cjs/persister-browser.cjs +1 -0
  2. package/lib/cjs/persister-browser.cjs.gz +0 -0
  3. package/lib/cjs/persister-file.cjs +1 -0
  4. package/lib/cjs/persister-file.cjs.gz +0 -0
  5. package/lib/cjs/persister-remote.cjs +1 -0
  6. package/lib/cjs/persister-remote.cjs.gz +0 -0
  7. package/lib/cjs/persister-yjs.cjs +1 -1
  8. package/lib/cjs/persister-yjs.cjs.gz +0 -0
  9. package/lib/cjs/persisters.cjs +1 -1
  10. package/lib/cjs/persisters.cjs.gz +0 -0
  11. package/lib/cjs/store.cjs +1 -1
  12. package/lib/cjs/store.cjs.gz +0 -0
  13. package/lib/cjs/tinybase.cjs +1 -1
  14. package/lib/cjs/tinybase.cjs.gz +0 -0
  15. package/lib/cjs-es6/persister-browser.cjs +1 -0
  16. package/lib/cjs-es6/persister-browser.cjs.gz +0 -0
  17. package/lib/cjs-es6/persister-file.cjs +1 -0
  18. package/lib/cjs-es6/persister-file.cjs.gz +0 -0
  19. package/lib/cjs-es6/persister-remote.cjs +1 -0
  20. package/lib/cjs-es6/persister-remote.cjs.gz +0 -0
  21. package/lib/cjs-es6/persister-yjs.cjs +1 -1
  22. package/lib/cjs-es6/persister-yjs.cjs.gz +0 -0
  23. package/lib/cjs-es6/persisters.cjs +1 -1
  24. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  25. package/lib/cjs-es6/store.cjs +1 -1
  26. package/lib/cjs-es6/store.cjs.gz +0 -0
  27. package/lib/cjs-es6/tinybase.cjs +1 -1
  28. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  29. package/lib/debug/persister-browser.js +148 -0
  30. package/lib/debug/persister-file.js +140 -0
  31. package/lib/debug/persister-remote.js +156 -0
  32. package/lib/debug/persister-yjs.js +30 -21
  33. package/lib/debug/persisters.js +24 -117
  34. package/lib/debug/store.js +36 -21
  35. package/lib/debug/tinybase.js +59 -135
  36. package/lib/es6/persister-browser.js +1 -0
  37. package/lib/es6/persister-browser.js.gz +0 -0
  38. package/lib/es6/persister-file.js +1 -0
  39. package/lib/es6/persister-file.js.gz +0 -0
  40. package/lib/es6/persister-remote.js +1 -0
  41. package/lib/es6/persister-remote.js.gz +0 -0
  42. package/lib/es6/persister-yjs.js +1 -1
  43. package/lib/es6/persister-yjs.js.gz +0 -0
  44. package/lib/es6/persisters.js +1 -1
  45. package/lib/es6/persisters.js.gz +0 -0
  46. package/lib/es6/store.js +1 -1
  47. package/lib/es6/store.js.gz +0 -0
  48. package/lib/es6/tinybase.js +1 -1
  49. package/lib/es6/tinybase.js.gz +0 -0
  50. package/lib/persister-browser.js +1 -0
  51. package/lib/persister-browser.js.gz +0 -0
  52. package/lib/persister-file.js +1 -0
  53. package/lib/persister-file.js.gz +0 -0
  54. package/lib/persister-remote.js +1 -0
  55. package/lib/persister-remote.js.gz +0 -0
  56. package/lib/persister-yjs.js +1 -1
  57. package/lib/persister-yjs.js.gz +0 -0
  58. package/lib/persisters.js +1 -1
  59. package/lib/persisters.js.gz +0 -0
  60. package/lib/store.js +1 -1
  61. package/lib/store.js.gz +0 -0
  62. package/lib/tinybase.js +1 -1
  63. package/lib/tinybase.js.gz +0 -0
  64. package/lib/types/persister-browser.d.ts +85 -0
  65. package/lib/types/persister-file.d.ts +41 -0
  66. package/lib/types/persister-remote.d.ts +60 -0
  67. package/lib/types/persisters.d.ts +40 -173
  68. package/lib/types/store.d.ts +117 -11
  69. package/lib/types/with-schemas/persister-browser.d.ts +103 -0
  70. package/lib/types/with-schemas/persister-file.d.ts +50 -0
  71. package/lib/types/with-schemas/persister-remote.d.ts +71 -0
  72. package/lib/types/with-schemas/persisters.d.ts +49 -214
  73. package/lib/types/with-schemas/store.d.ts +136 -11
  74. package/lib/umd/persister-browser.js +1 -0
  75. package/lib/umd/persister-browser.js.gz +0 -0
  76. package/lib/umd/persister-file.js +1 -0
  77. package/lib/umd/persister-file.js.gz +0 -0
  78. package/lib/umd/persister-remote.js +1 -0
  79. package/lib/umd/persister-remote.js.gz +0 -0
  80. package/lib/umd/persister-yjs.js +1 -1
  81. package/lib/umd/persister-yjs.js.gz +0 -0
  82. package/lib/umd/persisters.js +1 -1
  83. package/lib/umd/persisters.js.gz +0 -0
  84. package/lib/umd/store.js +1 -1
  85. package/lib/umd/store.js.gz +0 -0
  86. package/lib/umd/tinybase.js +1 -1
  87. package/lib/umd/tinybase.js.gz +0 -0
  88. package/lib/umd-es6/persister-browser.js +1 -0
  89. package/lib/umd-es6/persister-browser.js.gz +0 -0
  90. package/lib/umd-es6/persister-file.js +1 -0
  91. package/lib/umd-es6/persister-file.js.gz +0 -0
  92. package/lib/umd-es6/persister-remote.js +1 -0
  93. package/lib/umd-es6/persister-remote.js.gz +0 -0
  94. package/lib/umd-es6/persister-yjs.js +1 -1
  95. package/lib/umd-es6/persister-yjs.js.gz +0 -0
  96. package/lib/umd-es6/persisters.js +1 -1
  97. package/lib/umd-es6/persisters.js.gz +0 -0
  98. package/lib/umd-es6/store.js +1 -1
  99. package/lib/umd-es6/store.js.gz +0 -0
  100. package/lib/umd-es6/tinybase.js +1 -1
  101. package/lib/umd-es6/tinybase.js.gz +0 -0
  102. package/package.json +9 -9
  103. package/readme.md +2 -2
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The persister-remote module of the TinyBase project lets you save and load
3
+ * Store data to and from a remote server.
4
+ *
5
+ * @see Persisting Data guide
6
+ * @packageDocumentation
7
+ * @module persister-remote
8
+ */
9
+
10
+ import {OptionalSchemas, Store} from './store';
11
+ import {Persister} from './persisters';
12
+
13
+ /**
14
+ * The createRemotePersister function creates a Persister object that can
15
+ * persist the Store to a remote server.
16
+ *
17
+ * This has schema-based typing. The following is a simplified representation:
18
+ *
19
+ * ```ts override
20
+ * createRemotePersister(
21
+ * store: Store,
22
+ * loadUrl: string,
23
+ * saveUrl: string,
24
+ * autoLoadIntervalSeconds: number,
25
+ * ): Persister;
26
+ * ```
27
+ *
28
+ * As well as providing a reference to the Store to persist, you must provide
29
+ * `loadUrl` and `saveUrl` parameters. These identify the endpoints of the
30
+ * server that support the `GET` method (to fetch the Store JSON to load) and
31
+ * the `POST` method (to send the Store JSON to save) respectively.
32
+ *
33
+ * For when you choose to enable automatic loading for the Persister (with the
34
+ * startAutoLoad method), it will poll the loadUrl for changes. The
35
+ * `autoLoadIntervalSeconds` method is used to indicate how often to do this.
36
+ *
37
+ * @param store The Store to persist.
38
+ * @param loadUrl The endpoint that supports a `GET` method to load JSON.
39
+ * @param saveUrl The endpoint that supports a `POST` method to save JSON.
40
+ * @param autoLoadIntervalSeconds How often to poll the `loadUrl` when
41
+ * automatically loading changes from the server.
42
+ * @returns A reference to the new Persister object.
43
+ * @example
44
+ * This example creates a Persister object and persists the Store to a remote
45
+ * server.
46
+ *
47
+ * ```js yolo
48
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
49
+ * const persister = createRemotePersister(
50
+ * store,
51
+ * 'https://example.com/load',
52
+ * 'https://example.com/save',
53
+ * 5,
54
+ * );
55
+ *
56
+ * await persister.save();
57
+ * // Store JSON will be sent to server in a POST request.
58
+ *
59
+ * await persister.load();
60
+ * // Store JSON will be fetched from server with a GET request.
61
+ *
62
+ * persister.destroy();
63
+ * ```
64
+ * @category Creation
65
+ */
66
+ export function createRemotePersister<Schemas extends OptionalSchemas>(
67
+ store: Store<Schemas>,
68
+ loadUrl: string,
69
+ saveUrl: string,
70
+ autoLoadIntervalSeconds: number,
71
+ ): Persister<Schemas>;
@@ -3,21 +3,21 @@
3
3
  * saving and loading Store data, to and from different destinations, or
4
4
  * underlying storage types.
5
5
  *
6
- * Several entry points are provided, each of which returns a new Persister
7
- * object that can load and save a Store:
8
- *
9
- * - The createSessionPersister function returns a Persister that uses the
10
- * browser's session storage.
11
- * - The createLocalPersister function returns a Persister that uses the
12
- * browser's local storage.
13
- * - The createRemotePersister function returns a Persister that uses a remote
14
- * server.
15
- * - The createFilePersister function returns a Persister that uses a local file
16
- * (in an appropriate environment).
6
+ * Several entry points are provided (in separately installed modules), each of
7
+ * which returns a new Persister object that can load and save a Store:
8
+ *
9
+ * - The createSessionPersister function (in the persister-browser module)
10
+ * returns a Persister that uses the browser's session storage.
11
+ * - The createLocalPersister function (in the persister-browser module) returns
12
+ * a Persister that uses the browser's local storage.
13
+ * - The createRemotePersister function (in the persister-remote module) returns
14
+ * a Persister that uses a remote server.
15
+ * - The createFilePersister function (in the persister-file module) returns a
16
+ * Persister that uses a local file (in an appropriate environment).
17
17
  *
18
18
  * Since persistence requirements can be different for every app, the
19
- * createCustomPersister function can also be used to easily create a fully
20
- * customized way to save and load Store data.
19
+ * createCustomPersister function in this module can also be used to easily
20
+ * create a fully customized way to save and load Store data.
21
21
  *
22
22
  * @see Persisting Data guide
23
23
  * @see Countries demo
@@ -28,7 +28,6 @@
28
28
  */
29
29
 
30
30
  import {OptionalSchemas, Store, Tables, Values} from './store.d';
31
- import {Callback} from './common.d';
32
31
 
33
32
  /**
34
33
  * The PersisterStats type describes the number of times a Persister object has
@@ -50,6 +49,14 @@ export type PersisterStats = {
50
49
  saves?: number;
51
50
  };
52
51
 
52
+ /**
53
+ * A PersisterListener is a callback that lets a Persister inform the Store that
54
+ * a change has happened to the underlying data.
55
+ */
56
+ export type PersisterListener<Schemas extends OptionalSchemas> = (
57
+ content?: [Tables<Schemas[0], true>, Values<Schemas[1], true>],
58
+ ) => void;
59
+
53
60
  /**
54
61
  * A Persister object lets you save and load Store data to and from different
55
62
  * locations, or underlying storage types.
@@ -514,12 +521,12 @@ export interface Persister<in out Schemas extends OptionalSchemas> {
514
521
  * const persister = createSessionPersister(store, 'pets');
515
522
  * await persister.startAutoSave();
516
523
  *
517
- * console.log(store.getListenerStats().tables);
524
+ * console.log(store.getListenerStats().transaction);
518
525
  * // -> 1
519
526
  *
520
527
  * persister.destroy();
521
528
  *
522
- * console.log(store.getListenerStats().tables);
529
+ * console.log(store.getListenerStats().transaction);
523
530
  * // -> 0
524
531
  * ```
525
532
  * @category Lifecycle
@@ -572,189 +579,6 @@ export interface Persister<in out Schemas extends OptionalSchemas> {
572
579
  getStats(): PersisterStats;
573
580
  }
574
581
 
575
- /**
576
- * The createSessionPersister function creates a Persister object that can
577
- * persist the Store to the browser's session storage.
578
- *
579
- * This has schema-based typing. The following is a simplified representation:
580
- *
581
- * ```ts override
582
- * createSessionPersister(
583
- * store: Store,
584
- * storageName: string,
585
- * ): Persister;
586
- * ```
587
- *
588
- * As well as providing a reference to the Store to persist, you must provide a
589
- * `storageName` parameter which is unique to your application. This is the key
590
- * that the browser uses to identify the storage location.
591
- *
592
- * @param store The Store to persist.
593
- * @param storageName The unique key to identify the storage location.
594
- * @returns A reference to the new Persister object.
595
- * @example
596
- * This example creates a Persister object and persists the Store to the
597
- * browser's session storage.
598
- *
599
- * ```js
600
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
601
- * const persister = createSessionPersister(store, 'pets');
602
- *
603
- * await persister.save();
604
- * console.log(sessionStorage.getItem('pets'));
605
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
606
- *
607
- * persister.destroy();
608
- * sessionStorage.clear();
609
- * ```
610
- * @category Creation
611
- */
612
- export function createSessionPersister<Schemas extends OptionalSchemas>(
613
- store: Store<Schemas>,
614
- storageName: string,
615
- ): Persister<Schemas>;
616
-
617
- /**
618
- * The createLocalPersister function creates a Persister object that can
619
- * persist the Store to the browser's local storage.
620
- *
621
- * This has schema-based typing. The following is a simplified representation:
622
- *
623
- * ```ts override
624
- * createLocalPersister(
625
- * store: Store,
626
- * storageName: string,
627
- * ): Persister;
628
- * ```
629
- *
630
- * As well as providing a reference to the Store to persist, you must provide a
631
- * `storageName` parameter which is unique to your application. This is the key
632
- * that the browser uses to identify the storage location.
633
- *
634
- * @param store The Store to persist.
635
- * @param storageName The unique key to identify the storage location.
636
- * @returns A reference to the new Persister object.
637
- * @example
638
- * This example creates a Persister object and persists the Store to the
639
- * browser's local storage.
640
- *
641
- * ```js
642
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
643
- * const persister = createLocalPersister(store, 'pets');
644
- *
645
- * await persister.save();
646
- * console.log(localStorage.getItem('pets'));
647
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
648
- *
649
- * persister.destroy();
650
- * localStorage.clear();
651
- * ```
652
- * @category Creation
653
- */
654
- export function createLocalPersister<Schemas extends OptionalSchemas>(
655
- store: Store<Schemas>,
656
- storageName: string,
657
- ): Persister<Schemas>;
658
-
659
- /**
660
- * The createRemotePersister function creates a Persister object that can
661
- * persist the Store to a remote server.
662
- *
663
- * This has schema-based typing. The following is a simplified representation:
664
- *
665
- * ```ts override
666
- * createRemotePersister(
667
- * store: Store,
668
- * loadUrl: string,
669
- * saveUrl: string,
670
- * autoLoadIntervalSeconds: number,
671
- * ): Persister;
672
- * ```
673
- *
674
- * As well as providing a reference to the Store to persist, you must provide
675
- * `loadUrl` and `saveUrl` parameters. These identify the endpoints of the
676
- * server that support the `GET` method (to fetch the Store JSON to load) and
677
- * the `POST` method (to send the Store JSON to save) respectively.
678
- *
679
- * For when you choose to enable automatic loading for the Persister (with the
680
- * startAutoLoad method), it will poll the loadUrl for changes. The
681
- * `autoLoadIntervalSeconds` method is used to indicate how often to do this.
682
- *
683
- * @param store The Store to persist.
684
- * @param loadUrl The endpoint that supports a `GET` method to load JSON.
685
- * @param saveUrl The endpoint that supports a `POST` method to save JSON.
686
- * @param autoLoadIntervalSeconds How often to poll the `loadUrl` when
687
- * automatically loading changes from the server.
688
- * @returns A reference to the new Persister object.
689
- * @example
690
- * This example creates a Persister object and persists the Store to a remote
691
- * server.
692
- *
693
- * ```js yolo
694
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
695
- * const persister = createRemotePersister(
696
- * store,
697
- * 'https://example.com/load',
698
- * 'https://example.com/save',
699
- * 5,
700
- * );
701
- *
702
- * await persister.save();
703
- * // Store JSON will be sent to server in a POST request.
704
- *
705
- * await persister.load();
706
- * // Store JSON will be fetched from server with a GET request.
707
- *
708
- * persister.destroy();
709
- * ```
710
- * @category Creation
711
- */
712
- export function createRemotePersister<Schemas extends OptionalSchemas>(
713
- store: Store<Schemas>,
714
- loadUrl: string,
715
- saveUrl: string,
716
- autoLoadIntervalSeconds: number,
717
- ): Persister<Schemas>;
718
-
719
- /**
720
- * The createFilePersister function creates a Persister object that can persist
721
- * the Store to a local file (in an appropriate environment).
722
- *
723
- * This has schema-based typing. The following is a simplified representation:
724
- *
725
- * ```ts override
726
- * createFilePersister(store: Store, filePath: string): Persister;
727
- * ```
728
- *
729
- * As well as providing a reference to the Store to persist, you must provide
730
- * `filePath` parameter which identifies the file to persist it to.
731
- *
732
- * @param store The Store to persist.
733
- * @param filePath The location of the local file to persist the Store to.
734
- * @returns A reference to the new Persister object.
735
- * @example
736
- * This example creates a Persister object and persists the Store to a local
737
- * file.
738
- *
739
- * ```js yolo
740
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
741
- * const persister = createFilePersister(store, '/app/persisted.json');
742
- *
743
- * await persister.save();
744
- * // Store JSON will be saved to the file.
745
- *
746
- * await persister.load();
747
- * // Store JSON will be loaded from the file.
748
- *
749
- * persister.destroy();
750
- * ```
751
- * @category Creation
752
- */
753
- export function createFilePersister<Schemas extends OptionalSchemas>(
754
- store: Store<Schemas>,
755
- filePath: string,
756
- ): Persister<Schemas>;
757
-
758
582
  /**
759
583
  * The createCustomPersister function creates a Persister object that you can
760
584
  * configure to persist the Store in any way you wish.
@@ -765,9 +589,9 @@ export function createFilePersister<Schemas extends OptionalSchemas>(
765
589
  * createCustomPersister<ListeningHandle>(
766
590
  * store: Store,
767
591
  * getPersisted: () => Promise<string | null | undefined>,
768
- * setPersisted: (json: string) => Promise<void>,
769
- * startListeningToPersisted: (didChange: Callback) => ListeningHandle,
770
- * stopListeningToPersisted: (listeningHandle: ListeningHandle) => void,
592
+ * setPersisted: (getContent: () => [Tables, Values]) => Promise<void>,
593
+ * addPersisterListener: (listener: PersisterListener) => ListeningHandle,
594
+ * delPersisterListener: (listeningHandle: ListeningHandle) => void,
771
595
  * ): Persister;
772
596
  * ```
773
597
  *
@@ -780,18 +604,25 @@ export function createFilePersister<Schemas extends OptionalSchemas>(
780
604
  * covers. See those implementations for ideas on how to implement your own
781
605
  * Persister types.
782
606
  *
607
+ * This API changed in v4.0.0. Any custom persisters created on previous
608
+ * versions should be upgraded. Most notably, the `setPersisted` function
609
+ * parameter is provided with a `getContent` function to get the content from
610
+ * the Store itself, rather than being passed pre-serialized JSON.
611
+ * `addPersisterListener` has been renamed `addPersisterListener`, and
612
+ * `addPersisterListener` has been renamed `delPersisterListener`.
613
+ *
783
614
  * @param store The Store to persist.
784
- * @param getPersisted An asynchronous function which will fetch JSON from the
785
- * persistence layer (or `null` or `undefined` if not present).
786
- * @param setPersisted An asynchronous function which will send JSON to the
615
+ * @param getPersisted An asynchronous function which will fetch content from
616
+ * the persistence layer (or `null` or `undefined` if not present).
617
+ * @param setPersisted An asynchronous function which will send content to the
787
618
  * persistence layer.
788
- * @param startListeningToPersisted A function that will register a `didChange`
619
+ * @param addPersisterListener A function that will register a `listener`
789
620
  * listener on underlying changes to the persistence layer. You can return a
790
- * listening handle that will be provided again when `stopListeningToPersisted`
621
+ * listening handle that will be provided again when `delPersisterListener`
791
622
  * is called.
792
- * @param stopListeningToPersisted A function that will unregister the listener
623
+ * @param delPersisterListener A function that will unregister the listener
793
624
  * from the underlying changes to the persistence layer. It receives whatever
794
- * was returned from your `startListeningToPersisted` implementation.
625
+ * was returned from your `addPersisterListener` implementation.
795
626
  * @returns A reference to the new Persister object.
796
627
  * @example
797
628
  * This example creates a custom Persister object and persists the Store to a
@@ -805,8 +636,8 @@ export function createFilePersister<Schemas extends OptionalSchemas>(
805
636
  * const persister = createCustomPersister(
806
637
  * store,
807
638
  * async () => storeJson,
808
- * async (json) => (storeJson = json),
809
- * (didChange) => setInterval(didChange, 1000),
639
+ * async (getContent) => (storeJson = JSON.stringify(getContent())),
640
+ * (listener) => setInterval(listener, 1000),
810
641
  * (interval) => clearInterval(interval),
811
642
  * );
812
643
  *
@@ -830,7 +661,11 @@ export function createCustomPersister<
830
661
  >(
831
662
  store: Store<Schemas>,
832
663
  getPersisted: () => Promise<string | null | undefined>,
833
- setPersisted: (json: string) => Promise<void>,
834
- startListeningToPersisted: (didChange: Callback) => ListeningHandle,
835
- stopListeningToPersisted: (listeningHandle: ListeningHandle) => void,
664
+ setPersisted: (
665
+ getContent: () => [Tables<Schemas[0]>, Values<Schemas[1]>],
666
+ ) => Promise<void>,
667
+ addPersisterListener: (
668
+ listener: PersisterListener<Schemas>,
669
+ ) => ListeningHandle,
670
+ delPersisterListener: (listeningHandle: ListeningHandle) => void,
836
671
  ): Persister<Schemas>;
@@ -707,6 +707,10 @@ export type DoRollback<Schemas extends OptionalSchemas> = (
707
707
  * store: Store,
708
708
  * cellsTouched: boolean,
709
709
  * valuesTouched: boolean,
710
+ * changedCells: ChangedCells,
711
+ * invalidCells: InvalidCells,
712
+ * changedValues: ChangedValues,
713
+ * invalidValues: InvalidValues,
710
714
  * ) => void;
711
715
  * ```
712
716
  *
@@ -725,17 +729,30 @@ export type DoRollback<Schemas extends OptionalSchemas> = (
725
729
  * of `cellsTouched` and `valuesTouched` in the listener will be `false` because
726
730
  * all changes have been reverted.
727
731
  *
732
+ * Since v4.0, the listener also receives the list of (valid and invalid) Cell
733
+ * and Value changes made during the transaction.
734
+ *
728
735
  * @param store A reference to the Store that is completing a transaction.
729
736
  * @param cellsTouched Whether Cell values have been touched during the
730
737
  * transaction.
731
738
  * @param valuesTouched Whether Values have been touched during the transaction,
732
739
  * since v3.0.0.
740
+ * @param changedCells Any Cells that were changed during the transaction, since
741
+ * v4.0.0.
742
+ * @param invalidCells Any invalid attempts to change Cells, since v4.0.0.
743
+ * @param changedValues Any Values that were changed during the transaction,
744
+ * since v4.0.0.
745
+ * @param invalidValues Any invalid attempts to change Values, since v4.0.0.
733
746
  * @category Listener
734
747
  */
735
748
  export type TransactionListener<Schemas extends OptionalSchemas> = (
736
749
  store: Store<Schemas>,
737
750
  cellsTouched: boolean,
738
751
  valuesTouched: boolean,
752
+ changedCells: ChangedCells<Schemas[0]>,
753
+ invalidCells: InvalidCells,
754
+ changedValues: ChangedValues<Schemas[1]>,
755
+ invalidValues: InvalidValues,
739
756
  ) => void;
740
757
 
741
758
  /**
@@ -1811,8 +1828,47 @@ export type StoreListenerStats = {
1811
1828
  */
1812
1829
  export interface Store<in out Schemas extends OptionalSchemas> {
1813
1830
  /**
1814
- * The getTables method returns a Tables object containing the entire data of
1815
- * the Store.
1831
+ * The getContent method returns a Tables object and a Values object in an
1832
+ * array, representing the entire content of the Store.
1833
+ *
1834
+ * This has schema-based typing. The following is a simplified representation:
1835
+ *
1836
+ * ```ts override
1837
+ * getContent(): [Tables, Values];
1838
+ * ```
1839
+ *
1840
+ * Note that this returns a copy of, rather than a reference to the underlying
1841
+ * data, so changes made to the returned objects are not made to the Store
1842
+ * itself.
1843
+ *
1844
+ * @returns An array of a Tables object and a Values object.
1845
+ * @example
1846
+ * This example retrieves the content of a Store.
1847
+ *
1848
+ * ```js
1849
+ * const store = createStore()
1850
+ * .setTables({pets: {fido: {species: 'dog'}}})
1851
+ * .setValues({open: true, employees: 3});
1852
+ * console.log(store.getContent());
1853
+ * // -> [{pets: {fido: {species: 'dog'}}}, {open: true, employees: 3}]
1854
+ * ```
1855
+ * @example
1856
+ * This example retrieves the Tables and Values of an empty Store, returning
1857
+ * empty objects.
1858
+ *
1859
+ * ```js
1860
+ * const store = createStore();
1861
+ * console.log(store.getContent());
1862
+ * // -> [{}, {}]
1863
+ * ```
1864
+ * @category Getter
1865
+ * @since v4.0.0
1866
+ */
1867
+ getContent(): [Tables<Schemas[0]>, Values<Schemas[1]>];
1868
+
1869
+ /**
1870
+ * The getTables method returns a Tables object containing the entire tabular
1871
+ * data of the Store.
1816
1872
  *
1817
1873
  * This has schema-based typing. The following is a simplified representation:
1818
1874
  *
@@ -1824,9 +1880,9 @@ export interface Store<in out Schemas extends OptionalSchemas> {
1824
1880
  * data, so changes made to the returned object are not made to the Store
1825
1881
  * itself.
1826
1882
  *
1827
- * @returns A Tables object containing the entire data of the Store.
1883
+ * @returns A Tables object containing the tabular data of the Store.
1828
1884
  * @example
1829
- * This example retrieves the data in a Store.
1885
+ * This example retrieves the tabular data in a Store.
1830
1886
  *
1831
1887
  * ```js
1832
1888
  * const store = createStore().setTables({
@@ -2234,9 +2290,9 @@ export interface Store<in out Schemas extends OptionalSchemas> {
2234
2290
  * data, so changes made to the returned object are not made to the Store
2235
2291
  * itself.
2236
2292
  *
2237
- * @returns An object containing the entire data of the Values.
2293
+ * @returns An object containing the set of keyed Values in the Store.
2238
2294
  * @example
2239
- * This example retrieves the keyed Values data in a Store.
2295
+ * This example retrieves the set of keyed Values in the Store.
2240
2296
  *
2241
2297
  * ```js
2242
2298
  * const store = createStore().setValues({open: true, employees: 3});
@@ -2244,7 +2300,7 @@ export interface Store<in out Schemas extends OptionalSchemas> {
2244
2300
  * // -> {open: true, employees: 3}
2245
2301
  * ```
2246
2302
  * @example
2247
- * This example retrieves a Values from a Store that has none, returning an
2303
+ * This example retrieves Values from a Store that has none, returning an
2248
2304
  * empty object.
2249
2305
  *
2250
2306
  * ```js
@@ -2671,7 +2727,76 @@ export interface Store<in out Schemas extends OptionalSchemas> {
2671
2727
  getSchemaJson(): Json;
2672
2728
 
2673
2729
  /**
2674
- * The setTables method takes an object and sets the entire data of the Store.
2730
+ * The setContent method takes an object and sets the entire data of the
2731
+ * Store.
2732
+ *
2733
+ * This has schema-based typing. The following is a simplified representation:
2734
+ *
2735
+ * ```ts override
2736
+ * setContent([tables, values]: [Tables, Values]): Store;
2737
+ * ```
2738
+ *
2739
+ * This method will cause listeners to be called for any Table, Row, Cell,
2740
+ * Value, or Id changes resulting from it.
2741
+ *
2742
+ * Any part of the provided objects that are invalid (either according to the
2743
+ * Tables or Values type, or because it does not match a TablesSchema or
2744
+ * ValuesSchema associated with the Store), will be ignored silently.
2745
+ *
2746
+ * Assuming that at least some of the provided Tables object or Values object
2747
+ * is valid, any data that was already present in that part of the Store will
2748
+ * be completely overwritten. If either object is completely invalid, no
2749
+ * change will be made to the corresponding part of the Store.
2750
+ *
2751
+ * The method returns a reference to the Store so that subsequent operations
2752
+ * can be chained in a fluent style.
2753
+ *
2754
+ * @param content An array containing the tabular and keyed-value data of the
2755
+ * Store to be set.
2756
+ * @example
2757
+ * This example sets the data of a Store.
2758
+ *
2759
+ * ```js
2760
+ * const store = createStore().setContent([
2761
+ * {pets: {fido: {species: 'dog'}}},
2762
+ * {open: true, employees: 3},
2763
+ * ]);
2764
+ * console.log(store.getTables());
2765
+ * // -> {pets: {fido: {species: 'dog'}}}
2766
+ * console.log(store.getValues());
2767
+ * // -> {open: true, employees: 3}
2768
+ * ```
2769
+ * @example
2770
+ * This example attempts to set the data of an existing Store with partly
2771
+ * invalid, and then completely invalid objects.
2772
+ *
2773
+ * ```js
2774
+ * const store = createStore().setContent([
2775
+ * {pets: {fido: {species: 'dog'}}},
2776
+ * {open: true, employees: 3},
2777
+ * ]);
2778
+ *
2779
+ * store.setContent([{pets: {felix: {species: 'cat', bug: []}}}, '']);
2780
+ * console.log(store.getTables());
2781
+ * // -> {pets: {felix: {species: 'cat'}}}
2782
+ * console.log(store.getValues());
2783
+ * // -> {open: true, employees: 3}
2784
+ *
2785
+ * store.setContent([{meaning: 42}]);
2786
+ * console.log(store.getTables());
2787
+ * // -> {pets: {felix: {species: 'cat'}}}
2788
+ * ```
2789
+ * @category Setter
2790
+ * @since 4.0.0
2791
+ */
2792
+ setContent([tables, values]: [
2793
+ Tables<Schemas[0], true>,
2794
+ Values<Schemas[1], true>,
2795
+ ]): Store<Schemas>;
2796
+
2797
+ /**
2798
+ * The setTables method takes an object and sets the entire tabular data of
2799
+ * the Store.
2675
2800
  *
2676
2801
  * This has schema-based typing. The following is a simplified representation:
2677
2802
  *
@@ -2695,7 +2820,7 @@ export interface Store<in out Schemas extends OptionalSchemas> {
2695
2820
  *
2696
2821
  * @param tables The data of the Store to be set.
2697
2822
  * @example
2698
- * This example sets the data of a Store.
2823
+ * This example sets the tabular data of a Store.
2699
2824
  *
2700
2825
  * ```js
2701
2826
  * const store = createStore().setTables({
@@ -2706,8 +2831,8 @@ export interface Store<in out Schemas extends OptionalSchemas> {
2706
2831
  * // -> {pets: {fido: {species: 'dog'}}, species: {dog: {price: 5}}}
2707
2832
  * ```
2708
2833
  * @example
2709
- * This example attempts to set the data of an existing Store with partly
2710
- * invalid, and then completely invalid, Tables objects.
2834
+ * This example attempts to set the tabular data of an existing Store with
2835
+ * partly invalid, and then completely invalid, Tables objects.
2711
2836
  *
2712
2837
  * ```js
2713
2838
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -0,0 +1 @@
1
+ var e,t;e=this,t=function(e){"use strict";const t=e=>null==e,s=Object.freeze,a="storage",o=globalThis.window,n=(e,n,r)=>((e,i,d,c,u)=>{let l,f,v=0,y=!1;const p={load:async(s,a)=>{if(2!=v){v=1;const o=await(async()=>r.getItem(n))();t(o)||""==o?e.setContent([s,a]):e.setJson(o),v=0}return p},startAutoLoad:async(s,i)=>(p.stopAutoLoad(),await p.load(s,i),y=!0,f=(e=>{const t=t=>{if(t.storageArea===r&&t.key===n){let s;try{s=JSON.parse(t.newValue)}catch{}e(s)}};return o.addEventListener(a,t),t})((async s=>{t(s)?await p.load():2!=v&&(v=1,e.setContent(s),v=0)})),p),stopAutoLoad:()=>{return y&&(e=f,o.removeEventListener(a,e),f=void 0,y=!1),p;var e},save:async()=>(1!=v&&(v=2,await(async e=>{return r.setItem(n,(t=e(),JSON.stringify(t,((e,t)=>{return t instanceof Map?(s=(e,[t,s])=>(e[t]=s,e),a={},[...t].reduce(s,a)):t;var s,a}))));var t})(e.getContent),v=0),p),startAutoSave:async()=>(await p.stopAutoSave().save(),l=e.addDidFinishTransactionListener(p.save),p),stopAutoSave:()=>{var s,a;return s=l,a=e.delListener,t(s)||a(s),p},getStore:()=>e,destroy:()=>p.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return s(p)})(e);e.createLocalPersister=(e,t)=>n(e,t,localStorage),e.createSessionPersister=(e,t)=>n(e,t,sessionStorage)},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterBrowser={});
Binary file
@@ -0,0 +1 @@
1
+ var t,e;t=this,e=function(t,e,s){"use strict";const a="utf8",o=t=>null==t,r=Object.freeze;t.createFilePersister=(t,n)=>((t,i,c,u,d)=>{let f,l,p=0,y=!1;const v={load:async(s,r)=>{if(2!=p){p=1;const i=await(async()=>{try{return await e.readFile(n,a)}catch{}})();o(i)||""==i?t.setContent([s,r]):t.setJson(i),p=0}return v},startAutoLoad:async(e,a)=>{return v.stopAutoLoad(),await v.load(e,a),y=!0,r=async e=>{o(e)?await v.load():2!=p&&(p=1,t.setContent(e),p=0)},l=s.watch(n,(()=>r())),v;var r},stopAutoLoad:()=>(y&&(l?.close(),l=void 0,y=!1),v),save:async()=>(1!=p&&(p=2,await(async t=>{try{await e.writeFile(n,(s=t(),JSON.stringify(s,((t,e)=>{return e instanceof Map?(s=(t,[e,s])=>(t[e]=s,t),a={},[...e].reduce(s,a)):e;var s,a}))),a)}catch{}var s})(t.getContent),p=0),v),startAutoSave:async()=>(await v.stopAutoSave().save(),f=t.addDidFinishTransactionListener(v.save),v),stopAutoSave:()=>{var e,s;return e=f,s=t.delListener,o(e)||s(e),v},getStore:()=>t,destroy:()=>v.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return r(v)})(t)},"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("fs/promises"),require("fs")):"function"==typeof define&&define.amd?define(["exports","fs/promises","fs"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TinyBasePersisterFile={},t["fs/promises"],t.fs);
Binary file
@@ -0,0 +1 @@
1
+ var t,e;t=this,e=function(t){"use strict";const e=t=>null==t,a=Object.freeze,o=t=>t.headers.get("ETag");t.createRemotePersister=(t,n,s,r)=>{let i;return((t,d,c,u,f)=>{let l,p,y=0,v=!1;const h={load:async(a,s)=>{if(2!=y){y=1;const r=await(async()=>{const t=await fetch(n);return i=o(t),t.text()})();e(r)||""==r?t.setContent([a,s]):t.setJson(r),y=0}return h},startAutoLoad:async(a,s)=>{return h.stopAutoLoad(),await h.load(a,s),v=!0,d=async a=>{e(a)?await h.load():2!=y&&(y=1,t.setContent(a),y=0)},p=setInterval((async()=>{const t=await fetch(n,{method:"HEAD"}),a=o(t);e(i)||e(a)||a==i||(i=a,d())}),1e3*r),h;var d},stopAutoLoad:()=>(v&&(clearInterval(p),p=void 0,v=!1),h),save:async()=>(1!=y&&(y=2,await(async t=>{return await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:(e=t(),JSON.stringify(e,((t,e)=>{return e instanceof Map?(a=(t,[e,a])=>(t[e]=a,t),o={},[...e].reduce(a,o)):e;var a,o})))});var e})(t.getContent),y=0),h),startAutoSave:async()=>(await h.stopAutoSave().save(),l=t.addDidFinishTransactionListener(h.save),h),stopAutoSave:()=>{var a,o;return a=l,o=t.delListener,e(a)||o(a),h},getStore:()=>t,destroy:()=>h.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return a(h)})(t)}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TinyBasePersisterRemote={});
Binary file
@@ -1 +1 @@
1
- var e,t;e=this,t=function(e){"use strict";const t=e=>null==e,s=(e,s,o)=>t(e)?o?.():s(e),o=Object.freeze;e.createYjsPersister=(e,a)=>{const n=a.getMap("tinybase/store");return((e,a,r,i,d)=>{let u,c,l,f=0,p=!1;const v={load:async(s,o)=>{if(2!=f){f=1;const a=await(async()=>n.get("json"))();t(a)||""==a?e.transaction((()=>e.setTables(s).setValues(o))):e.setJson(a),f=0}return v},startAutoLoad:async(e,t)=>(v.stopAutoLoad(),await v.load(e,t),p=!0,l=(e=>{const t=()=>e();return n.observe(t),t})(v.load),v),stopAutoLoad:()=>{return p&&(e=l,n.unobserve(e),l=void 0,p=!1),v;var e},save:async()=>(1!=f&&(f=2,await(async e=>{n.set("json",e)})(e.getJson()),f=0),v),startAutoSave:async()=>(await v.stopAutoSave().save(),u=e.addTablesListener(v.save),c=e.addValuesListener(v.save),v),stopAutoSave:()=>(s(u,e.delListener),s(c,e.delListener),v),getStore:()=>e,destroy:()=>v.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return o(v)})(e)}},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterYjs={});
1
+ var t,e;t=this,e=function(t){"use strict";const e=t=>null==t,s=Object.freeze;t.createYjsPersister=(t,o)=>{const n=o.getMap("tinybase/store");return((t,o,a,r,i)=>{let d,u,c=0,f=!1;const y={load:async(s,o)=>{if(2!=c){c=1;const a=await(async()=>n.get("json"))();e(a)||""==a?t.setContent([s,o]):t.setJson(a),c=0}return y},startAutoLoad:async(s,o)=>(y.stopAutoLoad(),await y.load(s,o),f=!0,u=(t=>{const e=()=>t();return n.observe(e),e})((async s=>{e(s)?await y.load():2!=c&&(c=1,t.setContent(s),c=0)})),y),stopAutoLoad:()=>{return f&&(t=u,n.unobserve(t),u=void 0,f=!1),y;var t},save:async()=>(1!=c&&(c=2,await(async t=>{n.set("json",JSON.stringify(t()))})(t.getContent),c=0),y),startAutoSave:async()=>(await y.stopAutoSave().save(),d=t.addDidFinishTransactionListener(y.save),y),stopAutoSave:()=>{var s,o;return s=d,o=t.delListener,e(s)||o(s),y},getStore:()=>t,destroy:()=>y.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return s(y)})(t)}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TinyBasePersisterYjs={});
Binary file
@@ -1 +1 @@
1
- var e,t;e=this,t=function(e,t){"use strict";const s="utf8",a=e=>null==e,o=(e,t,s)=>a(e)?s?.():t(e),r=Object.freeze,n=(e,t,s,n,i)=>{let c,d,l,u=0,y=!1;const f={load:async(s,o)=>{if(2!=u){u=1;const r=await t();a(r)||""==r?e.transaction((()=>e.setTables(s).setValues(o))):e.setJson(r),u=0}return f},startAutoLoad:async(e,t)=>(f.stopAutoLoad(),await f.load(e,t),y=!0,l=n(f.load),f),stopAutoLoad:()=>(y&&(i(l),l=void 0,y=!1),f),save:async()=>(1!=u&&(u=2,await s(e.getJson()),u=0),f),startAutoSave:async()=>(await f.stopAutoSave().save(),c=e.addTablesListener(f.save),d=e.addValuesListener(f.save),f),stopAutoSave:()=>(o(c,e.delListener),o(d,e.delListener),f),getStore:()=>e,destroy:()=>f.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return r(f)},i="storage",c=globalThis.window,d=(e,t,s)=>n(e,(async()=>s.getItem(t)),(async e=>s.setItem(t,e)),(e=>{const a=a=>{a.storageArea===s&&a.key===t&&e()};return c.addEventListener(i,a),a}),(e=>c.removeEventListener(i,e))),l=e=>e.headers.get("ETag");e.createCustomPersister=n,e.createFilePersister=(e,a)=>n(e,(async()=>{try{return await t.promises.readFile(a,s)}catch{}}),(async e=>{try{await t.promises.writeFile(a,e,s)}catch{}}),(e=>t.watch(a,e)),(e=>e?.close())),e.createLocalPersister=(e,t)=>d(e,t,localStorage),e.createRemotePersister=(e,t,s,o)=>{let r;return n(e,(async()=>{const e=await fetch(t);return r=l(e),e.text()}),(async e=>await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:e})),(e=>setInterval((async()=>{const s=await fetch(t,{method:"HEAD"}),o=l(s);a(r)||a(o)||o==r||(r=o,e())}),1e3*o)),(e=>clearInterval(e)))},e.createSessionPersister=(e,t)=>d(e,t,sessionStorage)},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("fs")):"function"==typeof define&&define.amd?define(["exports","fs"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisters={},e.fs);
1
+ var t,e;t=this,e=function(t){"use strict";const e=t=>null==t,o=Object.freeze;t.createCustomPersister=(t,s,a,n,i)=>{let r,d,u=0,c=!1;const f={load:async(o,a)=>{if(2!=u){u=1;const n=await s();e(n)||""==n?t.setContent([o,a]):t.setJson(n),u=0}return f},startAutoLoad:async(o,s)=>(f.stopAutoLoad(),await f.load(o,s),c=!0,d=n((async o=>{e(o)?await f.load():2!=u&&(u=1,t.setContent(o),u=0)})),f),stopAutoLoad:()=>(c&&(i(d),d=void 0,c=!1),f),save:async()=>(1!=u&&(u=2,await a(t.getContent),u=0),f),startAutoSave:async()=>(await f.stopAutoSave().save(),r=t.addDidFinishTransactionListener(f.save),f),stopAutoSave:()=>{var o,s;return o=r,s=t.delListener,e(o)||s(o),f},getStore:()=>t,destroy:()=>f.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return o(f)}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TinyBasePersisters={});