tinybase 0.9.0 → 0.9.4

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 (69) hide show
  1. package/lib/checkpoints.d.ts +35 -20
  2. package/lib/checkpoints.js +1 -1
  3. package/lib/checkpoints.js.gz +0 -0
  4. package/lib/common.d.ts +56 -0
  5. package/lib/common.js +1 -0
  6. package/lib/common.js.gz +0 -0
  7. package/lib/debug/checkpoints.d.ts +35 -20
  8. package/lib/debug/checkpoints.js +1 -1
  9. package/lib/debug/common.d.ts +56 -0
  10. package/lib/debug/common.js +3 -0
  11. package/lib/debug/indexes.d.ts +35 -76
  12. package/lib/debug/indexes.js +18 -10
  13. package/lib/debug/metrics.d.ts +45 -20
  14. package/lib/debug/metrics.js +1 -1
  15. package/lib/debug/persisters.d.ts +203 -17
  16. package/lib/debug/persisters.js +1 -1
  17. package/lib/debug/relationships.d.ts +46 -23
  18. package/lib/debug/relationships.js +1 -1
  19. package/lib/debug/store.d.ts +179 -102
  20. package/lib/debug/store.js +1 -1
  21. package/lib/debug/tinybase.d.ts +1 -2
  22. package/lib/debug/tinybase.js +18 -1029
  23. package/lib/debug/{react.d.ts → ui-react.d.ts} +262 -162
  24. package/lib/debug/{react.js → ui-react.js} +24 -15
  25. package/lib/indexes.d.ts +35 -76
  26. package/lib/indexes.js +1 -1
  27. package/lib/indexes.js.gz +0 -0
  28. package/lib/metrics.d.ts +45 -20
  29. package/lib/metrics.js +1 -1
  30. package/lib/metrics.js.gz +0 -0
  31. package/lib/persisters.d.ts +203 -17
  32. package/lib/persisters.js +1 -1
  33. package/lib/persisters.js.gz +0 -0
  34. package/lib/relationships.d.ts +46 -23
  35. package/lib/relationships.js +1 -1
  36. package/lib/relationships.js.gz +0 -0
  37. package/lib/store.d.ts +179 -102
  38. package/lib/store.js +1 -1
  39. package/lib/store.js.gz +0 -0
  40. package/lib/tinybase.d.ts +1 -2
  41. package/lib/tinybase.js +1 -1
  42. package/lib/tinybase.js.gz +0 -0
  43. package/lib/{react.d.ts → ui-react.d.ts} +262 -162
  44. package/lib/ui-react.js +1 -0
  45. package/lib/ui-react.js.gz +0 -0
  46. package/lib/umd/checkpoints.js +1 -1
  47. package/lib/umd/checkpoints.js.gz +0 -0
  48. package/lib/umd/common.js +1 -0
  49. package/lib/umd/common.js.gz +0 -0
  50. package/lib/umd/indexes.js +1 -1
  51. package/lib/umd/indexes.js.gz +0 -0
  52. package/lib/umd/metrics.js +1 -1
  53. package/lib/umd/metrics.js.gz +0 -0
  54. package/lib/umd/persisters.js +1 -1
  55. package/lib/umd/persisters.js.gz +0 -0
  56. package/lib/umd/relationships.js +1 -1
  57. package/lib/umd/relationships.js.gz +0 -0
  58. package/lib/umd/store.js +1 -1
  59. package/lib/umd/store.js.gz +0 -0
  60. package/lib/umd/tinybase.js +1 -1
  61. package/lib/umd/tinybase.js.gz +0 -0
  62. package/lib/umd/ui-react.js +1 -0
  63. package/lib/umd/ui-react.js.gz +0 -0
  64. package/package.json +21 -16
  65. package/readme.md +13 -13
  66. package/lib/react.js +0 -1
  67. package/lib/react.js.gz +0 -0
  68. package/lib/umd/react.js +0 -1
  69. package/lib/umd/react.js.gz +0 -0
@@ -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
@@ -11,9 +11,9 @@
11
11
  * - The createLocalPersister function returns a Persister that uses the
12
12
  * browser's local storage.
13
13
  * - The createRemotePersister function returns a Persister that uses a remote
14
- * endpoint
14
+ * server.
15
15
  * - The createFilePersister function returns a Persister that uses a local file
16
- * (in an appropriate environment)
16
+ * (in an appropriate environment).
17
17
  *
18
18
  * Since persistence requirements can be different for every app, the
19
19
  * createCustomPersister function can also be used to easily create a fully
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  import {Store, Tables} from './store.d';
27
- import {Callback} from './common';
27
+ import {Callback} from './common.d';
28
28
 
29
29
  /**
30
30
  * The PersisterStats type describes the number of times a Persister object has
@@ -89,7 +89,7 @@ export type PersisterStats = {
89
89
  * a JSON string, changes the persisted data, updates the Store from it, and
90
90
  * finally destroys the Persister again.
91
91
  *
92
- * ```tsx
92
+ * ```js
93
93
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
94
94
  * const persister = createSessionPersister(store, 'pets');
95
95
  *
@@ -110,7 +110,7 @@ export type PersisterStats = {
110
110
  * browser's session storage as a JSON string. Changes to the Store data, or the
111
111
  * persisted data (implicitly firing a StorageEvent), are reflected accordingly.
112
112
  *
113
- * ```tsx
113
+ * ```js
114
114
  * const store = createStore();
115
115
  * const persister = createSessionPersister(store, 'pets');
116
116
  *
@@ -133,6 +133,7 @@ export type PersisterStats = {
133
133
  * persister.destroy();
134
134
  * sessionStorage.clear();
135
135
  * ```
136
+ * @category Persister
136
137
  */
137
138
  export interface Persister {
138
139
  /**
@@ -158,7 +159,7 @@ export interface Persister {
158
159
  * browser's session storage, which for the purposes of this example has been
159
160
  * previously populated.
160
161
  *
161
- * ```tsx
162
+ * ```js
162
163
  * sessionStorage.setItem('pets', '{"pets":{"fido":{"species":"dog"}}}');
163
164
  *
164
165
  * const store = createStore();
@@ -176,7 +177,7 @@ export interface Persister {
176
177
  * parameter is used. The second time the load method is called, data has
177
178
  * previously been persisted and instead, that is loaded.
178
179
  *
179
- * ```tsx
180
+ * ```js
180
181
  * const store = createStore();
181
182
  * const persister = createSessionPersister(store, 'pets');
182
183
  *
@@ -226,7 +227,7 @@ export interface Persister {
226
227
  * reflected in the Store (in this case through detection of StorageEvents
227
228
  * from session storage changes made in another browser tab).
228
229
  *
229
- * ```tsx
230
+ * ```js
230
231
  * const store = createStore();
231
232
  * const persister = createSessionPersister(store, 'pets');
232
233
  *
@@ -242,6 +243,7 @@ export interface Persister {
242
243
  * console.log(store.getTables());
243
244
  * // -> {pets: {toto: {species: 'dog'}}}
244
245
  *
246
+ * persister.destroy();
245
247
  * sessionStorage.clear();
246
248
  * ```
247
249
  * @category Load
@@ -261,7 +263,7 @@ export interface Persister {
261
263
  * into it from the browser's session storage. Once the automatic loading is
262
264
  * stopped, subsequent changes are not reflected in the Store.
263
265
  *
264
- * ```tsx
266
+ * ```js
265
267
  * const store = createStore();
266
268
  * const persister = createSessionPersister(store, 'pets');
267
269
  * await persister.startAutoLoad();
@@ -283,6 +285,7 @@ export interface Persister {
283
285
  * // -> {pets: {toto: {species: 'dog'}}}
284
286
  * // Storage change has not been automatically loaded.
285
287
  *
288
+ * persister.destroy();
286
289
  * sessionStorage.clear();
287
290
  * ```
288
291
  * @category Load
@@ -303,7 +306,7 @@ export interface Persister {
303
306
  * This example creates a Store with some data, and saves into the browser's
304
307
  * session storage.
305
308
  *
306
- * ```tsx
309
+ * ```js
307
310
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
308
311
  * const persister = createSessionPersister(store, 'pets');
309
312
  *
@@ -314,6 +317,7 @@ export interface Persister {
314
317
  * persister.destroy();
315
318
  * sessionStorage.clear();
316
319
  * ```
320
+ * @category Save
317
321
  */
318
322
  save(): Promise<Persister>;
319
323
 
@@ -336,7 +340,7 @@ export interface Persister {
336
340
  * session storage. Subsequent changes to the Store are then automatically
337
341
  * saved to the underlying storage.
338
342
  *
339
- * ```tsx
343
+ * ```js
340
344
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
341
345
  * const persister = createSessionPersister(store, 'pets');
342
346
  *
@@ -351,6 +355,7 @@ export interface Persister {
351
355
  *
352
356
  * sessionStorage.clear();
353
357
  * ```
358
+ * @category Save
354
359
  */
355
360
  startAutoSave(): Promise<Persister>;
356
361
 
@@ -368,7 +373,7 @@ export interface Persister {
368
373
  * saved to the underlying storage. Once the automatic saving is
369
374
  * stopped, subsequent changes are not reflected.
370
375
  *
371
- * ```tsx
376
+ * ```js
372
377
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
373
378
  * const persister = createSessionPersister(store, 'pets');
374
379
  * await persister.startAutoSave();
@@ -401,7 +406,7 @@ export interface Persister {
401
406
  * This example creates a Persister object against a newly-created Store and
402
407
  * then gets its reference in order to update its data.
403
408
  *
404
- * ```tsx
409
+ * ```js
405
410
  * const persister = createSessionPersister(createStore(), 'pets');
406
411
  * await persister.startAutoSave();
407
412
  *
@@ -430,7 +435,7 @@ export interface Persister {
430
435
  * registers a TablesListener with the underlying Store), and then destroys it
431
436
  * again, removing the listener.
432
437
  *
433
- * ```tsx
438
+ * ```js
434
439
  * const store = createStore();
435
440
  * const persister = createSessionPersister(store, 'pets');
436
441
  * await persister.startAutoSave();
@@ -468,7 +473,7 @@ export interface Persister {
468
473
  * starts - so those numbers are included in addition to the loads and saves
469
474
  * invoked by changes to the Store and to the underlying storage.
470
475
  *
471
- * ```tsx
476
+ * ```js
472
477
  * const store = createStore();
473
478
  * const persister = createSessionPersister(store, 'pets');
474
479
  *
@@ -493,16 +498,114 @@ export interface Persister {
493
498
  getStats(): PersisterStats;
494
499
  }
495
500
 
501
+ /**
502
+ * The createSessionPersister function creates an Persister object that can
503
+ * persist the Store to the browser's session storage.
504
+ *
505
+ * As well as providing a reference to the Store to persist, you must provide a
506
+ * `storageName` parameter which is unique to your application. This is the key
507
+ * that the browser uses to identify the storage location.
508
+ *
509
+ * @param store The Store to persist.
510
+ * @param storageName The unique key to identify the storage location.
511
+ * @returns A reference to the new Persister object.
512
+ * @example
513
+ * This example creates a Persister object and persists the Store to the
514
+ * browser's session storage.
515
+ *
516
+ * ```js
517
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
518
+ * const persister = createSessionPersister(store, 'pets');
519
+ *
520
+ * await persister.save();
521
+ * console.log(sessionStorage.getItem('pets'));
522
+ * // -> '{"pets":{"fido":{"species":"dog"}}}'
523
+ *
524
+ * persister.destroy();
525
+ * sessionStorage.clear();
526
+ * ```
527
+ * @category Creation
528
+ */
496
529
  export function createSessionPersister(
497
530
  store: Store,
498
531
  storageName: string,
499
532
  ): Persister;
500
533
 
534
+ /**
535
+ * The createLocalPersister function creates an Persister object that can
536
+ * persist the Store to the browser's local storage.
537
+ *
538
+ * As well as providing a reference to the Store to persist, you must provide a
539
+ * `storageName` parameter which is unique to your application. This is the key
540
+ * that the browser uses to identify the storage location.
541
+ *
542
+ * @param store The Store to persist.
543
+ * @param storageName The unique key to identify the storage location.
544
+ * @returns A reference to the new Persister object.
545
+ * @example
546
+ * This example creates a Persister object and persists the Store to the
547
+ * browser's local storage.
548
+ *
549
+ * ```js
550
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
551
+ * const persister = createLocalPersister(store, 'pets');
552
+ *
553
+ * await persister.save();
554
+ * console.log(localStorage.getItem('pets'));
555
+ * // -> '{"pets":{"fido":{"species":"dog"}}}'
556
+ *
557
+ * persister.destroy();
558
+ * localStorage.clear();
559
+ * ```
560
+ * @category Creation
561
+ */
501
562
  export function createLocalPersister(
502
563
  store: Store,
503
564
  storageName: string,
504
565
  ): Persister;
505
566
 
567
+ /**
568
+ * The createRemotePersister function creates an Persister object that can
569
+ * persist the Store to a remote server.
570
+ *
571
+ * As well as providing a reference to the Store to persist, you must provide
572
+ * `loadUrl` and `saveUrl` parameters. These identify the endpoints of the
573
+ * server that support the `GET` method (to fetch the Store JSON to load) and
574
+ * the `POST` method (to send the Store JSON to save) respectively.
575
+ *
576
+ * For when you choose to enable automatic loading for the Persister (with the
577
+ * startAutoLoad method), it will poll the loadUrl for changes. The
578
+ * `autoLoadIntervalSeconds` method is used to indicate how often to do this.
579
+ *
580
+ * @param store The Store to persist.
581
+ * @param loadUrl The endpoint that supports a `GET` method to load JSON.
582
+ * @param saveUrl The endpoint that supports a `POST` method to save JSON.
583
+ * @param autoLoadIntervalSeconds How often to poll the `loadUrl` when
584
+ * automatically loading changes from the server.
585
+ * @returns A reference to the new Persister object.
586
+ * @example
587
+ * This example creates a Persister object and persists the Store to a remote
588
+ * server.
589
+ *
590
+ * ```js yolo
591
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
592
+ * const persister = createRemotePersister(
593
+ * store,
594
+ * 'https://example.com/load',
595
+ * 'https://example.com/save',
596
+ * 5,
597
+ * );
598
+ *
599
+ * await persister.save();
600
+ * // Store JSON will be sent to server in a POST request.
601
+ *
602
+ * await persister.load();
603
+ * // Store JSON will be fetched from server with a GET request.
604
+ *
605
+ * persister.destroy();
606
+ * ```
607
+ * @category Creation
608
+ */
506
609
  export function createRemotePersister(
507
610
  store: Store,
508
611
  loadUrl: string,
@@ -510,8 +613,91 @@ export function createRemotePersister(
510
613
  autoLoadIntervalSeconds: number,
511
614
  ): Persister;
512
615
 
616
+ /**
617
+ * The createFilePersister function creates an Persister object that can persist
618
+ * the Store to a local file (in an appropriate environment).
619
+ *
620
+ * As well as providing a reference to the Store to persist, you must provide
621
+ * `filePath` parameter which identifies the file to persist it to.
622
+ *
623
+ * @param store The Store to persist.
624
+ * @param filePath The location of the local file to persist the Store to.
625
+ * @returns A reference to the new Persister object.
626
+ * @example
627
+ * This example creates a Persister object and persists the Store to a local
628
+ * file.
629
+ *
630
+ * ```js yolo
631
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
632
+ * const persister = createFilePersister(store, '/app/persisted.json');
633
+ *
634
+ * await persister.save();
635
+ * // Store JSON will be saved to the file.
636
+ *
637
+ * await persister.load();
638
+ * // Store JSON will be loaded from the file.
639
+ *
640
+ * persister.destroy();
641
+ * ```
642
+ * @category Creation
643
+ */
513
644
  export function createFilePersister(store: Store, filePath: string): Persister;
514
645
 
646
+ /**
647
+ * The createCustomPersister function creates an Persister object that you can
648
+ * configure to persist the Store in any way you wish.
649
+ *
650
+ * As well as providing a reference to the Store to persist, you must provide
651
+ * functions that handle how to fetch, write, and listen to, the persistence
652
+ * layer.
653
+ *
654
+ * The other creation functions (such as the createSessionPersister function and
655
+ * createFilePersister function, for example) all use this function under the
656
+ * covers. See those implementations for ideas on how to implement your own
657
+ * Persister types.
658
+ *
659
+ * @param store The Store to persist.
660
+ * @param getPersisted An asynchronous function which will fetch JSON from the
661
+ * persistence layer (or `null` or `undefined` if not present).
662
+ * @param setPersisted An asynchronous function which will send JSON to the
663
+ * persistence layer.
664
+ * @param startListeningToPersisted A function that will register a `didChange`
665
+ * listener on underlying changes to the persistence layer.
666
+ * @param stopListeningToPersisted A function that will unregister the listener
667
+ * from the underlying changes to the persistence layer.
668
+ * @returns A reference to the new Persister object.
669
+ * @example
670
+ * This example creates a custom Persister object and persists the Store to a
671
+ * local string called `storeJson` and which would automatically load by polling
672
+ * for changes every second.
673
+ *
674
+ * ```js
675
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
676
+ * let storeJson;
677
+ * let interval;
678
+ *
679
+ * const persister = createCustomPersister(
680
+ * store,
681
+ * async () => storeJson,
682
+ * async (json) => (storeJson = json),
683
+ * (didChange) => (interval = setInterval(didChange, 1000)),
684
+ * () => clearInterval(interval),
685
+ * );
686
+ *
687
+ * await persister.save();
688
+ * console.log(storeJson);
689
+ * // -> '{"pets":{"fido":{"species":"dog"}}}'
690
+ *
691
+ * storeJson = '{"pets":{"fido":{"species":"dog","color":"brown"}}}';
692
+ * await persister.load();
693
+ *
694
+ * console.log(store.getTables());
695
+ * // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
696
+ *
697
+ * persister.destroy();
698
+ * ```
699
+ * @category Creation
700
+ */
515
701
  export function createCustomPersister(
516
702
  store: Store,
517
703
  getPersisted: () => Promise<string | null | undefined>,
@@ -77,7 +77,7 @@ const createCustomPersister = (
77
77
  };
78
78
 
79
79
  const STORAGE = 'storage';
80
- const WINDOW = window;
80
+ const WINDOW = globalThis.window;
81
81
  const getStoragePersister = (store, storageName, storage) => {
82
82
  let listener;
83
83
  const getPersisted = async () => storage.getItem(storageName);
@@ -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
@@ -50,6 +50,9 @@ export type Relationship = {
50
50
  * object, the Id of the Relationship that changed, and the Id of the local Row
51
51
  * whose remote Row Id changed.
52
52
  *
53
+ * @param relationships A reference to the Relationships object that changed.
54
+ * @param relationshipId The Id of the Relationship that changed.
55
+ * @param localRowId The Id of the local Row whose remote Row Id changed.
53
56
  * @category Listener
54
57
  */
55
58
  export type RemoteRowIdListener = (
@@ -67,8 +70,11 @@ export type RemoteRowIdListener = (
67
70
  *
68
71
  * When called, a LocalRowIdsListener is given a reference to the Relationships
69
72
  * object, the Id of the Relationship that changed, and the Id of the remote Row
70
- * whose local Row Id changed.
73
+ * whose local Row Ids changed.
71
74
  *
75
+ * @param relationships A reference to the Relationships object that changed.
76
+ * @param relationshipId The Id of the Relationship that changed.
77
+ * @param remoteRowId The Id of the remote Row whose local Row Ids changed.
72
78
  * @category Listener
73
79
  */
74
80
  export type LocalRowIdsListener = (
@@ -88,6 +94,10 @@ export type LocalRowIdsListener = (
88
94
  * object, the Id of the Relationship that changed, and the Id of the first Row
89
95
  * of the the linked list whose members changed.
90
96
  *
97
+ * @param relationships A reference to the Relationships object that changed.
98
+ * @param relationshipId The Id of the Relationship that changed.
99
+ * @param firstRowId The Id of the first Row of the the linked list whose
100
+ * members changed.
91
101
  * @category Listener
92
102
  */
93
103
  export type LinkedRowIdsListener = (
@@ -107,8 +117,19 @@ export type LinkedRowIdsListener = (
107
117
  * @category Development
108
118
  */
109
119
  export type RelationshipsListenerStats = {
120
+ /**
121
+ * The number of RemoteRowIdListeners registered with the Relationships
122
+ * object.
123
+ */
110
124
  remoteRowId?: number;
125
+ /**
126
+ * The number of LocalRowIdsListeners registered with the Relationships
127
+ * object.
128
+ */
111
129
  localRowIds?: number;
130
+ /**
131
+ * The number of LinkedRowIds registered with the Relationships object.
132
+ */
112
133
  linkedRowIds?: number;
113
134
  };
114
135
 
@@ -137,7 +158,7 @@ export type RelationshipsListenerStats = {
137
158
  * creation, to adding definitions (both local/remote table and linked list),
138
159
  * getting their contents, and then registering and removing listeners for them.
139
160
  *
140
- * ```tsx
161
+ * ```js
141
162
  * const store = createStore()
142
163
  * .setTable('pets', {
143
164
  * fido: {species: 'dog', next: 'felix'},
@@ -201,6 +222,7 @@ export type RelationshipsListenerStats = {
201
222
  * relationships.delListener(listenerId2);
202
223
  * relationships.destroy();
203
224
  * ```
225
+ * @category Relationships
204
226
  */
205
227
  export interface Relationships {
206
228
  /**
@@ -239,7 +261,7 @@ export interface Relationships {
239
261
  * a simple Relationship based on the values in the `species` Cell of the
240
262
  * `pets` Table that relates a Row to another in the `species` Table.
241
263
  *
242
- * ```tsx
264
+ * ```js
243
265
  * const store = createStore()
244
266
  * .setTable('pets', {
245
267
  * fido: {species: 'dog'},
@@ -269,7 +291,7 @@ export interface Relationships {
269
291
  * a linked list Relationship based on the values in the `next` Cell of the
270
292
  * `pets` Table that relates a Row to another in the same Table.
271
293
  *
272
- * ```tsx
294
+ * ```js
273
295
  * const store = createStore().setTable('pets', {
274
296
  * fido: {species: 'dog', next: 'felix'},
275
297
  * felix: {species: 'cat', next: 'cujo'},
@@ -306,7 +328,7 @@ export interface Relationships {
306
328
  * This example creates a Store, creates a Relationships object, defines a
307
329
  * simple Relationship, and then removes it.
308
330
  *
309
- * ```tsx
331
+ * ```js
310
332
  * const store = createStore()
311
333
  * .setTable('pets', {
312
334
  * fido: {species: 'dog'},
@@ -345,7 +367,7 @@ export interface Relationships {
345
367
  * This example creates a Relationships object against a newly-created Store
346
368
  * and then gets its reference in order to update its data.
347
369
  *
348
- * ```tsx
370
+ * ```js
349
371
  * const relationships = createRelationships(createStore());
350
372
  * relationships.setRelationshipDefinition(
351
373
  * 'petSpecies',
@@ -370,7 +392,7 @@ export interface Relationships {
370
392
  * This example creates a Relationships object with two definitions, and then
371
393
  * gets the Ids of the definitions.
372
394
  *
373
- * ```tsx
395
+ * ```js
374
396
  * const relationships = createRelationships(createStore())
375
397
  * .setRelationshipDefinition('petSpecies', 'pets', 'species', 'species')
376
398
  * .setRelationshipDefinition('petSequence', 'pets', 'pets', 'next');
@@ -395,7 +417,7 @@ export interface Relationships {
395
417
  * definition, and then queries it (and a non-existent definition) to get the
396
418
  * underlying local Table Id.
397
419
  *
398
- * ```tsx
420
+ * ```js
399
421
  * const relationships = createRelationships(createStore());
400
422
  * relationships.setRelationshipDefinition(
401
423
  * 'petSpecies',
@@ -427,7 +449,7 @@ export interface Relationships {
427
449
  * definition, and then queries it (and a non-existent definition) to get the
428
450
  * underlying remote Table Id.
429
451
  *
430
- * ```tsx
452
+ * ```js
431
453
  * const relationships = createRelationships(createStore());
432
454
  * relationships.setRelationshipDefinition(
433
455
  * 'petSpecies',
@@ -461,7 +483,7 @@ export interface Relationships {
461
483
  * in the Relationship (and also the remote Row Ids for a local Row that does
462
484
  * not exist, and for a Relationship that has not been defined).
463
485
  *
464
- * ```tsx
486
+ * ```js
465
487
  * const store = createStore()
466
488
  * .setTable('pets', {
467
489
  * fido: {species: 'dog'},
@@ -508,7 +530,7 @@ export interface Relationships {
508
530
  * in the Relationship (and also the local Row Ids for a remote Row that does
509
531
  * not exist, and for a Relationship that has not been defined).
510
532
  *
511
- * ```tsx
533
+ * ```js
512
534
  * const store = createStore()
513
535
  * .setTable('pets', {
514
536
  * fido: {species: 'dog'},
@@ -560,7 +582,7 @@ export interface Relationships {
560
582
  * linked Row Ids in the Relationship (and also the linked Row Ids for a Row
561
583
  * that does not exist, and for a Relationship that has not been defined).
562
584
  *
563
- * ```tsx
585
+ * ```js
564
586
  * const store = createStore().setTable('pets', {
565
587
  * fido: {species: 'dog', next: 'felix'},
566
588
  * felix: {species: 'cat', next: 'cujo'},
@@ -618,7 +640,7 @@ export interface Relationships {
618
640
  * This example creates a Store, a Relationships object, and then registers a
619
641
  * listener that responds to any changes to a specific local Row's remote Row.
620
642
  *
621
- * ```tsx
643
+ * ```js
622
644
  * const store = createStore()
623
645
  * .setTable('pets', {
624
646
  * fido: {species: 'dog'},
@@ -660,7 +682,7 @@ export interface Relationships {
660
682
  * also illustrates how you can use the getStore method and the getRemoteRowId
661
683
  * method to resolve the remote Row as a whole.
662
684
  *
663
- * ```tsx
685
+ * ```js
664
686
  * const store = createStore()
665
687
  * .setTable('pets', {
666
688
  * fido: {species: 'dog', color: 'brown'},
@@ -750,7 +772,7 @@ export interface Relationships {
750
772
  * listener that responds to any changes to a specific remote Row's local Row
751
773
  * objects.
752
774
  *
753
- * ```tsx
775
+ * ```js
754
776
  * const store = createStore()
755
777
  * .setTable('pets', {
756
778
  * fido: {species: 'dog'},
@@ -791,7 +813,7 @@ export interface Relationships {
791
813
  * listener that responds to any changes to any remote Row's local Row
792
814
  * objects.
793
815
  *
794
- * ```tsx
816
+ * ```js
795
817
  * const store = createStore()
796
818
  * .setTable('pets', {
797
819
  * fido: {species: 'dog', color: 'brown'},
@@ -877,7 +899,7 @@ export interface Relationships {
877
899
  * listener that responds to any changes to a specific first Row's linked Row
878
900
  * objects.
879
901
  *
880
- * ```tsx
902
+ * ```js
881
903
  * const store = createStore().setTable('pets', {
882
904
  * fido: {species: 'dog', next: 'felix'},
883
905
  * felix: {species: 'cat', next: 'cujo'},
@@ -930,7 +952,7 @@ export interface Relationships {
930
952
  * This example creates a Store, a Relationships object, registers a listener,
931
953
  * and then removes it.
932
954
  *
933
- * ```tsx
955
+ * ```js
934
956
  * const store = createStore()
935
957
  * .setTable('pets', {
936
958
  * fido: {species: 'dog'},
@@ -984,7 +1006,7 @@ export interface Relationships {
984
1006
  * definition (that registers a RowListener with the underlying Store),
985
1007
  * and then destroys it again, removing the listener.
986
1008
  *
987
- * ```tsx
1009
+ * ```js
988
1010
  * const store = createStore()
989
1011
  * .setTable('pets', {
990
1012
  * fido: {species: 'dog'},
@@ -1034,7 +1056,7 @@ export interface Relationships {
1034
1056
  * @example
1035
1057
  * This example gets the listener statistics of a Relationships object.
1036
1058
  *
1037
- * ```tsx
1059
+ * ```js
1038
1060
  * const store = createStore();
1039
1061
  * const relationships = createRelationships(store);
1040
1062
  * relationships.addRemoteRowIdListener(null, null, () => {
@@ -1070,7 +1092,7 @@ export interface Relationships {
1070
1092
  * @example
1071
1093
  * This example creates an Relationships object.
1072
1094
  *
1073
- * ```tsx
1095
+ * ```js
1074
1096
  * const store = createStore();
1075
1097
  * const relationships = createRelationships(store);
1076
1098
  * console.log(relationships.getRelationshipIds());
@@ -1080,12 +1102,13 @@ export interface Relationships {
1080
1102
  * This example creates a Relationships object, and calls the method a second
1081
1103
  * time for the same Store to return the same object.
1082
1104
  *
1083
- * ```tsx
1105
+ * ```js
1084
1106
  * const store = createStore();
1085
1107
  * const relationships1 = createRelationships(store);
1086
1108
  * const relationships2 = createRelationships(store);
1087
1109
  * console.log(relationships1 === relationships2);
1088
1110
  * // -> true
1089
1111
  * ```
1112
+ * @category Creation
1090
1113
  */
1091
1114
  export function createRelationships(store: Store): Relationships;
@@ -191,7 +191,7 @@ const getListenerFunctions = (getThing) => {
191
191
  const listenerPool = [];
192
192
  const allListeners = mapNew();
193
193
  const addListener = (listener, deepSet, idOrNulls = []) => {
194
- thing ?? (thing = getThing());
194
+ thing ??= getThing();
195
195
  const id = listenerPool.pop() ?? '' + nextId++;
196
196
  mapSet(allListeners, id, [listener, deepSet, idOrNulls]);
197
197
  addDeepSet(deepSet, id, idOrNulls);