tinybase 5.1.1 → 5.1.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.
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import type {DatabasePersisterConfig, Persister} from '../index.d.cts';
12
- import type {AbstractPowerSyncDatabase} from '@journeyapps/powersync-sdk-common';
12
+ import type {AbstractPowerSyncDatabase} from '@powersync/common';
13
13
  import type {Store} from '../../store/index.d.cts';
14
14
 
15
15
  /**
@@ -38,7 +38,7 @@ export interface PowerSyncPersister extends Persister {
38
38
  * ```js yolo
39
39
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
40
40
  * import {createStore} from 'tinybase';
41
- * import {usePowerSync} from '@journeyapps/powersync-react';
41
+ * import {usePowerSync} from '@powersync/react';
42
42
  *
43
43
  * const ps = usePowerSync();
44
44
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -98,7 +98,7 @@ export interface PowerSyncPersister extends Persister {
98
98
  * ```js yolo
99
99
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
100
100
  * import {createStore} from 'tinybase';
101
- * import {usePowerSync} from '@journeyapps/powersync-react';
101
+ * import {usePowerSync} from '@powersync/react';
102
102
  *
103
103
  * const ps = usePowerSync();
104
104
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -134,7 +134,7 @@ export interface PowerSyncPersister extends Persister {
134
134
  * ```js yolo
135
135
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
136
136
  * import {createStore} from 'tinybase';
137
- * import {usePowerSync} from '@journeyapps/powersync-react';
137
+ * import {usePowerSync} from '@powersync/react';
138
138
  *
139
139
  * const ps = usePowerSync();
140
140
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import type {DatabasePersisterConfig, Persister} from '../index.d.ts';
12
- import type {AbstractPowerSyncDatabase} from '@journeyapps/powersync-sdk-common';
12
+ import type {AbstractPowerSyncDatabase} from '@powersync/common';
13
13
  import type {Store} from '../../store/index.d.ts';
14
14
 
15
15
  /**
@@ -38,7 +38,7 @@ export interface PowerSyncPersister extends Persister {
38
38
  * ```js yolo
39
39
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
40
40
  * import {createStore} from 'tinybase';
41
- * import {usePowerSync} from '@journeyapps/powersync-react';
41
+ * import {usePowerSync} from '@powersync/react';
42
42
  *
43
43
  * const ps = usePowerSync();
44
44
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -98,7 +98,7 @@ export interface PowerSyncPersister extends Persister {
98
98
  * ```js yolo
99
99
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
100
100
  * import {createStore} from 'tinybase';
101
- * import {usePowerSync} from '@journeyapps/powersync-react';
101
+ * import {usePowerSync} from '@powersync/react';
102
102
  *
103
103
  * const ps = usePowerSync();
104
104
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -134,7 +134,7 @@ export interface PowerSyncPersister extends Persister {
134
134
  * ```js yolo
135
135
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
136
136
  * import {createStore} from 'tinybase';
137
- * import {usePowerSync} from '@journeyapps/powersync-react';
137
+ * import {usePowerSync} from '@powersync/react';
138
138
  *
139
139
  * const ps = usePowerSync();
140
140
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -16,7 +16,7 @@ import type {
16
16
  OptionalSchemas,
17
17
  Store,
18
18
  } from '../../../store/with-schemas/index.d.cts';
19
- import type {AbstractPowerSyncDatabase} from '@journeyapps/powersync-sdk-common';
19
+ import type {AbstractPowerSyncDatabase} from '@powersync/common';
20
20
 
21
21
  /**
22
22
  * The PowerSyncPersister interface represents a Persister that lets you save
@@ -45,7 +45,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
45
45
  * ```js yolo
46
46
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
47
47
  * import {createStore} from 'tinybase';
48
- * import {usePowerSync} from '@journeyapps/powersync-react';
48
+ * import {usePowerSync} from '@powersync/react';
49
49
  *
50
50
  * const ps = usePowerSync();
51
51
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -117,7 +117,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
117
117
  * ```js yolo
118
118
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
119
119
  * import {createStore} from 'tinybase';
120
- * import {usePowerSync} from '@journeyapps/powersync-react';
120
+ * import {usePowerSync} from '@powersync/react';
121
121
  *
122
122
  * const ps = usePowerSync();
123
123
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -153,7 +153,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
153
153
  * ```js yolo
154
154
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
155
155
  * import {createStore} from 'tinybase';
156
- * import {usePowerSync} from '@journeyapps/powersync-react';
156
+ * import {usePowerSync} from '@powersync/react';
157
157
  *
158
158
  * const ps = usePowerSync();
159
159
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -16,7 +16,7 @@ import type {
16
16
  OptionalSchemas,
17
17
  Store,
18
18
  } from '../../../store/with-schemas/index.d.ts';
19
- import type {AbstractPowerSyncDatabase} from '@journeyapps/powersync-sdk-common';
19
+ import type {AbstractPowerSyncDatabase} from '@powersync/common';
20
20
 
21
21
  /**
22
22
  * The PowerSyncPersister interface represents a Persister that lets you save
@@ -45,7 +45,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
45
45
  * ```js yolo
46
46
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
47
47
  * import {createStore} from 'tinybase';
48
- * import {usePowerSync} from '@journeyapps/powersync-react';
48
+ * import {usePowerSync} from '@powersync/react';
49
49
  *
50
50
  * const ps = usePowerSync();
51
51
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -117,7 +117,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
117
117
  * ```js yolo
118
118
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
119
119
  * import {createStore} from 'tinybase';
120
- * import {usePowerSync} from '@journeyapps/powersync-react';
120
+ * import {usePowerSync} from '@powersync/react';
121
121
  *
122
122
  * const ps = usePowerSync();
123
123
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -153,7 +153,7 @@ export interface PowerSyncPersister<Schemas extends OptionalSchemas>
153
153
  * ```js yolo
154
154
  * import {createPowerSyncPersister} from 'tinybase/persisters/persister-powersync';
155
155
  * import {createStore} from 'tinybase';
156
- * import {usePowerSync} from '@journeyapps/powersync-react';
156
+ * import {usePowerSync} from '@powersync/react';
157
157
  *
158
158
  * const ps = usePowerSync();
159
159
  * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
@@ -585,7 +585,10 @@ export interface WsServer {
585
585
  * const server = createWsServer(
586
586
  * new WebSocketServer({port: 8047}),
587
587
  * (pathId) =>
588
- * createFilePersister(createMergeableStore(), pathId + '.json'),
588
+ * createFilePersister(
589
+ * createMergeableStore(),
590
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
591
+ * ),
589
592
  * );
590
593
  *
591
594
  * // Client 1
@@ -653,7 +656,10 @@ export interface WsServer {
653
656
  * const server = createWsServer(
654
657
  * new WebSocketServer({port: 8047}),
655
658
  * (pathId) => [
656
- * createFilePersister(createMergeableStore(), pathId + '.json'),
659
+ * createFilePersister(
660
+ * createMergeableStore(),
661
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
662
+ * ),
657
663
  * (store) => store.setValue('pathId', pathId),
658
664
  * ],
659
665
  * );
@@ -585,7 +585,10 @@ export interface WsServer {
585
585
  * const server = createWsServer(
586
586
  * new WebSocketServer({port: 8047}),
587
587
  * (pathId) =>
588
- * createFilePersister(createMergeableStore(), pathId + '.json'),
588
+ * createFilePersister(
589
+ * createMergeableStore(),
590
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
591
+ * ),
589
592
  * );
590
593
  *
591
594
  * // Client 1
@@ -653,7 +656,10 @@ export interface WsServer {
653
656
  * const server = createWsServer(
654
657
  * new WebSocketServer({port: 8047}),
655
658
  * (pathId) => [
656
- * createFilePersister(createMergeableStore(), pathId + '.json'),
659
+ * createFilePersister(
660
+ * createMergeableStore(),
661
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
662
+ * ),
657
663
  * (store) => store.setValue('pathId', pathId),
658
664
  * ],
659
665
  * );
@@ -609,7 +609,10 @@ export interface WsServer {
609
609
  * const server = createWsServer(
610
610
  * new WebSocketServer({port: 8047}),
611
611
  * (pathId) =>
612
- * createFilePersister(createMergeableStore(), pathId + '.json'),
612
+ * createFilePersister(
613
+ * createMergeableStore(),
614
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
615
+ * ),
613
616
  * );
614
617
  *
615
618
  * // Client 1
@@ -677,7 +680,10 @@ export interface WsServer {
677
680
  * const server = createWsServer(
678
681
  * new WebSocketServer({port: 8047}),
679
682
  * (pathId) => [
680
- * createFilePersister(createMergeableStore(), pathId + '.json'),
683
+ * createFilePersister(
684
+ * createMergeableStore(),
685
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
686
+ * ),
681
687
  * (store) => store.setValue('pathId', pathId),
682
688
  * ],
683
689
  * );
@@ -609,7 +609,10 @@ export interface WsServer {
609
609
  * const server = createWsServer(
610
610
  * new WebSocketServer({port: 8047}),
611
611
  * (pathId) =>
612
- * createFilePersister(createMergeableStore(), pathId + '.json'),
612
+ * createFilePersister(
613
+ * createMergeableStore(),
614
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
615
+ * ),
613
616
  * );
614
617
  *
615
618
  * // Client 1
@@ -677,7 +680,10 @@ export interface WsServer {
677
680
  * const server = createWsServer(
678
681
  * new WebSocketServer({port: 8047}),
679
682
  * (pathId) => [
680
- * createFilePersister(createMergeableStore(), pathId + '.json'),
683
+ * createFilePersister(
684
+ * createMergeableStore(),
685
+ * pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
686
+ * ),
681
687
  * (store) => store.setValue('pathId', pathId),
682
688
  * ],
683
689
  * );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "5.1.1",
3
+ "version": "5.1.2",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
@@ -21,8 +21,8 @@
21
21
  "sideEffects": false,
22
22
  "peerDependencies": {
23
23
  "@automerge/automerge-repo": "^1.2.0",
24
- "@journeyapps/powersync-sdk-common": "^1.6.0",
25
- "@libsql/client": "^0.7.0",
24
+ "@powersync/common": "^1.6.0",
25
+ "@libsql/client": "^0.8.0",
26
26
  "@sqlite.org/sqlite-wasm": "^3.46.0-build2",
27
27
  "@vlcn.io/crsqlite-wasm": "^0.16.0",
28
28
  "electric-sql": "^0.12.1",
@@ -41,7 +41,7 @@
41
41
  "@automerge/automerge-repo": {
42
42
  "optional": true
43
43
  },
44
- "@journeyapps/powersync-sdk-common": {
44
+ "@powersync/common": {
45
45
  "optional": true
46
46
  },
47
47
  "@libsql/client": {
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- <section id="hero"><h2 id="the-reactive-data-store-for-local-first-apps">The <em>reactive</em> data store for <span>local-first apps</span>.</h2></section><p><a href="https://tinybase.org/guides/releases/#v5-1"><em>NEW!</em> v5.1 release</a></p><p><span id="one-with">&quot;The One You Can Sync... with a server!&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><section><h2 id="it-s-reactive">It&#x27;s <em>Reactive</em></h2><p>TinyBase lets you <a href="#register-granular-listeners">listen to changes</a> made to any part of your data. This means your app will be fast, since you only spend rendering cycles on things that change. The optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and <a href="#pre-built-reactive-components">pre-built components</a> let you easily build fully reactive UIs on top of TinyBase. You even get a built-in <a href="#set-checkpoints-for-an-undo-stack">undo stack</a>, and <a href="#an-inspector-for-your-data">developer tools</a>!</p></section><section><h2 id="it-s-database-like">It&#x27;s <em>Database-Like</em></h2><p>Consumer app? Enterprise app? Or even a game? Model <a href="#start-with-a-simple-key-value-store">key-value data</a> and <a href="#level-up-to-use-tabular-data">tabular data</a> with optional typed <a href="#apply-schemas-to-tables-values">schematization</a>, whatever its data structures. There are built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, and tabular <a href="#model-table-relationships">relationships</a> APIs - and a powerful <a href="#build-complex-queries-with-tinyql">query engine</a> to select, join, filter, and group data (reactively!) without SQL.</p></section><section><h2 id="it-synchronizes">It <em>Synchronizes</em></h2><p>TinyBase has <a href="#synchronize-between-devices">native CRDT</a> support, meaning that you can deterministically <a href="https://tinybase.org/guides/synchronization/">synchronize</a> and merge data across multiple sources, clients, and servers. And although TinyBase is an in-memory data store, but you can easily <a href="#persist-to-storage-sqlite-more">persist</a> your data to file, <a href="https://tinybase.org/api/persister-browser">browser storage</a>, <a href="https://tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://tinybase.org/guides/persistence/database-persistence/">SQLite databases</a>, and <a href="https://tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>.</p></section><section><h2 id="it-s-built-for-a-local-first-world">It&#x27;s Built For A <em>Local-First</em> World</h2><p>TinyBase works anywhere that JavaScript does, but it&#x27;s especially great for local-first apps: where data is stored locally on the user&#x27;s device and that can be run offline. It&#x27;s tiny by name, tiny by nature: just <a href="#did-we-say-tiny">5.3kB - 12.7kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends!</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img width="48" src="https://tinybase.org/react.svg"> React</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img width="48" src="https://tinybase.org/partykit.svg"> PartyKit</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/expo.svg">Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/electric.svg">ElectricSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/sqlite.svg"> SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/turso.svg">Turso</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/powersync.svg">PowerSync</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img width="48" src="https://tinybase.org/indexeddb.svg"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img width="48" src="https://tinybase.org/yjs.svg"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img width="48" src="https://tinybase.org/crsqlite.png"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img width="48" src="https://tinybase.org/automerge.svg"> Automerge</a></div></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;label=Twitter&amp;labelColor=%23333&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=jest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/5.1.0" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/store/functions/creation/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
1
+ <section id="hero"><h2 id="the-reactive-data-store-for-local-first-apps">The <em>reactive</em> data store for <span>local-first apps</span>.</h2></section><p><a href="https://tinybase.org/guides/releases/#v5-1"><em>NEW!</em> v5.1 release</a></p><p><span id="one-with">&quot;The One You Can Sync... with a server!&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><section><h2 id="it-s-reactive">It&#x27;s <em>Reactive</em></h2><p>TinyBase lets you <a href="#register-granular-listeners">listen to changes</a> made to any part of your data. This means your app will be fast, since you only spend rendering cycles on things that change. The optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and <a href="#pre-built-reactive-components">pre-built components</a> let you easily build fully reactive UIs on top of TinyBase. You even get a built-in <a href="#set-checkpoints-for-an-undo-stack">undo stack</a>, and <a href="#an-inspector-for-your-data">developer tools</a>!</p></section><section><h2 id="it-s-database-like">It&#x27;s <em>Database-Like</em></h2><p>Consumer app? Enterprise app? Or even a game? Model <a href="#start-with-a-simple-key-value-store">key-value data</a> and <a href="#level-up-to-use-tabular-data">tabular data</a> with optional typed <a href="#apply-schemas-to-tables-values">schematization</a>, whatever its data structures. There are built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, and tabular <a href="#model-table-relationships">relationships</a> APIs - and a powerful <a href="#build-complex-queries-with-tinyql">query engine</a> to select, join, filter, and group data (reactively!) without SQL.</p></section><section><h2 id="it-synchronizes">It <em>Synchronizes</em></h2><p>TinyBase has <a href="#synchronize-between-devices">native CRDT</a> support, meaning that you can deterministically <a href="https://tinybase.org/guides/synchronization/">synchronize</a> and merge data across multiple sources, clients, and servers. And although TinyBase is an in-memory data store, but you can easily <a href="#persist-to-storage-sqlite-more">persist</a> your data to file, <a href="https://tinybase.org/api/persister-browser">browser storage</a>, <a href="https://tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://tinybase.org/guides/persistence/database-persistence/">SQLite databases</a>, and <a href="https://tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>.</p></section><section><h2 id="it-s-built-for-a-local-first-world">It&#x27;s Built For A <em>Local-First</em> World</h2><p>TinyBase works anywhere that JavaScript does, but it&#x27;s especially great for local-first apps: where data is stored locally on the user&#x27;s device and that can be run offline. It&#x27;s tiny by name, tiny by nature: just <a href="#did-we-say-tiny">5.3kB - 12.7kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends!</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img width="48" src="https://tinybase.org/react.svg"> React</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img width="48" src="https://tinybase.org/partykit.svg"> PartyKit</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/expo.svg">Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/electric.svg">ElectricSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/sqlite.svg"> SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/turso.svg">Turso</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/powersync.svg">PowerSync</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img width="48" src="https://tinybase.org/indexeddb.svg"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img width="48" src="https://tinybase.org/yjs.svg"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img width="48" src="https://tinybase.org/crsqlite.png"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img width="48" src="https://tinybase.org/automerge.svg"> Automerge</a></div></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;label=Twitter&amp;labelColor=%23333&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=jest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/5.1.2" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/store/functions/creation/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
2
2
 
3
3
  ```js
4
4
  import {createStore} from 'tinybase';
@@ -292,4 +292,4 @@ export const createShop: typeof createShopDecl = () => {
292
292
  };
293
293
  ```
294
294
 
295
- <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic <a href="https://tinybase.org/api/store/"><code>store</code></a> module alone, you&#x27;ll only add a gzipped <em>5.3kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>12.7kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>4.6kB</em>, the ui-react-dom components are another <em>2.5kB</em>, and everything is super fast. Life&#x27;s easy when you have zero dependencies!</p><p>Read more about how TinyBase is structured and packaged in the <a href="https://tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>5.3kB</td><td>52.5kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.7kB</td><td>130.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>4.6kB</td><td>48.3kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>2.5kB</td><td>20.4kB</td></tr></tbody></table></div><section><h2 id="well-tested-and-documented">Well tested and documented.</h2><p>TinyBase has <em>100.0%</em> test coverage, including the code throughout the documentation - even on this page! The guides, demos, and API examples are designed to make it as easy as possible for you to get your TinyBase-powered app up and running.</p><p>Read more about how TinyBase is tested in the Unit <a href="https://tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Lines</th><td>2,380</td><td>2,380</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,567</td><td>2,567</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,006</td><td>1,006</td><td>100.0%</td></tr><tr><th class="right">Branches</th><td>951</td><td>951</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">6,848</td></tr><tr><th class="right">Assertions</th><td colspan="3">32,069</td></tr></tbody></table></div><hr><section id="sponsors"><h2 id="proud-to-be-sponsored-by">Proud to be sponsored by:</h2><a href="https://github.com/cpojer" target="_blank"><img title="cpojer" src="https://github.com/cpojer.png?size=48" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img title="expo" src="https://github.com/expo.png?size=48" width="48" height="48"></a><a href="https://github.com/beekeeb" target="_blank"><img title="beekeeb" src="https://github.com/beekeeb.png?size=48" width="48" height="48"></a><a href="https://github.com/cancelself" target="_blank"><img title="cancelself" src="https://github.com/cancelself.png?size=48" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img title="WonderPanda" src="https://github.com/WonderPanda.png?size=48" width="48" height="48"></a><a href="https://github.com/arpitBhalla" target="_blank"><img title="arpitBhalla" src="https://github.com/arpitBhalla.png?size=48" width="48" height="48"></a></section><section id="users"><h2 id="excited-to-be-used-by">Excited to be used by:</h2><a href="https://github.com/Apocalypsor" target="_blank"><img title="Apocalypsor" src="https://github.com/Apocalypsor.png?size=48" width="48" height="48"></a><a href="https://github.com/brentvatne" target="_blank"><img title="brentvatne" src="https://github.com/brentvatne.png?size=48" width="48" height="48"></a><a href="https://github.com/byCedric" target="_blank"><img title="byCedric" src="https://github.com/byCedric.png?size=48" width="48" height="48"></a><a href="https://github.com/circadian-risk" target="_blank"><img title="circadian-risk" src="https://github.com/circadian-risk.png?size=48" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img title="cpojer" src="https://github.com/cpojer.png?size=48" width="48" height="48"></a><a href="https://github.com/cubecull" target="_blank"><img title="cubecull" src="https://github.com/cubecull.png?size=48" width="48" height="48"></a><a href="https://github.com/erwinkn" target="_blank"><img title="erwinkn" src="https://github.com/erwinkn.png?size=48" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img title="expo" src="https://github.com/expo.png?size=48" width="48" height="48"></a><a href="https://github.com/ezra-en" target="_blank"><img title="ezra-en" src="https://github.com/ezra-en.png?size=48" width="48" height="48"></a><a href="https://github.com/fdfontes" target="_blank"><img title="fdfontes" src="https://github.com/fdfontes.png?size=48" width="48" height="48"></a><a href="https://github.com/feychenie" target="_blank"><img title="feychenie" src="https://github.com/feychenie.png?size=48" width="48" height="48"></a><a href="https://github.com/flaming-codes" target="_blank"><img title="flaming-codes" src="https://github.com/flaming-codes.png?size=48" width="48" height="48"></a><a href="https://github.com/fostertheweb" target="_blank"><img title="fostertheweb" src="https://github.com/fostertheweb.png?size=48" width="48" height="48"></a><a href="https://github.com/generates" target="_blank"><img title="generates" src="https://github.com/generates.png?size=48" width="48" height="48"></a><a href="https://github.com/Giulio987" target="_blank"><img title="Giulio987" src="https://github.com/Giulio987.png?size=48" width="48" height="48"></a><a href="https://github.com/itsdevcoffee" target="_blank"><img title="itsdevcoffee" src="https://github.com/itsdevcoffee.png?size=48" width="48" height="48"></a><a href="https://github.com/jaysc" target="_blank"><img title="jaysc" src="https://github.com/jaysc.png?size=48" width="48" height="48"></a><a href="https://github.com/jbolda" target="_blank"><img title="jbolda" src="https://github.com/jbolda.png?size=48" width="48" height="48"></a><a href="https://github.com/Kayoo-asso" target="_blank"><img title="Kayoo-asso" src="https://github.com/Kayoo-asso.png?size=48" width="48" height="48"></a><a href="https://github.com/kotofurumiya" target="_blank"><img title="kotofurumiya" src="https://github.com/kotofurumiya.png?size=48" width="48" height="48"></a><a href="https://github.com/Kudo" target="_blank"><img title="Kudo" src="https://github.com/Kudo.png?size=48" width="48" height="48"></a><a href="https://github.com/learn-anything" target="_blank"><img title="learn-anything" src="https://github.com/learn-anything.png?size=48" width="48" height="48"></a><a href="https://github.com/lluc" target="_blank"><img title="lluc" src="https://github.com/lluc.png?size=48" width="48" height="48"></a><a href="https://github.com/marksteve" target="_blank"><img title="marksteve" src="https://github.com/marksteve.png?size=48" width="48" height="48"></a><a href="https://github.com/miking-the-viking" target="_blank"><img title="miking-the-viking" src="https://github.com/miking-the-viking.png?size=48" width="48" height="48"></a><a href="https://github.com/mjamesderocher" target="_blank"><img title="mjamesderocher" src="https://github.com/mjamesderocher.png?size=48" width="48" height="48"></a><a href="https://github.com/mouktardev" target="_blank"><img title="mouktardev" src="https://github.com/mouktardev.png?size=48" width="48" height="48"></a><a href="https://github.com/nickmessing" target="_blank"><img title="nickmessing" src="https://github.com/nickmessing.png?size=48" width="48" height="48"></a><a href="https://github.com/nikitavoloboev" target="_blank"><img title="nikitavoloboev" src="https://github.com/nikitavoloboev.png?size=48" width="48" height="48"></a><a href="https://github.com/nkzw-tech" target="_blank"><img title="nkzw-tech" src="https://github.com/nkzw-tech.png?size=48" width="48" height="48"></a><a href="https://github.com/palerdot" target="_blank"><img title="palerdot" src="https://github.com/palerdot.png?size=48" width="48" height="48"></a><a href="https://github.com/PorcoRosso85" target="_blank"><img title="PorcoRosso85" src="https://github.com/PorcoRosso85.png?size=48" width="48" height="48"></a><a href="https://github.com/primodiumxyz" target="_blank"><img title="primodiumxyz" src="https://github.com/primodiumxyz.png?size=48" width="48" height="48"></a><a href="https://github.com/shaneosullivan" target="_blank"><img title="shaneosullivan" src="https://github.com/shaneosullivan.png?size=48" width="48" height="48"></a><a href="https://github.com/sudo-self" target="_blank"><img title="sudo-self" src="https://github.com/sudo-self.png?size=48" width="48" height="48"></a><a href="https://github.com/SuperSonicHub1" target="_blank"><img title="SuperSonicHub1" src="https://github.com/SuperSonicHub1.png?size=48" width="48" height="48"></a><a href="https://github.com/threepointone" target="_blank"><img title="threepointone" src="https://github.com/threepointone.png?size=48" width="48" height="48"></a><a href="https://github.com/uptonking" target="_blank"><img title="uptonking" src="https://github.com/uptonking.png?size=48" width="48" height="48"></a><a href="https://github.com/ViktorZhurbin" target="_blank"><img title="ViktorZhurbin" src="https://github.com/ViktorZhurbin.png?size=48" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img title="WonderPanda" src="https://github.com/WonderPanda.png?size=48" width="48" height="48"></a></section><hr><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><section id="about"><h2 id="about">About</h2><p>Modern apps deserve better. Why trade reactive user experiences to be able to use relational data? Or sacrifice features for bundle size? And why does the cloud do all the work <a href="https://localfirstweb.dev/" target="_blank">anyway</a>?</p><p>Building TinyBase was originally an interesting exercise for <a rel="me" href="https://tripleodeon.com">me</a> in API design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.</p><p>It could not have been built without these great <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://tinybase.org/youtube.webp"></a></section>
295
+ <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic <a href="https://tinybase.org/api/store/"><code>store</code></a> module alone, you&#x27;ll only add a gzipped <em>5.3kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>12.7kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>4.6kB</em>, the ui-react-dom components are another <em>2.5kB</em>, and everything is super fast. Life&#x27;s easy when you have zero dependencies!</p><p>Read more about how TinyBase is structured and packaged in the <a href="https://tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>5.3kB</td><td>52.5kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.7kB</td><td>130.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>4.6kB</td><td>48.3kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>2.5kB</td><td>20.4kB</td></tr></tbody></table></div><section><h2 id="well-tested-and-documented">Well tested and documented.</h2><p>TinyBase has <em>100.0%</em> test coverage, including the code throughout the documentation - even on this page! The guides, demos, and API examples are designed to make it as easy as possible for you to get your TinyBase-powered app up and running.</p><p>Read more about how TinyBase is tested in the Unit <a href="https://tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Lines</th><td>2,380</td><td>2,380</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,567</td><td>2,567</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,006</td><td>1,006</td><td>100.0%</td></tr><tr><th class="right">Branches</th><td>951</td><td>951</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">6,851</td></tr><tr><th class="right">Assertions</th><td colspan="3">32,074</td></tr></tbody></table></div><hr><section id="sponsors"><h2 id="proud-to-be-sponsored-by">Proud to be sponsored by:</h2><a href="https://github.com/cpojer" target="_blank"><img title="cpojer" src="https://github.com/cpojer.png?size=48" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img title="expo" src="https://github.com/expo.png?size=48" width="48" height="48"></a><a href="https://github.com/beekeeb" target="_blank"><img title="beekeeb" src="https://github.com/beekeeb.png?size=48" width="48" height="48"></a><a href="https://github.com/cancelself" target="_blank"><img title="cancelself" src="https://github.com/cancelself.png?size=48" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img title="WonderPanda" src="https://github.com/WonderPanda.png?size=48" width="48" height="48"></a><a href="https://github.com/arpitBhalla" target="_blank"><img title="arpitBhalla" src="https://github.com/arpitBhalla.png?size=48" width="48" height="48"></a></section><section id="users"><h2 id="excited-to-be-used-by">Excited to be used by:</h2><a href="https://github.com/Apocalypsor" target="_blank"><img title="Apocalypsor" src="https://github.com/Apocalypsor.png?size=48" width="48" height="48"></a><a href="https://github.com/brentvatne" target="_blank"><img title="brentvatne" src="https://github.com/brentvatne.png?size=48" width="48" height="48"></a><a href="https://github.com/byCedric" target="_blank"><img title="byCedric" src="https://github.com/byCedric.png?size=48" width="48" height="48"></a><a href="https://github.com/circadian-risk" target="_blank"><img title="circadian-risk" src="https://github.com/circadian-risk.png?size=48" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img title="cpojer" src="https://github.com/cpojer.png?size=48" width="48" height="48"></a><a href="https://github.com/cubecull" target="_blank"><img title="cubecull" src="https://github.com/cubecull.png?size=48" width="48" height="48"></a><a href="https://github.com/erwinkn" target="_blank"><img title="erwinkn" src="https://github.com/erwinkn.png?size=48" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img title="expo" src="https://github.com/expo.png?size=48" width="48" height="48"></a><a href="https://github.com/ezra-en" target="_blank"><img title="ezra-en" src="https://github.com/ezra-en.png?size=48" width="48" height="48"></a><a href="https://github.com/fdfontes" target="_blank"><img title="fdfontes" src="https://github.com/fdfontes.png?size=48" width="48" height="48"></a><a href="https://github.com/feychenie" target="_blank"><img title="feychenie" src="https://github.com/feychenie.png?size=48" width="48" height="48"></a><a href="https://github.com/flaming-codes" target="_blank"><img title="flaming-codes" src="https://github.com/flaming-codes.png?size=48" width="48" height="48"></a><a href="https://github.com/fostertheweb" target="_blank"><img title="fostertheweb" src="https://github.com/fostertheweb.png?size=48" width="48" height="48"></a><a href="https://github.com/generates" target="_blank"><img title="generates" src="https://github.com/generates.png?size=48" width="48" height="48"></a><a href="https://github.com/Giulio987" target="_blank"><img title="Giulio987" src="https://github.com/Giulio987.png?size=48" width="48" height="48"></a><a href="https://github.com/itsdevcoffee" target="_blank"><img title="itsdevcoffee" src="https://github.com/itsdevcoffee.png?size=48" width="48" height="48"></a><a href="https://github.com/jaysc" target="_blank"><img title="jaysc" src="https://github.com/jaysc.png?size=48" width="48" height="48"></a><a href="https://github.com/jbolda" target="_blank"><img title="jbolda" src="https://github.com/jbolda.png?size=48" width="48" height="48"></a><a href="https://github.com/Kayoo-asso" target="_blank"><img title="Kayoo-asso" src="https://github.com/Kayoo-asso.png?size=48" width="48" height="48"></a><a href="https://github.com/kotofurumiya" target="_blank"><img title="kotofurumiya" src="https://github.com/kotofurumiya.png?size=48" width="48" height="48"></a><a href="https://github.com/Kudo" target="_blank"><img title="Kudo" src="https://github.com/Kudo.png?size=48" width="48" height="48"></a><a href="https://github.com/learn-anything" target="_blank"><img title="learn-anything" src="https://github.com/learn-anything.png?size=48" width="48" height="48"></a><a href="https://github.com/lluc" target="_blank"><img title="lluc" src="https://github.com/lluc.png?size=48" width="48" height="48"></a><a href="https://github.com/marksteve" target="_blank"><img title="marksteve" src="https://github.com/marksteve.png?size=48" width="48" height="48"></a><a href="https://github.com/miking-the-viking" target="_blank"><img title="miking-the-viking" src="https://github.com/miking-the-viking.png?size=48" width="48" height="48"></a><a href="https://github.com/mjamesderocher" target="_blank"><img title="mjamesderocher" src="https://github.com/mjamesderocher.png?size=48" width="48" height="48"></a><a href="https://github.com/mouktardev" target="_blank"><img title="mouktardev" src="https://github.com/mouktardev.png?size=48" width="48" height="48"></a><a href="https://github.com/nickmessing" target="_blank"><img title="nickmessing" src="https://github.com/nickmessing.png?size=48" width="48" height="48"></a><a href="https://github.com/nikitavoloboev" target="_blank"><img title="nikitavoloboev" src="https://github.com/nikitavoloboev.png?size=48" width="48" height="48"></a><a href="https://github.com/nkzw-tech" target="_blank"><img title="nkzw-tech" src="https://github.com/nkzw-tech.png?size=48" width="48" height="48"></a><a href="https://github.com/palerdot" target="_blank"><img title="palerdot" src="https://github.com/palerdot.png?size=48" width="48" height="48"></a><a href="https://github.com/PorcoRosso85" target="_blank"><img title="PorcoRosso85" src="https://github.com/PorcoRosso85.png?size=48" width="48" height="48"></a><a href="https://github.com/primodiumxyz" target="_blank"><img title="primodiumxyz" src="https://github.com/primodiumxyz.png?size=48" width="48" height="48"></a><a href="https://github.com/shaneosullivan" target="_blank"><img title="shaneosullivan" src="https://github.com/shaneosullivan.png?size=48" width="48" height="48"></a><a href="https://github.com/sudo-self" target="_blank"><img title="sudo-self" src="https://github.com/sudo-self.png?size=48" width="48" height="48"></a><a href="https://github.com/SuperSonicHub1" target="_blank"><img title="SuperSonicHub1" src="https://github.com/SuperSonicHub1.png?size=48" width="48" height="48"></a><a href="https://github.com/threepointone" target="_blank"><img title="threepointone" src="https://github.com/threepointone.png?size=48" width="48" height="48"></a><a href="https://github.com/uptonking" target="_blank"><img title="uptonking" src="https://github.com/uptonking.png?size=48" width="48" height="48"></a><a href="https://github.com/ViktorZhurbin" target="_blank"><img title="ViktorZhurbin" src="https://github.com/ViktorZhurbin.png?size=48" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img title="WonderPanda" src="https://github.com/WonderPanda.png?size=48" width="48" height="48"></a></section><hr><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><section id="about"><h2 id="about">About</h2><p>Modern apps deserve better. Why trade reactive user experiences to be able to use relational data? Or sacrifice features for bundle size? And why does the cloud do all the work <a href="https://localfirstweb.dev/" target="_blank">anyway</a>?</p><p>Building TinyBase was originally an interesting exercise for <a rel="me" href="https://tripleodeon.com">me</a> in API design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.</p><p>It could not have been built without these great <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://tinybase.org/youtube.webp"></a></section>
package/releases.md CHANGED
@@ -8,8 +8,14 @@ import {createWsServer} from 'tinybase/synchronizers/synchronizer-ws-server';
8
8
 
9
9
  const persistingServer = createWsServer(
10
10
  new WebSocketServer({port: 8051}),
11
- (pathId) => createFilePersister(createMergeableStore(), pathId + '.json'),
11
+ (pathId) =>
12
+ createFilePersister(
13
+ createMergeableStore(),
14
+ pathId.replace(/[^a-zA-Z0-9]/g, '-') + '.json',
15
+ ),
12
16
  );
17
+
18
+ persistingServer.destroy();
13
19
  ```
14
20
 
15
21
  <p>This is a very crude (and not production-safe!) example, but demonstrates a server that will create a file, based on any path that clients connect to, and persist data to it. See the <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> function documentation for more details.</p><p>This implementation is still experimental so please kick the tires!</p><p>There is one small breaking change in this release: the functions for creating <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/"><code>Synchronizer</code></a> objects can now take optional onSend and onReceive callbacks that will fire whenever messages pass through the <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/"><code>Synchronizer</code></a>. See, for example, the <a href="https://tinybase.org/api/synchronizer-ws-client/functions/creation/createwssynchronizer/"><code>createWsSynchronizer</code></a> function. These are suitable for debugging synchronization issues in a development environment.</p><h2 id="v5-0">v5.0</h2><p>We&#x27;re excited to announce this major release for <a href="https://tinybase.org/">TinyBase</a>! It includes important data synchronization functionality and a range of other improvements.</p><h2 id="in-summary">In Summary</h2><ul><li><a href="#the-new-mergeableStore-type">The new MergeableStore type</a> wraps your data as a Conflict-Free Replicated Data Type (CRDT).</li><li><a href="#the-new-synchronizer-framework">The new Synchronizer framework</a> keeps multiple instances of data in sync across different media.</li><li>An <a href="#improved-module-folder-structure">improved module folder structure</a> removes common packaging and bundling issues.</li><li>The <a href="https://tinybase.org/">TinyBase</a> Inspector is now in its own standalone <a href="https://tinybase.org/api/ui-react-inspector/"><code>ui-react-inspector</code></a> module.</li><li><a href="https://tinybase.org/">TinyBase</a> now supports only Expo SQLite v14 (<a href="https://expo.dev/changelog/2024/05-07-sdk-51">SDK 51</a>) and above.</li></ul><p>There are also some small <a href="#breaking-changes-in-v50">breaking changes</a> that may affect you (but which should easy to fix if they do).</p><p>Let&#x27;s look at the major functionality in more detail!</p><h3 id="the-new-mergeablestore-type">The New <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> Type</h3><p>A key part of <a href="https://tinybase.org/">TinyBase</a> v5.0 is the new <a href="https://tinybase.org/api/mergeable-store/"><code>mergeable-store</code></a> module, which contains a subtype of <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> - called <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> - that can be merged with another with deterministic results. The implementation uses an encoded hybrid logical clock (HLC) to timestamp the changes made so that they can be cleanly merged.</p><p>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getmergeablecontent/"><code>getMergeableContent</code></a> method on a <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> is used to get the state of a store that can be merged into another. The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/applymergeablechanges/"><code>applyMergeableChanges</code></a> method will let you apply that to (another) store. The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/merge/"><code>merge</code></a> method is a convenience function to bidirectionally merge two stores together:</p>