tinybase 5.0.0 → 5.1.0-beta.0

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 (3) hide show
  1. package/package.json +1 -1
  2. package/readme.md +40 -13
  3. package/releases.md +22 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "5.0.0",
3
+ "version": "5.1.0-beta.0",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
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://beta.tinybase.org/guides/releases/#v5-0"><em>NEW!</em> v5.0 release</a> <span id="one-with">&quot;The One You Can Sync&quot;</span></p><p><a class="start" href="https://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.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>Store <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="&#x27;#apply-schemas-to-tables-values">schematization</a> to model your app&#x27;s data structures. TinyBase provides 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 - or the 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 is an in-memory data store, but you can easily <a href="#persist-to-storage-sqlite-crdts">persist</a> your data to <a href="https://beta.tinybase.org/api/persister-browser">browser storage</a>, <a href="https://beta.tinybase.org/api/persister-indexed-db">IndexedDB</a>, many flavors of <a href="https://beta.tinybase.org/guides/persistence/database-persistence/">database</a>, and <a href="https://beta.tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>. TinyBase now has native CRDT support, meaning that you can <a href="https://beta.tinybase.org/guides/synchronization/">natively synchronize</a> and merge data across multiple sources and clients.</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://beta.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://beta.tinybase.org/guides/building-uis/getting-started-with-ui-react"><img width="48" src="https://beta.tinybase.org/react.svg"> React</a></div><div><a href="https://beta.tinybase.org/api/persister-partykit-client"><img width="48" src="https://beta.tinybase.org/partykit.svg"> PartyKit</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://beta.tinybase.org/expo.svg">Expo SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://beta.tinybase.org/electric.svg">ElectricSQL</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://beta.tinybase.org/sqlite.svg"> SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://beta.tinybase.org/turso.svg">Turso</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://beta.tinybase.org/powersync.svg">PowerSync</a></div><div><a href="https://beta.tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img width="48" src="https://beta.tinybase.org/indexeddb.svg"> IndexedDB</a></div><div><a href="https://beta.tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img width="48" src="https://beta.tinybase.org/yjs.svg"> YJS</a></div><div><a href="https://beta.tinybase.org/api/persister-cr-sqlite-wasm"><img width="48" src="https://beta.tinybase.org/crsqlite.png"> CR-SQLite</a></div><div><a href="https://beta.tinybase.org/api/persister-automerge"><img width="48" src="https://beta.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.0.0-beta.28" 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 Store requires just a simple call to the createStore function. Once you have one, you can easily set Values in it by unique Id. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://beta.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-0"><em>NEW!</em> v5.0 release</a> <span id="one-with">&quot;The One You Can Sync&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><a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> <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="&#x27;#apply-schemas-to-tables-values">schematization</a> to model your app&#x27;s data structures. TinyBase provides 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 - or the 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 is an in-memory data store, but you can easily <a href="#persist-to-storage-sqlite-more">persist</a> your data to <a href="https://tinybase.org/api/persister-browser">browser storage</a>, <a href="https://tinybase.org/api/persister-indexed-db">IndexedDB</a>, many flavors of <a href="https://tinybase.org/guides/persistence/database-persistence/">database</a>, and <a href="https://tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>. TinyBase now has <a href="#synchronize-between-devices">native CRDT</a> support, meaning that you can <a href="https://tinybase.org/guides/synchronization/">natively synchronize</a> and merge data across multiple sources and clients.</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.0.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>
2
2
 
3
3
  ```js
4
4
  import {createStore} from 'tinybase';
@@ -11,7 +11,7 @@ console.log(store.getValues());
11
11
  // -> {employees: 3, open: true}
12
12
  ```
13
13
 
14
- <section><h2 id="level-up-to-use-tabular-data">Level up to use tabular data.</h2><p>For other types of data applications, a tabular data structure is more useful. TinyBase lets you set and get nested Table, Row, or Cell data, by unique Id - and in the same Store as the keyed values!</p><p>Read more about setting and changing data in <a href="https://beta.tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
14
+ <section><h2 id="level-up-to-use-tabular-data">Level up to use tabular data.</h2><p>For other types of data applications, a tabular data structure is more useful. TinyBase lets you set and get nested <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, or <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> data, by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> - and in the same <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> as the keyed values!</p><p>Read more about setting and changing data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
15
15
 
16
16
  ```js
17
17
  store
@@ -22,7 +22,7 @@ console.log(store.getRow('pets', 'fido'));
22
22
  // -> {species: 'dog', color: 'brown'}
23
23
  ```
24
24
 
25
- <section><h2 id="register-granular-listeners">Register granular listeners.</h2><p>The magic starts to happen when you register listeners on a Value, Table, Row, or Cell. They get called when any part of that object changes. You can also use wildcards - useful when you don&#x27;t know the Id of the objects that might change.</p><p>Read more about listeners in the <a href="https://beta.tinybase.org/guides/the-basics/listening-to-stores/">Listening To Stores</a> guide.</p></section>
25
+ <section><h2 id="register-granular-listeners">Register granular listeners.</h2><p>The magic starts to happen when you register listeners on a <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>, <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, or <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. They get called when any part of that object changes. You can also use wildcards - useful when you don&#x27;t know the <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> of the objects that might change.</p><p>Read more about listeners in the <a href="https://tinybase.org/guides/the-basics/listening-to-stores/">Listening To Stores</a> guide.</p></section>
26
26
 
27
27
  ```js
28
28
  const listenerId = store.addTableListener('pets', () =>
@@ -35,7 +35,7 @@ store.setCell('pets', 'fido', 'sold', false);
35
35
  store.delListener(listenerId);
36
36
  ```
37
37
 
38
- <section><h2 id="call-hooks-to-bind-to-data">Call hooks to bind to data.</h2><p>If you&#x27;re using React in your application, the optional ui-react module provides hooks to bind to the data in a Store.</p><p>More magic! The useCell hook in this example fetches the dog&#x27;s color. But it also registers a listener on that cell that will fire and re-render the component whenever the value changes.</p><p>Basically you simply describe what data you want in your user interface and TinyBase will take care of the whole lifecycle of updating it for you.</p><p>Read more about the using hooks in the <a href="https://beta.tinybase.org/guides/building-uis/using-react-hooks/">Using React Hooks</a> guide.</p></section>
38
+ <section><h2 id="call-hooks-to-bind-to-data">Call hooks to bind to data.</h2><p>If you&#x27;re using React in your application, the optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module provides hooks to bind to the data in a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</p><p>More magic! The <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usecell/"><code>useCell</code></a> hook in this example fetches the dog&#x27;s color. But it also registers a listener on that cell that will fire and re-render the component whenever the value changes.</p><p>Basically you simply describe what data you want in your user interface and TinyBase will take care of the whole lifecycle of updating it for you.</p><p>Read more about the using hooks in the <a href="https://tinybase.org/guides/building-uis/using-react-hooks/">Using React Hooks</a> guide.</p></section>
39
39
 
40
40
  ```jsx
41
41
  import React from 'react';
@@ -58,7 +58,7 @@ console.log(app.innerHTML);
58
58
  // -> 'Color: walnut'
59
59
  ```
60
60
 
61
- <section><h2 id="pre-built-reactive-components">Pre-built reactive components.</h2><p>The ui-react module provides bare React components that let you build up a fully reactive user interface based on a Store.</p><p>For web applications in particular, the new ui-react-dom module provides pre-built components for tabular display of your data, with lots of customization and interactivity options.</p><p>Try them out in the <a href="https://beta.tinybase.org/demos/ui-components/">UI Components</a> demos, and read more about the underlying ui-react module in the <a href="https://beta.tinybase.org/guides/building-uis/">Building UIs</a> guides.</p></section><img src="https://beta.tinybase.org/ui-react-dom.webp"><section><h2 id="an-inspector-for-your-data">An inspector for your data.</h2><p>If you are building a web application, the new Inspector component lets you overlay a view of the data in your Store, Indexes, Relationships, and so on. You can even edit the data in place and see it update in your app immediately.</p><p>Read more about this powerful new tool in the <a href="https://beta.tinybase.org/guides/developer-tools/inspecting-data/">Inspecting Data</a> guide.</p></section><img src="https://beta.tinybase.org/store-inspector.webp"><section><h2 id="apply-schemas-to-tables-values">Apply schemas to tables &amp; values.</h2><p>By default, a Store can contain any arbitrary Value, and a Row can contain any arbitrary Cell. But you can add a ValuesSchema or a TablesSchema to a Store to ensure that the values are always what you expect: constraining their types, and providing defaults.</p><p>In this example, we set a new Row without the <code>sold</code> Cell in it. The schema ensures it&#x27;s present with default of <code>false</code>.</p><p>Read more about schemas in the <a href="https://beta.tinybase.org/guides/schemas/">Schemas</a> guide.</p></section>
61
+ <section><h2 id="pre-built-reactive-components">Pre-built reactive components.</h2><p>The <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module provides bare React components that let you build up a fully reactive user interface based on a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</p><p>For web applications in particular, the new <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module provides pre-built components for tabular display of your data, with lots of customization and interactivity options.</p><p>Try them out in the <a href="https://tinybase.org/demos/ui-components/">UI Components</a> demos, and read more about the underlying <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module in the <a href="https://tinybase.org/guides/building-uis/">Building UIs</a> guides.</p></section><img src="https://tinybase.org/ui-react-dom.webp"><section><h2 id="an-inspector-for-your-data">An inspector for your data.</h2><p>If you are building a web application, the new <a href="https://tinybase.org/api/ui-react-inspector/functions/development-components/inspector/"><code>Inspector</code></a> component lets you overlay a view of the data in your <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a>, <a href="https://tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a>, and so on. You can even edit the data in place and see it update in your app immediately.</p><p>Read more about this powerful new tool in the <a href="https://tinybase.org/guides/developer-tools/inspecting-data/">Inspecting Data</a> guide.</p></section><img src="https://tinybase.org/store-inspector.webp"><section><h2 id="apply-schemas-to-tables-values">Apply schemas to tables &amp; values.</h2><p>By default, a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> can contain any arbitrary <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>, and a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> can contain any arbitrary <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. But you can add a <a href="https://tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> or a <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a> to a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> to ensure that the values are always what you expect: constraining their types, and providing defaults.</p><p>In this example, we set a new <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> without the <code>sold</code> <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> in it. The schema ensures it&#x27;s present with default of <code>false</code>.</p><p>Read more about schemas in the <a href="https://tinybase.org/guides/schemas/">Schemas</a> guide.</p></section>
62
62
 
63
63
  ```js
64
64
  store.setTablesSchema({
@@ -76,7 +76,34 @@ console.log(store.getRow('pets', 'polly'));
76
76
  store.delTablesSchema();
77
77
  ```
78
78
 
79
- <section><h2 id="persist-to-storage-sqlite-crdts">Persist to storage, SQLite, CRDTs.</h2><p>You can easily persist a Store between browser page reloads or sessions. You can also synchronize it with a web endpoint, or (if you&#x27;re using TinyBase in an appropriate environment), load and save it to a file. <a href="https://beta.tinybase.org/guides/releases/#v4-0">New in v4.0</a>, you can bind <a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence/">TinyBase to SQLite</a> via a range of modules, or to <a href="https://yjs.dev/">Yjs</a> or <a href="https://automerge.org/">Automerge</a> CRDT documents.</p><p>Read more about persisters in the <a href="https://beta.tinybase.org/guides/persistence/">Persistence</a> guides.</p></section>
79
+ <section><h2 id="synchronize-between-devices">Synchronize between devices.</h2><p>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> type acts as a native CRDT, letting you merge data and synchronize it between clients and systems. The synchronization protocol can run over WebSockets, the browser BroadcastChannel, or your own custom synchronization medium.</p><p>Read more about these techniques in the <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> guides.</p></section>
80
+
81
+ ```js
82
+ import {WebSocketServer, WebSocket} from 'ws';
83
+ import {createMergeableStore} from 'tinybase';
84
+ import {createWsServer} from 'tinybase/synchronizers/synchronizer-ws-server';
85
+ import {createWsSynchronizer} from 'tinybase/synchronizers/synchronizer-ws-client';
86
+
87
+ // On a server machine:
88
+ const server = createWsServer(
89
+ new WebSocketServer({port: 8040}),
90
+ );
91
+
92
+ // On a client machine:
93
+ const store1 = createMergeableStore();
94
+ const synchronizer1 = await createWsSynchronizer(
95
+ store1,
96
+ new WebSocket('ws://localhost:8040'),
97
+ );
98
+ await synchronizer1.startSync();
99
+
100
+ // ...
101
+
102
+ synchronizer1.destroy();
103
+ server.destroy();
104
+ ```
105
+
106
+ <section><h2 id="persist-to-storage-sqlite-more">Persist to storage, SQLite, &amp; more.</h2><p>You can easily persist a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> between browser page reloads or sessions. You can also synchronize it with a web endpoint, or (if you&#x27;re using TinyBase in an appropriate environment), load and save it to a file. You can bind TinyBase to various flavors of <a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence/">SQLite</a>, or to <a href="https://yjs.dev/">Yjs</a> and <a href="https://automerge.org/">Automerge</a> CRDT documents.</p><p>Read more about persisters in the <a href="https://tinybase.org/guides/persistence/">Persistence</a> guides.</p></section>
80
107
 
81
108
  ```js
82
109
  import {createSessionPersister} from 'tinybase/persisters/persister-browser';
@@ -102,7 +129,7 @@ persister.destroy();
102
129
  sessionStorage.clear();
103
130
  ```
104
131
 
105
- <section><h2 id="build-complex-queries-with-tinyql">Build complex queries with <a href="https://beta.tinybase.org/guides/using-queries/tinyql/">TinyQL</a>.</h2><p>The Queries object lets you query data across tables, with filtering and aggregation - using a SQL-adjacent syntax called <a href="https://beta.tinybase.org/guides/using-queries/tinyql/">TinyQL</a>.</p><p>Accessors and listeners let you sort and paginate the results efficiently, making building rich tabular interfaces easier than ever.</p><p>In this example, we have two tables: of pets and their owners. They are joined together by the pet&#x27;s ownerId Cell. We select the pet&#x27;s species, and the owner&#x27;s state, and then aggregate the prices for the combinations.</p><p>We access the results by descending price, essentially answering the question: &quot;which is the highest-priced species, and in which state?&quot;</p><p>Needless to say, the results are reactive too! You can add listeners to queries just as easily as you do to raw tables.</p><p>Read more about Queries in the <a href="https://beta.tinybase.org/guides/releases/#v2-0">v2.0 Release Notes</a>, the <a href="https://beta.tinybase.org/guides/using-queries/">Using Queries</a> guide, and the <a href="https://beta.tinybase.org/demos/car-analysis/">Car Analysis</a> demo and <a href="https://beta.tinybase.org/demos/movie-database/">Movie Database</a> demo.</p></section>
132
+ <section><h2 id="build-complex-queries-with-tinyql">Build complex queries with <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a>.</h2><p>The <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> object lets you query data across tables, with filtering and aggregation - using a SQL-adjacent syntax called <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a>.</p><p>Accessors and listeners let you sort and paginate the results efficiently, making building rich tabular interfaces easier than ever.</p><p>In this example, we have two tables: of pets and their owners. They are joined together by the pet&#x27;s ownerId <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. We select the pet&#x27;s species, and the owner&#x27;s state, and then aggregate the prices for the combinations.</p><p>We access the results by descending price, essentially answering the question: &quot;which is the highest-priced species, and in which state?&quot;</p><p>Needless to say, the results are reactive too! You can add listeners to queries just as easily as you do to raw tables.</p><p>Read more about <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> in the <a href="https://tinybase.org/guides/releases/#v2-0">v2.0 Release Notes</a>, the <a href="https://tinybase.org/guides/using-queries/">Using Queries</a> guide, and the <a href="https://tinybase.org/demos/car-analysis/">Car Analysis</a> demo and <a href="https://tinybase.org/demos/movie-database/">Movie Database</a> demo.</p></section>
106
133
 
107
134
  ```js
108
135
  import {createQueries} from 'tinybase';
@@ -145,7 +172,7 @@ queries
145
172
  queries.destroy();
146
173
  ```
147
174
 
148
- <section><h2 id="define-metrics-and-aggregations">Define metrics and aggregations.</h2><p>A Metrics object makes it easy to keep a running aggregation of Cell values in each Row of a Table. This is useful for counting rows, but also supports averages, ranges of values, or arbitrary aggregations.</p><p>In this example, we create a new table of the pet species, and keep a track of which is most expensive. When we add horses to our pet store, the listener detects that the highest price has changed.</p><p>Read more about Metrics in the <a href="https://beta.tinybase.org/guides/using-metrics/">Using Metrics</a> guide.</p></section>
175
+ <section><h2 id="define-metrics-and-aggregations">Define metrics and aggregations.</h2><p>A <a href="https://tinybase.org/api/metrics/interfaces/metrics/metrics/"><code>Metrics</code></a> object makes it easy to keep a running aggregation of <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> values in each <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> of a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>. This is useful for counting rows, but also supports averages, ranges of values, or arbitrary aggregations.</p><p>In this example, we create a new table of the pet species, and keep a track of which is most expensive. When we add horses to our pet store, the listener detects that the highest price has changed.</p><p>Read more about <a href="https://tinybase.org/api/metrics/interfaces/metrics/metrics/"><code>Metrics</code></a> in the <a href="https://tinybase.org/guides/using-metrics/">Using Metrics</a> guide.</p></section>
149
176
 
150
177
  ```js
151
178
  import {createMetrics} from 'tinybase';
@@ -176,7 +203,7 @@ store.setCell('species', 'horse', 'price', 20);
176
203
  metrics.destroy();
177
204
  ```
178
205
 
179
- <section><h2 id="create-indexes-for-fast-lookups">Create indexes for fast lookups.</h2><p>An Indexes object makes it easy to look up all the Row objects that have a certain value in a Cell.</p><p>In this example, we create an index on the <code>species</code> Cell values. We can then get the the list of distinct Cell value present for that index (known as &#x27;slices&#x27;), and the set of Row objects that match each value.</p><p>Indexes objects are reactive too. So you can set listeners on them just as you do for the data in the underlying Store.</p><p>Read more about Indexes in the <a href="https://beta.tinybase.org/guides/using-indexes/">Using Indexes</a> guide.</p></section>
206
+ <section><h2 id="create-indexes-for-fast-lookups">Create indexes for fast lookups.</h2><p>An <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> object makes it easy to look up all the <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> objects that have a certain value in a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>.</p><p>In this example, we create an index on the <code>species</code> <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> values. We can then get the the list of distinct <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> value present for that index (known as &#x27;slices&#x27;), and the set of <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> objects that match each value.</p><p><a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> objects are reactive too. So you can set listeners on them just as you do for the data in the underlying <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</p><p>Read more about <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> in the <a href="https://tinybase.org/guides/using-indexes/">Using Indexes</a> guide.</p></section>
180
207
 
181
208
  ```js
182
209
  import {createIndexes} from 'tinybase';
@@ -202,7 +229,7 @@ store.setRow('pets', 'lowly', {species: 'worm'});
202
229
  indexes.destroy();
203
230
  ```
204
231
 
205
- <section><h2 id="model-table-relationships">Model table relationships.</h2><p>A Relationships object lets you associate a Row in a local Table with the Id of a Row in a remote Table. You can also reference a table to itself to create linked lists.</p><p>In this example, the <code>species</code> Cell of the <code>pets</code> Table is used to create a relationship to the <code>species</code> Table, so that we can access the price of a given pet.</p><p>Like everything else, you can set listeners on Relationships too.</p><p>Read more about Relationships in the <a href="https://beta.tinybase.org/guides/using-relationships/">Using Relationships</a> guide.</p></section>
232
+ <section><h2 id="model-table-relationships">Model table relationships.</h2><p>A <a href="https://tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a> object lets you associate a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> in a local <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> with the <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> of a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> in a remote <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>. You can also reference a table to itself to create linked lists.</p><p>In this example, the <code>species</code> <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> of the <code>pets</code> <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> is used to create a relationship to the <code>species</code> <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, so that we can access the price of a given pet.</p><p>Like everything else, you can set listeners on <a href="https://tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a> too.</p><p>Read more about <a href="https://tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a> in the <a href="https://tinybase.org/guides/using-relationships/">Using Relationships</a> guide.</p></section>
206
233
 
207
234
  ```js
208
235
  import {createRelationships} from 'tinybase';
@@ -227,7 +254,7 @@ console.log(
227
254
  relationships.destroy();
228
255
  ```
229
256
 
230
- <section><h2 id="set-checkpoints-for-an-undo-stack">Set checkpoints for an undo stack.</h2><p>A Checkpoints object lets you set checkpoints on a Store. Move forward and backward through them to create undo and redo functions.</p><p>In this example, we set a checkpoint, then sell one of the pets. Later, the pet is brought back to the shop, and we go back to that checkpoint to revert the store to its previous state.</p><p>Read more about Checkpoints in the <a href="https://beta.tinybase.org/guides/using-checkpoints/">Using Checkpoints</a> guide.</p></section>
257
+ <section><h2 id="set-checkpoints-for-an-undo-stack">Set checkpoints for an undo stack.</h2><p>A <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> object lets you set checkpoints on a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>. Move forward and backward through them to create undo and redo functions.</p><p>In this example, we set a checkpoint, then sell one of the pets. Later, the pet is brought back to the shop, and we go back to that checkpoint to revert the store to its previous state.</p><p>Read more about <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> in the <a href="https://tinybase.org/guides/using-checkpoints/">Using Checkpoints</a> guide.</p></section>
231
258
 
232
259
  ```js
233
260
  import {createCheckpoints} from 'tinybase';
@@ -246,7 +273,7 @@ console.log(store.getCell('pets', 'felix', 'sold'));
246
273
  // -> false
247
274
  ```
248
275
 
249
- <section><h2 id="type-definitions-orm-like-apis">Type definitions &amp; ORM-like APIs</h2><p>TinyBase has comprehensive type definitions, and even offers definitions that infer API types from the data schemas you apply.</p><p>Furthermore, you can easily create TypeScript <code>.d.ts</code> definitions that model your data and encourage type-safety when reading and writing data - as well as <code>.ts</code> implementations that provide ORM-like methods for your named tables.</p><p>Read more about type support in the <a href="https://beta.tinybase.org/guides/the-basics/tinybase-and-typescript/">TinyBase And TypeScript</a> guide.</p></section>
276
+ <section><h2 id="type-definitions-orm-like-apis">Type definitions &amp; ORM-like APIs</h2><p>TinyBase has comprehensive type definitions, and even offers definitions that infer API types from the data schemas you apply.</p><p>Furthermore, you can easily create TypeScript <code>.d.ts</code> definitions that model your data and encourage type-safety when reading and writing data - as well as <code>.ts</code> implementations that provide ORM-like methods for your named tables.</p><p>Read more about type support in the <a href="https://tinybase.org/guides/the-basics/tinybase-and-typescript/">TinyBase And TypeScript</a> guide.</p></section>
250
277
 
251
278
  ```js yolo
252
279
  const tools = createTools(store);
@@ -265,4 +292,4 @@ export const createShop: typeof createShopDecl = () => {
265
292
  };
266
293
  ```
267
294
 
268
- <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic store 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 ui-react 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://beta.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://beta.tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>5.3kB</td><td>52.3kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.7kB</td><td>129.8kB</td></tr><tr><th class="right"><a href="https://beta.tinybase.org/api/ui-react/">ui-react</a></th><td>4.6kB</td><td>48.1kB</td></tr><tr><th class="right"><a href="https://beta.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://beta.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,371</td><td>2,371</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,555</td><td>2,555</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,000</td><td>1,000</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,814</td></tr><tr><th class="right">Assertions</th><td colspan="3">31,994</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://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.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://beta.tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://beta.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://beta.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.3kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.7kB</td><td>129.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.1kB</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,371</td><td>2,371</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,555</td><td>2,555</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,000</td><td>1,000</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,816</td></tr><tr><th class="right">Assertions</th><td colspan="3">32,001</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
@@ -1,4 +1,4 @@
1
- <p>This is a reverse chronological list of the major <a href="https://beta.tinybase.org/">TinyBase</a> releases, with highlighted features.</p><h2 id="v5-0">v5.0</h2><p>We&#x27;re excited to announce this major release for <a href="https://beta.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://beta.tinybase.org/">TinyBase</a> Inspector is now in its own standalone ui-react-inspector module.</li><li><a href="https://beta.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 MergeableStore Type</h3><p>A key part of <a href="https://beta.tinybase.org/">TinyBase</a> v5.0 is the new mergeable-store module, which contains a subtype of Store - called MergeableStore - 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 getMergeableContent method on a MergeableStore is used to get the state of a store that can be merged into another. The applyMergeableChanges method will let you apply that to (another) store. The merge method is a convenience function to bidirectionally merge two stores together:</p>
1
+ <p>This is a reverse chronological list of the major <a href="https://tinybase.org/">TinyBase</a> releases, with highlighted features.</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>
2
2
 
3
3
  ```js
4
4
  import {createMergeableStore} from 'tinybase';
@@ -18,14 +18,14 @@ console.log(localStore2.getContent());
18
18
  // -> [{pets: {felix: {species: 'cat'}, fido: {species: 'dog'}}}, {}]
19
19
  ```
20
20
 
21
- <p>Please read the new <a href="https://beta.tinybase.org/guides/synchronization/using-a-mergeablestore/">Using A MergeableStore</a> guide for more details of how to use this important new API.</p><p>A MergeableStore can be persisted locally, just like a regular Store into file, local and session storage, and simple SQLite environments such as Expo and SQLite3. These allow you to save the state of a MergeableStore locally before it has had the chance to be synchronized online, for example.</p><p>Which leads us onto the next important feature in v5.0, allowing you to synchronize stores between systems...</p><h3 id="the-new-synchronizer-framework">The New Synchronizer Framework</h3><p>The v5.0 release also introduces the new concept of synchronization. Synchronizer objects implement a negotiation protocol that allows multiple MergeableStore objects to be merged together. This can be across a network, using WebSockets, for example:</p>
21
+ <p>Please read the new <a href="https://tinybase.org/guides/synchronization/using-a-mergeablestore/">Using A MergeableStore</a> guide for more details of how to use this important new API.</p><p>A <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> can be persisted locally, just like a regular <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> into file, local and session storage, and simple SQLite environments such as Expo and SQLite3. These allow you to save the state of a <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> locally before it has had the chance to be synchronized online, for example.</p><p>Which leads us onto the next important feature in v5.0, allowing you to synchronize stores between systems...</p><h3 id="the-new-synchronizer-framework">The New <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/"><code>Synchronizer</code></a> Framework</h3><p>The v5.0 release also introduces the new concept of synchronization. <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/"><code>Synchronizer</code></a> objects implement a negotiation protocol that allows multiple <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> objects to be merged together. This can be across a network, using WebSockets, for example:</p>
22
22
 
23
23
  ```js
24
24
  import {WebSocketServer, WebSocket} from 'ws';
25
25
  import {createWsServer} from 'tinybase/synchronizers/synchronizer-ws-server';
26
26
  import {createWsSynchronizer} from 'tinybase/synchronizers/synchronizer-ws-client';
27
27
 
28
- // On a server machine
28
+ // On a server machine:
29
29
  const server = createWsServer(new WebSocketServer({port: 8043}));
30
30
 
31
31
  // On the first client machine:
@@ -57,7 +57,7 @@ synchronizer2.destroy();
57
57
  server.destroy();
58
58
  ```
59
59
 
60
- <p>This release includes three types of Synchronizer:</p><ul><li>The WsSynchronizer uses WebSockets to communicate between different systems as shown above.</li><li>The BroadcastChannelSynchronizer uses the browser&#x27;s BroadcastChannel API to communicate between different tabs and workers.</li><li>The LocalSynchronizer demonstrates synchronization in memory on a single local system.</li></ul><p>Notice that the WsSynchronizer assumes that there exists a server that can forward requests to other WsSynchronizer systems. This can be created using the createWsServer function that takes a WebSocketServer as also shown above.</p><p>Please read the new <a href="https://beta.tinybase.org/guides/synchronization/using-a-synchronizer/">Using A Synchronizer</a> guide for more details of how to synchronize your data.</p><h3 id="improved-module-folder-structure">Improved Module Folder Structure</h3><p>We have previously found issues with legacy bundlers and other tools that didn&#x27;t fully support the new <code>exports</code> field in the module&#x27;s package.</p><p>To mitigate that, the <a href="https://beta.tinybase.org/">TinyBase</a> distribution now has a top-level folder structure that fully echoes the import paths, including signifiers for JavaScript versions, schema support, minification and so on.</p><p>Please read the comprehensive <a href="https://beta.tinybase.org/guides/the-basics/importing-tinybase/">Importing TinyBase</a> guide for more details of how to construct the correct import paths in v5.0.</p><h3 id="breaking-changes-in-v5-0">Breaking Changes in v5.0</h3><h4 id="module-file-structure">Module File Structure</h4><p>If you previously had <code>/lib/</code> in your import paths, you should remove it. You also do not have to explicitly specify whether you need the <code>cjs</code> version of <a href="https://beta.tinybase.org/">TinyBase</a> - if you are using a <code>require</code> rather than an <code>import</code>, you will get it automatically.</p><p>The non-minified version of the code is now default and you need to be explicit with you <em>want</em> minified code. Previously you would add <code>/debug</code> to the import path to get non-minified code, but now you add <code>/min</code> to the import path to get <em>minified</em> code.</p><h4 id="expo-sqlite-persister">Expo SQLite Persister</h4><p>Previously the persister-expo-sqlite module supported expo-sqlite v13 and the persister-expo-sqlite-next module supported their modern &#x27;next&#x27; package. In v5.0, the persister-expo-sqlite module only supports v14 and later, and the persister-expo-sqlite-next module has been removed.</p><h4 id="the-tinybase-inspector">The <a href="https://beta.tinybase.org/">TinyBase</a> Inspector</h4><p>Previously, the React-based inspector (then known as <code>StoreInspector</code>) resided in the debug version of the ui-react-dom module. It now lives in its own ui-react-inspector module (so that it can be used against non-debug code) and has been renamed to Inspector.</p><p>Please update your imports and rename the component when used, accordingly. See the API documentation for details, or the <a href="https://beta.tinybase.org/demos/ui-components/inspector/"><inspector></inspector></a>demo, for example.</p><h4 id="api-changes">API Changes</h4><p>The following changes have been made to the existing <a href="https://beta.tinybase.org/">TinyBase</a> API for consistency. These are less common parts of the API but should straightforward to correct if you are using them.</p><p>In the type definitions:</p><ul><li>The GetTransactionChanges and GetTransactionLog types have been removed.</li><li>The TransactionChanges type has been renamed as the Changes type.</li><li>The Changes type now uses <code>undefined</code> instead of <code>null</code> to indicate a Cell or Value that has been deleted or that was not present.</li><li>The TransactionLog type is now an array instead of a JavaScript object.</li></ul><p>In the Store interface:</p><ul><li>There is a new getTransactionChanges method and a new getTransactionLog method.</li><li>The setTransactionChanges method is renamed as the applyChanges method.</li><li>A DoRollback function no longer gets passed arguments. You can use the getTransactionChanges method and getTransactionLog method directly instead.</li><li>Similarly, a TransactionListener function no longer gets passed arguments.</li></ul><p>In the persisters module:</p><ul><li>The createCustomPersister function now takes a final optional boolean (<code>supportsMergeableStore</code>) to indicate that the Persister can support MergeableStore as well as Store objects.</li><li>A Persister&#x27;s load method and startAutoLoad method now take a Content object as one parameter, rather than Tables and Values as two.</li><li>If you create a custom Persister, the setPersisted method now receives changes made to a Store directly by reference, rather than via a callback. Similarly, the PersisterListener you register in your addPersisterListener implementation now takes Content and Changes objects directly rather than via a callback.</li><li>The broadcastTransactionChanges method in the persister-partykit-server module has been renamed to the broadcastChanges method.</li></ul><h2 id="v4-8">v4.8</h2><p>This release includes the new persister-powersync module, which provides a Persister for <a href="https://www.powersync.com/">PowerSync&#x27;s SQLite</a> database.</p><p>Much like the other SQLite persisters, use it by passing in a PowerSync instance to the createPowerSyncPersister function; something like:</p>
60
+ <p>This release includes three types of <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/"><code>Synchronizer</code></a>:</p><ul><li>The <a href="https://tinybase.org/api/synchronizer-ws-client/interfaces/synchronizer/wssynchronizer/"><code>WsSynchronizer</code></a> uses WebSockets to communicate between different systems as shown above.</li><li>The <a href="https://tinybase.org/api/synchronizer-broadcast-channel/interfaces/synchronizer/broadcastchannelsynchronizer/"><code>BroadcastChannelSynchronizer</code></a> uses the browser&#x27;s BroadcastChannel API to communicate between different tabs and workers.</li><li>The <a href="https://tinybase.org/api/synchronizer-local/interfaces/synchronizer/localsynchronizer/"><code>LocalSynchronizer</code></a> demonstrates synchronization in memory on a single local system.</li></ul><p>Notice that the <a href="https://tinybase.org/api/synchronizer-ws-client/interfaces/synchronizer/wssynchronizer/"><code>WsSynchronizer</code></a> assumes that there exists a server that can forward requests to other <a href="https://tinybase.org/api/synchronizer-ws-client/interfaces/synchronizer/wssynchronizer/"><code>WsSynchronizer</code></a> systems. This can be created using the <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> function that takes a WebSocketServer as also shown above.</p><p>Please read the new <a href="https://tinybase.org/guides/synchronization/using-a-synchronizer/">Using A Synchronizer</a> guide for more details of how to synchronize your data.</p><h3 id="improved-module-folder-structure">Improved Module Folder Structure</h3><p>We have previously found issues with legacy bundlers and other tools that didn&#x27;t fully support the new <code>exports</code> field in the module&#x27;s package.</p><p>To mitigate that, the <a href="https://tinybase.org/">TinyBase</a> distribution now has a top-level folder structure that fully echoes the import paths, including signifiers for JavaScript versions, schema support, minification and so on.</p><p>Please read the comprehensive <a href="https://tinybase.org/guides/the-basics/importing-tinybase/">Importing TinyBase</a> guide for more details of how to construct the correct import paths in v5.0.</p><h3 id="breaking-changes-in-v5-0">Breaking <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> in v5.0</h3><h4 id="module-file-structure">Module File Structure</h4><p>If you previously had <code>/lib/</code> in your import paths, you should remove it. You also do not have to explicitly specify whether you need the <code>cjs</code> version of <a href="https://tinybase.org/">TinyBase</a> - if you are using a <code>require</code> rather than an <code>import</code>, you will get it automatically.</p><p>The non-minified version of the code is now default and you need to be explicit with you <em>want</em> minified code. Previously you would add <code>/debug</code> to the import path to get non-minified code, but now you add <code>/min</code> to the import path to get <em>minified</em> code.</p><h4 id="expo-sqlite-persister">Expo SQLite <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a></h4><p>Previously the <a href="https://tinybase.org/api/persister-expo-sqlite/"><code>persister-expo-sqlite</code></a> module supported expo-sqlite v13 and the persister-expo-sqlite-next module supported their modern &#x27;next&#x27; package. In v5.0, the <a href="https://tinybase.org/api/persister-expo-sqlite/"><code>persister-expo-sqlite</code></a> module only supports v14 and later, and the persister-expo-sqlite-next module has been removed.</p><h4 id="the-tinybase-inspector">The <a href="https://tinybase.org/">TinyBase</a> Inspector</h4><p>Previously, the React-based inspector (then known as <code>StoreInspector</code>) resided in the debug version of the <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module. It now lives in its own <a href="https://tinybase.org/api/ui-react-inspector/"><code>ui-react-inspector</code></a> module (so that it can be used against non-debug code) and has been renamed to Inspector.</p><p>Please update your imports and rename the component when used, accordingly. See the API documentation for details, or the <a href="https://tinybase.org/demos/ui-components/inspector/"><inspector></inspector></a>demo, for example.</p><h4 id="api-changes">API <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a></h4><p>The following changes have been made to the existing <a href="https://tinybase.org/">TinyBase</a> API for consistency. These are less common parts of the API but should straightforward to correct if you are using them.</p><p>In the type definitions:</p><ul><li>The GetTransactionChanges and GetTransactionLog types have been removed.</li><li>The TransactionChanges type has been renamed as the <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> type.</li><li>The <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> type now uses <code>undefined</code> instead of <code>null</code> to indicate a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> that has been deleted or that was not present.</li><li>The <a href="https://tinybase.org/api/store/type-aliases/transaction/transactionlog/"><code>TransactionLog</code></a> type is now an array instead of a JavaScript object.</li></ul><p>In the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> interface:</p><ul><li>There is a new <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/gettransactionchanges/"><code>getTransactionChanges</code></a> method and a new getTransactionLog method.</li><li>The setTransactionChanges method is renamed as the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/applychanges/"><code>applyChanges</code></a> method.</li><li>A <a href="https://tinybase.org/api/store/type-aliases/callback/dorollback/"><code>DoRollback</code></a> function no longer gets passed arguments. You can use the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/gettransactionchanges/"><code>getTransactionChanges</code></a> method and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/gettransactionlog/"><code>getTransactionLog</code></a> method directly instead.</li><li>Similarly, a <a href="https://tinybase.org/api/store/type-aliases/listener/transactionlistener/"><code>TransactionListener</code></a> function no longer gets passed arguments.</li></ul><p>In the <a href="https://tinybase.org/api/persisters/"><code>persisters</code></a> module:</p><ul><li>The <a href="https://tinybase.org/api/persisters/functions/creation/createcustompersister/"><code>createCustomPersister</code></a> function now takes a final optional boolean (<code>supportsMergeableStore</code>) to indicate that the <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> can support <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> as well as <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> objects.</li><li>A <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a>&#x27;s <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/load/"><code>load</code></a> method and <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/startautoload/"><code>startAutoLoad</code></a> method now take a <a href="https://tinybase.org/api/store/type-aliases/store/content/"><code>Content</code></a> object as one parameter, rather than <a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a> and <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> as two.</li><li>If you create a custom <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a>, the setPersisted method now receives changes made to a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> directly by reference, rather than via a callback. Similarly, the <a href="https://tinybase.org/api/persisters/type-aliases/creation/persisterlistener/"><code>PersisterListener</code></a> you register in your addPersisterListener implementation now takes <a href="https://tinybase.org/api/store/type-aliases/store/content/"><code>Content</code></a> and <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> objects directly rather than via a callback.</li><li>The broadcastTransactionChanges method in the <a href="https://tinybase.org/api/persister-partykit-server/"><code>persister-partykit-server</code></a> module has been renamed to the broadcastChanges method.</li></ul><h2 id="v4-8">v4.8</h2><p>This release includes the new <a href="https://tinybase.org/api/persister-powersync/"><code>persister-powersync</code></a> module, which provides a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> for <a href="https://www.powersync.com/">PowerSync&#x27;s SQLite</a> database.</p><p>Much like the other SQLite persisters, use it by passing in a PowerSync instance to the <a href="https://tinybase.org/api/persister-powersync/functions/creation/createpowersyncpersister/"><code>createPowerSyncPersister</code></a> function; something like:</p>
61
61
 
62
62
  ```js yolo
63
63
  const powerSync = usePowerSync();
@@ -71,7 +71,7 @@ const persister = createPowerSyncPersister(store, powerSync, {
71
71
  });
72
72
  ```
73
73
 
74
- <p>A huge thank you to <a href="https://bndkt.com/">Benedikt Mueller</a> (<a href="https://github.com/bndkt">@bndkt</a>) for building out this functionality! And please provide feedback on how this new Persister works for you.</p><h2 id="v4-7">v4.7</h2><p>This release includes the new persister-libsql module, which provides a Persister for <a href="https://turso.tech/libsql">Turso&#x27;s LibSQL</a> database.</p><p>Use the Persister by passing in a reference to the LibSQL client to the createLibSQLPersister function; something like:</p>
74
+ <p>A huge thank you to <a href="https://bndkt.com/">Benedikt Mueller</a> (<a href="https://github.com/bndkt">@bndkt</a>) for building out this functionality! And please provide feedback on how this new <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> works for you.</p><h2 id="v4-7">v4.7</h2><p>This release includes the new <a href="https://tinybase.org/api/persister-libsql/"><code>persister-libsql</code></a> module, which provides a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> for <a href="https://turso.tech/libsql">Turso&#x27;s LibSQL</a> database.</p><p>Use the <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> by passing in a reference to the LibSQL client to the createLibSQLPersister function; something like:</p>
75
75
 
76
76
  ```js yolo
77
77
  const client = createClient({url: 'file:my.db'});
@@ -85,7 +85,7 @@ const persister = createLibSqlPersister(store, client, {
85
85
  });
86
86
  ```
87
87
 
88
- <p>This is the first version of this functionality, so please provide feedback on how it works for you!</p><h2 id="v4-6">v4.6</h2><p>This release includes the new persister-electric-sql module, which provides a Persister for <a href="https://electric-sql.com/">ElectricSQL</a> client databases.</p><p>Use the Persister by passing in a reference to the Electric client to the createElectricSqlPersister function; something like:</p>
88
+ <p>This is the first version of this functionality, so please provide feedback on how it works for you!</p><h2 id="v4-6">v4.6</h2><p>This release includes the new <a href="https://tinybase.org/api/persister-electric-sql/"><code>persister-electric-sql</code></a> module, which provides a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> for <a href="https://electric-sql.com/">ElectricSQL</a> client databases.</p><p>Use the <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> by passing in a reference to the Electric client to the <a href="https://tinybase.org/api/persister-electric-sql/functions/creation/createelectricsqlpersister/"><code>createElectricSqlPersister</code></a> function; something like:</p>
89
89
 
90
90
  ```js yolo
91
91
  const electric = await electrify(connection, schema, config);
@@ -99,14 +99,14 @@ const persister = createElectricSqlPersister(store, electric, {
99
99
  });
100
100
  ```
101
101
 
102
- <p>This release is accompanied by a <a href="https://github.com/tinyplex/tinybase-ts-react-electricsql">template project</a> to get started quickly with this integration. Enjoy!</p><h2 id="v4-5">v4.5</h2><p>This release includes the new persister-expo-sqlite-next module, which provides a Persister for the modern version of Expo&#x27;s <a href="https://docs.expo.dev/versions/latest/sdk/sqlite">SQLite</a> library, designated &#x27;next&#x27; as of November 2023. This API should be used if you are installing the <code>expo-sqlite/next</code> module.</p><p>Note that <a href="https://beta.tinybase.org/">TinyBase</a> support for the legacy version of Expo-SQLite (<code>expo-sqlite</code>) is still available in the persister-expo-sqlite module.</p><p>NB as of <a href="https://beta.tinybase.org/">TinyBase</a> v5.0, this is now the default and legacy support has been removed.</p><p>Thank you to Expo for providing this functionality!</p><h2 id="v4-4">v4.4</h2><p>This relatively straightforward release adds a selection of new listeners to the Store object, and their respective hooks. These are for listening to changes in the &#x27;existence&#x27; of entities rather than to their value. For example, the addHasTableListener method will let you listen for the presence (or not) of a specific table.</p><p>The full set of new existence-listening methods and hooks to work with this is as follows:</p><div class="table"><table><thead><tr><th>Existence of:</th><th>Add Listener</th><th>Hook</th><th>Add Listener Hook</th></tr></thead><tbody><tr><td>Tables</td><td>addHasTablesListener</td><td>useHasTables</td><td>useHasTablesListener</td></tr><tr><td>A Table</td><td>addHasTableListener</td><td>useHasTable</td><td>useHasTableListener</td></tr><tr><td>A Table Cell</td><td>addHasTableCellListener</td><td>useHasTableCell</td><td>useHasTableCellListener</td></tr><tr><td>A Row</td><td>addHasRowListener</td><td>useHasRow</td><td>useHasRowListener</td></tr><tr><td>A Cell</td><td>addHasCellListener</td><td>useHasCell</td><td>useHasCellListener</td></tr><tr><td>Values</td><td>addHasValuesListener</td><td>useHasValues</td><td>useHasValuesListener</td></tr><tr><td>A Value</td><td>addHasValueListener</td><td>useHasValue</td><td>useHasValueListener</td></tr></tbody></table></div><p>These methods may become particularly important in future versions of <a href="https://beta.tinybase.org/">TinyBase</a> that support <code>null</code> as valid Cells and Values.</p><h2 id="v4-3">v4.3</h2><p>We&#x27;re excited to announce <a href="https://beta.tinybase.org/">TinyBase</a> 4.3, which provides an integration with <a href="https://www.partykit.io/">PartyKit</a>, a cloud-based collaboration provider.</p><p>This allows you to enjoy the benefits of both a &quot;local-first&quot; architecture and a &quot;sharing-first&quot; platform. You can have structured data on the client with fast, reactive user experiences, but also benefit from cloud-based persistence and room-based collaboration.</p><p><img src="https://beta.tinybase.org/partykit.gif" alt="PartyKit" title="PartyKit"></p><p>This release includes two new modules:</p><ul><li>The persister-partykit-server module provides a server class for coordinating clients and persisting Store data to the PartyKit cloud.</li><li>The persister-partykit-client module provides the API to create connections to the server and a binding to your Store.</li></ul><p>A <a href="https://beta.tinybase.org/">TinyBase</a> server implementation on PartyKit can be as simple as this:</p>
102
+ <p>This release is accompanied by a <a href="https://github.com/tinyplex/tinybase-ts-react-electricsql">template project</a> to get started quickly with this integration. Enjoy!</p><h2 id="v4-5">v4.5</h2><p>This release includes the new persister-expo-sqlite-next module, which provides a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> for the modern version of Expo&#x27;s <a href="https://docs.expo.dev/versions/latest/sdk/sqlite">SQLite</a> library, designated &#x27;next&#x27; as of November 2023. This API should be used if you are installing the <code>expo-sqlite/next</code> module.</p><p>Note that <a href="https://tinybase.org/">TinyBase</a> support for the legacy version of Expo-SQLite (<code>expo-sqlite</code>) is still available in the <a href="https://tinybase.org/api/persister-expo-sqlite/"><code>persister-expo-sqlite</code></a> module.</p><p>NB as of <a href="https://tinybase.org/">TinyBase</a> v5.0, this is now the default and legacy support has been removed.</p><p>Thank you to Expo for providing this functionality!</p><h2 id="v4-4">v4.4</h2><p>This relatively straightforward release adds a selection of new listeners to the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> object, and their respective hooks. These are for listening to changes in the &#x27;existence&#x27; of entities rather than to their value. For example, the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhastablelistener/"><code>addHasTableListener</code></a> method will let you listen for the presence (or not) of a specific table.</p><p>The full set of new existence-listening methods and hooks to work with this is as follows:</p><div class="table"><table><thead><tr><th>Existence of:</th><th>Add Listener</th><th>Hook</th><th>Add Listener Hook</th></tr></thead><tbody><tr><td><a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhastableslistener/"><code>addHasTablesListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastables/"><code>useHasTables</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastableslistener/"><code>useHasTablesListener</code></a></td></tr><tr><td>A <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhastablelistener/"><code>addHasTableListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastable/"><code>useHasTable</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastablelistener/"><code>useHasTableListener</code></a></td></tr><tr><td>A <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhastablecelllistener/"><code>addHasTableCellListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastablecell/"><code>useHasTableCell</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehastablecelllistener/"><code>useHasTableCellListener</code></a></td></tr><tr><td>A <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhasrowlistener/"><code>addHasRowListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasrow/"><code>useHasRow</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasrowlistener/"><code>useHasRowListener</code></a></td></tr><tr><td>A <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhascelllistener/"><code>addHasCellListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehascell/"><code>useHasCell</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehascelllistener/"><code>useHasCellListener</code></a></td></tr><tr><td><a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhasvalueslistener/"><code>addHasValuesListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasvalues/"><code>useHasValues</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasvalueslistener/"><code>useHasValuesListener</code></a></td></tr><tr><td>A <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a></td><td><a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addhasvaluelistener/"><code>addHasValueListener</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasvalue/"><code>useHasValue</code></a></td><td><a href="https://tinybase.org/api/ui-react/functions/store-hooks/usehasvaluelistener/"><code>useHasValueListener</code></a></td></tr></tbody></table></div><p>These methods may become particularly important in future versions of <a href="https://tinybase.org/">TinyBase</a> that support <code>null</code> as valid Cells and <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>.</p><h2 id="v4-3">v4.3</h2><p>We&#x27;re excited to announce <a href="https://tinybase.org/">TinyBase</a> 4.3, which provides an integration with <a href="https://www.partykit.io/">PartyKit</a>, a cloud-based collaboration provider.</p><p>This allows you to enjoy the benefits of both a &quot;local-first&quot; architecture and a &quot;sharing-first&quot; platform. You can have structured data on the client with fast, reactive user experiences, but also benefit from cloud-based persistence and room-based collaboration.</p><p><img src="https://tinybase.org/partykit.gif" alt="PartyKit" title="PartyKit"></p><p>This release includes two new modules:</p><ul><li>The <a href="https://tinybase.org/api/persister-partykit-server/"><code>persister-partykit-server</code></a> module provides a server class for coordinating clients and persisting <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> data to the PartyKit cloud.</li><li>The <a href="https://tinybase.org/api/persister-partykit-client/"><code>persister-partykit-client</code></a> module provides the API to create connections to the server and a binding to your <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</li></ul><p>A <a href="https://tinybase.org/">TinyBase</a> server implementation on PartyKit can be as simple as this:</p>
103
103
 
104
104
  ```js yolo
105
105
  import {TinyBasePartyKitServer} from 'tinybase/persisters/persister-partykit-server';
106
106
  export default class extends TinyBasePartyKitServer {}
107
107
  ```
108
108
 
109
- <p>On the client, use the familiar Persister API, passing in a reference to a PartyKit socket object that&#x27;s been configured to connect to your server deployment and named room:</p>
109
+ <p>On the client, use the familiar <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> API, passing in a reference to a PartyKit socket object that&#x27;s been configured to connect to your server deployment and named room:</p>
110
110
 
111
111
  ```js yolo
112
112
  import {createPartyKitPersister} from 'tinybase/persisters/persister-partykit-client';
@@ -122,7 +122,7 @@ await persister.startAutoSave();
122
122
  await persister.startAutoLoad();
123
123
  ```
124
124
 
125
- <p>The load method and (gracefully failing) save method on this Persister use HTTPS to get or set full copies of the Store to the cloud. However, the auto-save and auto-load modes use a websocket to transmit subsequent incremental changes in either direction, making for performant sharing of state between clients.</p><p>See and try out this new collaboration functionality in the <a href="https://beta.tinybase.org/demos/todo-app/todo-app-v6-collaboration/">Todo App v6 (collaboration)</a> demo. This also emphasizes the few changes that need to be made to an existing app to make it instantly collaborative.</p><p>Also try out the <a href="https://github.com/tinyplex/tinybase-ts-react-partykit">tinybase-ts-react-partykit</a> template that gets you up and running with a PartyKit-enabled <a href="https://beta.tinybase.org/">TinyBase</a> app extremely quickly.</p><p>PartyKit supports retries for clients that go offline, and so the disconnected user experience is solid, out of the box. Learn more about configuring this behavior <a href="https://docs.partykit.io/reference/partysocket-api/#options">here</a>.</p><p>Note, however, that this release is not yet a full CRDT implementation: there is no clock synchronization and it is more &#x27;every write wins&#x27; than &#x27;last write wins&#x27;. However, since the transmitted updates are at single cell (or value) granularity, conflicts are minimized. More resilient replication is planned as this integration matures.</p><h2 id="v4-2">v4.2</h2><p>This release adds support for persisting <a href="https://beta.tinybase.org/">TinyBase</a> to a browser&#x27;s IndexedDB storage. You&#x27;ll need to import the new persister-indexed-db module, and call the createIndexedDbPersister function to create the IndexedDB Persister.</p><p>The API is the same as for all the other Persister APIs:</p>
125
+ <p>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/load/"><code>load</code></a> method and (gracefully failing) <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/save/save/"><code>save</code></a> method on this <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> use HTTPS to get or set full copies of the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> to the cloud. However, the auto-save and auto-load modes use a websocket to transmit subsequent incremental changes in either direction, making for performant sharing of state between clients.</p><p>See and try out this new collaboration functionality in the <a href="https://tinybase.org/demos/todo-app/todo-app-v6-collaboration/">Todo App v6 (collaboration)</a> demo. This also emphasizes the few changes that need to be made to an existing app to make it instantly collaborative.</p><p>Also try out the <a href="https://github.com/tinyplex/tinybase-ts-react-partykit">tinybase-ts-react-partykit</a> template that gets you up and running with a PartyKit-enabled <a href="https://tinybase.org/">TinyBase</a> app extremely quickly.</p><p>PartyKit supports retries for clients that go offline, and so the disconnected user experience is solid, out of the box. Learn more about configuring this behavior <a href="https://docs.partykit.io/reference/partysocket-api/#options">here</a>.</p><p>Note, however, that this release is not yet a full CRDT implementation: there is no clock synchronization and it is more &#x27;every write wins&#x27; than &#x27;last write wins&#x27;. However, since the transmitted updates are at single cell (or value) granularity, conflicts are minimized. More resilient replication is planned as this integration matures.</p><h2 id="v4-2">v4.2</h2><p>This release adds support for persisting <a href="https://tinybase.org/">TinyBase</a> to a browser&#x27;s IndexedDB storage. You&#x27;ll need to import the new <a href="https://tinybase.org/api/persister-indexed-db/"><code>persister-indexed-db</code></a> module, and call the <a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister/"><code>createIndexedDbPersister</code></a> function to create the IndexedDB <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a>.</p><p>The API is the same as for all the other <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> APIs:</p>
126
126
 
127
127
  ```js
128
128
  import {createIndexedDbPersister} from 'tinybase/persisters/persister-indexed-db';
@@ -152,7 +152,7 @@ await indexedDbPersister.save();
152
152
  indexedDbPersister.destroy();
153
153
  ```
154
154
 
155
- <p>Note that it is not possible to reactively detect changes to a browser&#x27;s IndexedDB storage. A polling technique is used to load underlying changes if you choose to &#x27;autoLoad&#x27; your data into <a href="https://beta.tinybase.org/">TinyBase</a>.</p><p>This release also upgrades Prettier to v3.0 which has a peer-dependency impact on the tools module. Please report any issues!</p><h2 id="v4-1">v4.1</h2><p>This release introduces the new ui-react-dom module. This provides pre-built components for tabular display of your data in a web application.</p><p><img src="https://beta.tinybase.org/ui-react-dom.webp" alt="A TinyBase DOM Component" title="A [TinyBase](/) DOM Component"></p><h3 id="new-dom-components">New DOM Components</h3><p>The following is the list of all the components released in v4.1:</p><div class="table"><table><thead><tr><th>Component</th><th>Purpose</th><th></th></tr></thead><tbody><tr><td>ValuesInHtmlTable</td><td>Renders Values.</td><td><a href="https://beta.tinybase.org/demos/ui-components/valuesinhtmltable">demo</a></td></tr><tr><td>TableInHtmlTable</td><td>Renders a Table.</td><td><a href="https://beta.tinybase.org/demos/ui-components/tableinhtmltable">demo</a></td></tr><tr><td>SortedTableInHtmlTable</td><td>Renders a sorted Table, with optional interactivity.</td><td><a href="https://beta.tinybase.org/demos/ui-components/sortedtableinhtmltable">demo</a></td></tr><tr><td>SliceInHtmlTable</td><td>Renders a Slice from an Index.</td><td><a href="https://beta.tinybase.org/demos/ui-components/sliceinhtmltable">demo</a></td></tr><tr><td>RelationshipInHtmlTable</td><td>Renders the local and remote Tables of a relationship</td><td><a href="https://beta.tinybase.org/demos/ui-components/relationshipinhtmltable">demo</a></td></tr><tr><td>ResultTableInHtmlTable</td><td>Renders a ResultTable.</td><td><a href="https://beta.tinybase.org/demos/ui-components/resulttableinhtmltable">demo</a></td></tr><tr><td>ResultSortedTableInHtmlTable</td><td>Renders a sorted ResultTable, with optional interactivity.</td><td><a href="https://beta.tinybase.org/demos/ui-components/resultsortedtableinhtmltable">demo</a></td></tr><tr><td>EditableCellView</td><td>Renders a Cell and lets you change its type and value.</td><td><a href="https://beta.tinybase.org/demos/ui-components/editablecellview">demo</a></td></tr><tr><td>EditableValueView</td><td>Renders a Value and lets you change its type and value.</td><td><a href="https://beta.tinybase.org/demos/ui-components/editablevalueview">demo</a></td></tr></tbody></table></div><p>These pre-built components are showcased in the <a href="https://beta.tinybase.org/demos/ui-components/">UI Components</a> demos. Using them should be very familiar if you have used the more abstract ui-react module:</p>
155
+ <p>Note that it is not possible to reactively detect changes to a browser&#x27;s IndexedDB storage. A polling technique is used to load underlying changes if you choose to &#x27;autoLoad&#x27; your data into <a href="https://tinybase.org/">TinyBase</a>.</p><p>This release also upgrades Prettier to v3.0 which has a peer-dependency impact on the <a href="https://tinybase.org/api/tools/"><code>tools</code></a> module. Please report any issues!</p><h2 id="v4-1">v4.1</h2><p>This release introduces the new <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module. This provides pre-built components for tabular display of your data in a web application.</p><p><img src="https://tinybase.org/ui-react-dom.webp" alt="A TinyBase DOM Component" title="A [TinyBase](/) DOM Component"></p><h3 id="new-dom-components">New DOM Components</h3><p>The following is the list of all the components released in v4.1:</p><div class="table"><table><thead><tr><th>Component</th><th>Purpose</th><th></th></tr></thead><tbody><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/store-components/valuesinhtmltable/"><code>ValuesInHtmlTable</code></a></td><td>Renders <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>.</td><td><a href="https://tinybase.org/demos/ui-components/valuesinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/store-components/tableinhtmltable/"><code>TableInHtmlTable</code></a></td><td>Renders a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>.</td><td><a href="https://tinybase.org/demos/ui-components/tableinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/store-components/sortedtableinhtmltable/"><code>SortedTableInHtmlTable</code></a></td><td>Renders a sorted <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, with optional interactivity.</td><td><a href="https://tinybase.org/demos/ui-components/sortedtableinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/indexes-components/sliceinhtmltable/"><code>SliceInHtmlTable</code></a></td><td>Renders a <a href="https://tinybase.org/api/indexes/type-aliases/concept/slice/"><code>Slice</code></a> from an <a href="https://tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a>.</td><td><a href="https://tinybase.org/demos/ui-components/sliceinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/relationships-components/relationshipinhtmltable/"><code>RelationshipInHtmlTable</code></a></td><td>Renders the local and remote <a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a> of a relationship</td><td><a href="https://tinybase.org/demos/ui-components/relationshipinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/queries-components/resulttableinhtmltable/"><code>ResultTableInHtmlTable</code></a></td><td>Renders a <a href="https://tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>.</td><td><a href="https://tinybase.org/demos/ui-components/resulttableinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/queries-components/resultsortedtableinhtmltable/"><code>ResultSortedTableInHtmlTable</code></a></td><td>Renders a sorted <a href="https://tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>, with optional interactivity.</td><td><a href="https://tinybase.org/demos/ui-components/resultsortedtableinhtmltable">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/store-components/editablecellview/"><code>EditableCellView</code></a></td><td>Renders a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> and lets you change its type and value.</td><td><a href="https://tinybase.org/demos/ui-components/editablecellview">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/store-components/editablevalueview/"><code>EditableValueView</code></a></td><td>Renders a <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> and lets you change its type and value.</td><td><a href="https://tinybase.org/demos/ui-components/editablevalueview">demo</a></td></tr></tbody></table></div><p>These pre-built components are showcased in the <a href="https://tinybase.org/demos/ui-components/">UI Components</a> demos. Using them should be very familiar if you have used the more abstract <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module:</p>
156
156
 
157
157
  ```jsx
158
158
  import React from 'react';
@@ -190,7 +190,7 @@ console.log(app.innerHTML);
190
190
  root.unmount();
191
191
  ```
192
192
 
193
- <p>The EditableCellView component and EditableValueView component are interactive input controls for updating Cell and Value content respectively. You can generally use them across your table views by adding the <code>editable</code> prop to your table component.</p><h3 id="the-new-inspector">The new Inspector</h3><p><img src="https://beta.tinybase.org/store-inspector.webp" alt="Inspector" title="Inspector"></p><p>The new Inspector component allows you to view, understand, and edit the content of a Store in a debug web environment. Try it out in most of the demos on the site, including the <a href="https://beta.tinybase.org/demos/movie-database/">Movie Database</a> demo, pictured. This requires a debug build of the new ui-react-dom module, which is now also included in the UMD distribution.</p><p>Also in this release, the getResultTableCellIds method and addResultTableCellIdsListener method have been added to the Queries object. The equivalent useResultTableCellIds hook and useResultTableCellIdsListener hook have also been added to ui-react module. A number of other minor React hooks have been added to support the components above.</p><p><a href="https://beta.tinybase.org/demos/">Demos</a> have been updated to demonstrate the ui-react-dom module and the Inspector component where appropriate.</p><p>(NB: Previous to v5.0, this component was called <code>StoreInspector</code>.)</p><h2 id="v4-0">v4.0</h2><p>This major release provides Persister modules that connect <a href="https://beta.tinybase.org/">TinyBase</a> to SQLite databases (in both browser and server contexts), and CRDT frameworks that can provide synchronization and local-first reconciliation:</p><div class="table"><table><thead><tr><th>Module</th><th>Function</th><th>Storage</th></tr></thead><tbody><tr><td>persister-sqlite3</td><td>createSqlite3Persister</td><td>SQLite in Node, via <a href="https://github.com/TryGhost/node-sqlite3">sqlite3</a></td></tr><tr><td>persister-sqlite-wasm</td><td>createSqliteWasmPersister</td><td>SQLite in a browser, via <a href="https://github.com/tomayac/sqlite-wasm">sqlite-wasm</a></td></tr><tr><td>persister-cr-sqlite-wasm</td><td>createCrSqliteWasmPersister</td><td>SQLite CRDTs, via <a href="https://github.com/vlcn-io/cr-sqlite">cr-sqlite-wasm</a></td></tr><tr><td>persister-yjs</td><td>createYjsPersister</td><td>Yjs CRDTs, via <a href="https://github.com/yjs/yjs">yjs</a></td></tr><tr><td>persister-automerge</td><td>createSqliteWasmPersister</td><td>Automerge CRDTs, via <a href="https://github.com/automerge/automerge-repo">automerge-repo</a></td></tr></tbody></table></div><p>See the <a href="https://beta.tinybase.org/guides/persistence/database-persistence/">Database Persistence</a> guide for details on how to work with SQLite databases, and the <a href="https://beta.tinybase.org/guides/schemas-and-persistence/synchronizing-data/">Synchronizing Data</a> guide for more complex synchronization with the CRDT frameworks.</p><p>Take a look at the <a href="https://github.com/tinyplex/vite-tinybase-ts-react-crsqlite">vite-tinybase-ts-react-crsqlite</a> template, for example, which demonstrates Vulcan&#x27;s cr-sqlite to provide persistence and synchronization via this technique.</p><h3 id="sqlite-databases">SQLite databases</h3><p>You can persist Store data to a database with either a JSON serialization or tabular mapping. (See the DatabasePersisterConfig documentation for more details).</p><p>For example, this creates a Persister object and saves and loads the Store to and from a local SQLite database. It uses an explicit tabular one-to-one mapping for the &#x27;pets&#x27; table:</p>
193
+ <p>The <a href="https://tinybase.org/api/ui-react-dom/functions/store-components/editablecellview/"><code>EditableCellView</code></a> component and <a href="https://tinybase.org/api/ui-react-dom/functions/store-components/editablevalueview/"><code>EditableValueView</code></a> component are interactive input controls for updating <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> and <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> content respectively. You can generally use them across your table views by adding the <code>editable</code> prop to your table component.</p><h3 id="the-new-inspector">The new Inspector</h3><p><img src="https://tinybase.org/store-inspector.webp" alt="Inspector" title="Inspector"></p><p>The new <a href="https://tinybase.org/api/ui-react-inspector/functions/development-components/inspector/"><code>Inspector</code></a> component allows you to view, understand, and edit the content of a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> in a debug web environment. Try it out in most of the demos on the site, including the <a href="https://tinybase.org/demos/movie-database/">Movie Database</a> demo, pictured. This requires a debug build of the new <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module, which is now also included in the UMD distribution.</p><p>Also in this release, the <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/result/getresulttablecellids/"><code>getResultTableCellIds</code></a> method and <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/listener/addresulttablecellidslistener/"><code>addResultTableCellIdsListener</code></a> method have been added to the <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> object. The equivalent <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresulttablecellids/"><code>useResultTableCellIds</code></a> hook and <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresulttablecellidslistener/"><code>useResultTableCellIdsListener</code></a> hook have also been added to <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module. A number of other minor React hooks have been added to support the components above.</p><p><a href="https://tinybase.org/demos/">Demos</a> have been updated to demonstrate the <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module and the <a href="https://tinybase.org/api/ui-react-inspector/functions/development-components/inspector/"><code>Inspector</code></a> component where appropriate.</p><p>(NB: Previous to v5.0, this component was called <code>StoreInspector</code>.)</p><h2 id="v4-0">v4.0</h2><p>This major release provides <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> modules that connect <a href="https://tinybase.org/">TinyBase</a> to SQLite databases (in both browser and server contexts), and CRDT frameworks that can provide synchronization and local-first reconciliation:</p><div class="table"><table><thead><tr><th>Module</th><th>Function</th><th>Storage</th></tr></thead><tbody><tr><td><a href="https://tinybase.org/api/persister-sqlite3/"><code>persister-sqlite3</code></a></td><td><a href="https://tinybase.org/api/persister-sqlite3/functions/creation/createsqlite3persister/"><code>createSqlite3Persister</code></a></td><td>SQLite in Node, via <a href="https://github.com/TryGhost/node-sqlite3">sqlite3</a></td></tr><tr><td><a href="https://tinybase.org/api/persister-sqlite-wasm/"><code>persister-sqlite-wasm</code></a></td><td><a href="https://tinybase.org/api/persister-sqlite-wasm/functions/creation/createsqlitewasmpersister/"><code>createSqliteWasmPersister</code></a></td><td>SQLite in a browser, via <a href="https://github.com/tomayac/sqlite-wasm">sqlite-wasm</a></td></tr><tr><td><a href="https://tinybase.org/api/persister-cr-sqlite-wasm/"><code>persister-cr-sqlite-wasm</code></a></td><td><a href="https://tinybase.org/api/persister-cr-sqlite-wasm/functions/creation/createcrsqlitewasmpersister/"><code>createCrSqliteWasmPersister</code></a></td><td>SQLite CRDTs, via <a href="https://github.com/vlcn-io/cr-sqlite">cr-sqlite-wasm</a></td></tr><tr><td><a href="https://tinybase.org/api/persister-yjs/"><code>persister-yjs</code></a></td><td><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister/"><code>createYjsPersister</code></a></td><td>Yjs CRDTs, via <a href="https://github.com/yjs/yjs">yjs</a></td></tr><tr><td><a href="https://tinybase.org/api/persister-automerge/"><code>persister-automerge</code></a></td><td><a href="https://tinybase.org/api/persister-sqlite-wasm/functions/creation/createsqlitewasmpersister/"><code>createSqliteWasmPersister</code></a></td><td>Automerge CRDTs, via <a href="https://github.com/automerge/automerge-repo">automerge-repo</a></td></tr></tbody></table></div><p>See the <a href="https://tinybase.org/guides/persistence/database-persistence/">Database Persistence</a> guide for details on how to work with SQLite databases, and the <a href="https://tinybase.org/guides/schemas-and-persistence/synchronizing-data/">Synchronizing Data</a> guide for more complex synchronization with the CRDT frameworks.</p><p>Take a look at the <a href="https://github.com/tinyplex/vite-tinybase-ts-react-crsqlite">vite-tinybase-ts-react-crsqlite</a> template, for example, which demonstrates Vulcan&#x27;s cr-sqlite to provide persistence and synchronization via this technique.</p><h3 id="sqlite-databases">SQLite databases</h3><p>You can persist <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> data to a database with either a JSON serialization or tabular mapping. (See the <a href="https://tinybase.org/api/persisters/type-aliases/configuration/databasepersisterconfig/"><code>DatabasePersisterConfig</code></a> documentation for more details).</p><p>For example, this creates a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> object and saves and loads the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> to and from a local SQLite database. It uses an explicit tabular one-to-one mapping for the &#x27;pets&#x27; table:</p>
194
194
 
195
195
  ```js
196
196
  import {createSqliteWasmPersister} from 'tinybase/persisters/persister-sqlite-wasm';
@@ -216,7 +216,7 @@ console.log(store.getTables());
216
216
  sqlitePersister.destroy();
217
217
  ```
218
218
 
219
- <h3 id="crdt-frameworks">CRDT Frameworks</h3><p>CRDTs allow complex reconciliation and synchronization between clients. Yjs and Automerge are two popular examples. The API should be familiar! The following will persist a <a href="https://beta.tinybase.org/">TinyBase</a> Store to a Yjs document:</p>
219
+ <h3 id="crdt-frameworks">CRDT Frameworks</h3><p>CRDTs allow complex reconciliation and synchronization between clients. Yjs and Automerge are two popular examples. The API should be familiar! The following will persist a <a href="https://tinybase.org/">TinyBase</a> <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> to a Yjs document:</p>
220
220
 
221
221
  ```js
222
222
  import {Doc} from 'yjs';
@@ -255,7 +255,7 @@ automergePersister.destroy();
255
255
  store.delTables();
256
256
  ```
257
257
 
258
- <h3 id="new-methods">New methods</h3><p>There are three new methods on the Store object. The getContent method lets you get the Store&#x27;s Tables and Values in one call. The corresponding setContent method lets you set them simultaneously.</p><p>The new setTransactionChanges method lets you replay TransactionChanges (received at the end of a transaction via listeners) into a Store, allowing you to take changes from one Store and apply them to another.</p><p>Persisters now provide a schedule method that lets you queue up asynchronous tasks, such as when persisting data that requires complex sequences of actions.</p><h3 id="breaking-changes">Breaking changes</h3><p>The way that data is provided to the DoRollback and TransactionListener callbacks at the end of a transaction has changed. Although previously they directly received content about changed Cell and Value content, they now receive functions that they can choose to call to receive that same data. This has a performance improvement, and your callback or listener can choose between concise TransactionChanges or more verbose TransactionLog structures for that data.</p><p>If you have build a custom persister, you will need to update your implementation. Most notably, the <code>setPersisted</code> function parameter is provided with a <code>getContent</code> function to get the content from the Store itself, rather than being passed pre-serialized JSON. It also receives information about the changes made during a transaction. The <code>getPersisted</code> function must return the content (or nothing) rather than JSON. <code>startListeningToPersisted</code> has been renamed <code>addPersisterListener</code>, and <code>stopListeningToPersisted</code> has been renamed <code>delPersisterListener</code>.</p><h2 id="v3-3">v3.3</h2><p>This release allows you to track the Cell Ids used across a whole Table, regardless of which Row they are in.</p><p>In a Table (particularly in a Store without a TablesSchema), different Rows can use different Cells. Consider this Store, where each pet has a different set of Cell Ids:</p>
258
+ <h3 id="new-methods">New methods</h3><p>There are three new methods on the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> object. The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getcontent/"><code>getContent</code></a> method lets you get the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>&#x27;s <a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a> and <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in one call. The corresponding <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setcontent/"><code>setContent</code></a> method lets you set them simultaneously.</p><p>The new setTransactionChanges method lets you replay TransactionChanges (received at the end of a transaction via listeners) into a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, allowing you to take changes from one <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> and apply them to another.</p><p>Persisters now provide a <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/schedule/"><code>schedule</code></a> method that lets you queue up asynchronous tasks, such as when persisting data that requires complex sequences of actions.</p><h3 id="breaking-changes">Breaking changes</h3><p>The way that data is provided to the <a href="https://tinybase.org/api/store/type-aliases/callback/dorollback/"><code>DoRollback</code></a> and <a href="https://tinybase.org/api/store/type-aliases/listener/transactionlistener/"><code>TransactionListener</code></a> callbacks at the end of a transaction has changed. Although previously they directly received content about changed <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> and <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> content, they now receive functions that they can choose to call to receive that same data. This has a performance improvement, and your callback or listener can choose between concise TransactionChanges or more verbose <a href="https://tinybase.org/api/store/type-aliases/transaction/transactionlog/"><code>TransactionLog</code></a> structures for that data.</p><p>If you have build a custom persister, you will need to update your implementation. Most notably, the <code>setPersisted</code> function parameter is provided with a <code>getContent</code> function to get the content from the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> itself, rather than being passed pre-serialized JSON. It also receives information about the changes made during a transaction. The <code>getPersisted</code> function must return the content (or nothing) rather than JSON. <code>startListeningToPersisted</code> has been renamed <code>addPersisterListener</code>, and <code>stopListeningToPersisted</code> has been renamed <code>delPersisterListener</code>.</p><h2 id="v3-3">v3.3</h2><p>This release allows you to track the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> used across a whole <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, regardless of which <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> they are in.</p><p>In a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> (particularly in a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> without a <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a>), different Rows can use different Cells. Consider this <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, where each pet has a different set of <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>:</p>
259
259
 
260
260
  ```js
261
261
  store.setTable('pets', {
@@ -265,7 +265,7 @@ store.setTable('pets', {
265
265
  });
266
266
  ```
267
267
 
268
- <p>Prior to v3.3, you could only get the Cell Ids used in each Row at a time (with the getCellIds method). But you can now use the getTableCellIds method to get the union of all the Cell Ids used across the Table:</p>
268
+ <p>Prior to v3.3, you could only get the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> used in each <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> at a time (with the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getcellids/"><code>getCellIds</code></a> method). But you can now use the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/gettablecellids/"><code>getTableCellIds</code></a> method to get the union of all the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> used across the <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>:</p>
269
269
 
270
270
  ```js
271
271
  console.log(store.getCellIds('pets', 'fido')); // previously available
@@ -275,7 +275,7 @@ console.log(store.getTableCellIds('pets')); // new in v3.3
275
275
  // -> ['species', 'friendly', 'legs']
276
276
  ```
277
277
 
278
- <p>You can register a listener to track the Cell Ids used across a Table with the new addTableCellIdsListener method. Use cases for this might include knowing which headers to render when displaying a sparse Table in a user interface, or synchronizing data with relational or column-oriented database system.</p><p>There is also a corresponding useTableCellIds hook in the optional ui-react module for accessing these Ids reactively, and a useTableCellIdsListener hook for more advanced purposes.</p><p>Note that the bookkeeping behind these new accessors and listeners is efficient and should not be slowed by the number of Rows in the Table.</p><p>This release also passes a getIdChanges function to every Id-related listener that, when called, returns information about the Id changes, both additions and removals, during a transaction. See the TableIdsListener type, for example.</p>
278
+ <p>You can register a listener to track the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> used across a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> with the new <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addtablecellidslistener/"><code>addTableCellIdsListener</code></a> method. Use cases for this might include knowing which headers to render when displaying a sparse <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> in a user interface, or synchronizing data with relational or column-oriented database system.</p><p>There is also a corresponding <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usetablecellids/"><code>useTableCellIds</code></a> hook in the optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module for accessing these <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> reactively, and a <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usetablecellidslistener/"><code>useTableCellIdsListener</code></a> hook for more advanced purposes.</p><p>Note that the bookkeeping behind these new accessors and listeners is efficient and should not be slowed by the number of Rows in the <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>.</p><p>This release also passes a getIdChanges function to every <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>-related listener that, when called, returns information about the <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> changes, both additions and removals, during a transaction. See the <a href="https://tinybase.org/api/store/type-aliases/listener/tableidslistener/"><code>TableIdsListener</code></a> type, for example.</p>
279
279
 
280
280
  ```js
281
281
  let listenerId = store.addRowIdsListener(
@@ -294,7 +294,7 @@ store.delRow('pets', 'felix');
294
294
  store.delListener(listenerId).delTables();
295
295
  ```
296
296
 
297
- <h2 id="v3-2">v3.2</h2><p>This release lets you add a listener to the start of a transaction, and detect that a set of changes are about to be made to a Store.</p><p>To use this, call the addStartTransactionListener method on your Store. The listener you add can itself mutate the data in the Store.</p><p>From this release onwards, listeners added with the existing addWillFinishTransactionListener method are also able to mutate data. <a href="https://beta.tinybase.org/guides/the-basics/transactions/">Transactions</a> added with the existing addDidFinishTransactionListener method <em>cannot</em> mutate data.</p>
297
+ <h2 id="v3-2">v3.2</h2><p>This release lets you add a listener to the start of a transaction, and detect that a set of changes are about to be made to a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</p><p>To use this, call the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addstarttransactionlistener/"><code>addStartTransactionListener</code></a> method on your <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>. The listener you add can itself mutate the data in the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</p><p>From this release onwards, listeners added with the existing <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addwillfinishtransactionlistener/"><code>addWillFinishTransactionListener</code></a> method are also able to mutate data. <a href="https://tinybase.org/guides/the-basics/transactions/">Transactions</a> added with the existing <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/adddidfinishtransactionlistener/"><code>addDidFinishTransactionListener</code></a> method <em>cannot</em> mutate data.</p>
298
298
 
299
299
  ```js
300
300
  const startListenerId = store.addStartTransactionListener(() => {
@@ -331,7 +331,7 @@ store
331
331
  store.delTables();
332
332
  ```
333
333
 
334
- <p>This release also fixes a bug where using the explicit startTransaction method <em>inside</em> another listener could create infinite recursion.</p><h2 id="v3-1">v3.1</h2><p>This new release adds a powerful schema-based type system to <a href="https://beta.tinybase.org/">TinyBase</a>.</p><p>If you define the shape and structure of your data with a TablesSchema or ValuesSchema, you can benefit from an enhanced developer experience when operating on it. For example:</p>
334
+ <p>This release also fixes a bug where using the explicit <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/starttransaction/"><code>startTransaction</code></a> method <em>inside</em> another listener could create infinite recursion.</p><h2 id="v3-1">v3.1</h2><p>This new release adds a powerful schema-based type system to <a href="https://tinybase.org/">TinyBase</a>.</p><p>If you define the shape and structure of your data with a <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a> or <a href="https://tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a>, you can benefit from an enhanced developer experience when operating on it. For example:</p>
335
335
 
336
336
  ```ts yolo
337
337
  // Import the 'with-schemas' definition:
@@ -349,7 +349,7 @@ store.setValues({employees: true}); // TypeScript error
349
349
  store.setValues({employees: 3, website: 'pets.com'}); // TypeScript error
350
350
  ```
351
351
 
352
- <p>The schema-based typing is used comprehensively throughout every module - from the core Store interface all the way through to the ui-react module. See the new <a href="https://beta.tinybase.org/guides/schemas/schema-based-typing/">Schema-Based Typing</a> guide for instructions on how to use it.</p><p>This now means that there are <em>three</em> progressive ways to use TypeScript with <a href="https://beta.tinybase.org/">TinyBase</a>:</p><ul><li>Basic Type Support (since v1.0)</li><li>Schema-based Typing (since v3.1)</li><li>ORM-like type definitions (since v2.2)</li></ul><p>These are each described in the new <a href="https://beta.tinybase.org/guides/the-basics/tinybase-and-typescript/">TinyBase And TypeScript</a> guide.</p><p>Also in v3.1, the ORM-like type definition generation in the tools module has been extended to emit ui-react module definitions.</p><p>Finally, v3.1.1 adds a <code>reuseRowIds</code> parameter to the addRow method and the useAddRowCallback hook. It defaults to <code>true</code>, for backwards compatibility, but if set to <code>false</code>, new Row Ids will not be reused unless the whole Table is deleted.</p><h2 id="v3-0">v3.0</h2><p>This major new release adds key/value store functionality to <a href="https://beta.tinybase.org/">TinyBase</a>. Alongside existing tabular data, it allows you to get, set, and listen to, individual Value items, each with a unique Id.</p>
352
+ <p>The schema-based typing is used comprehensively throughout every module - from the core <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> interface all the way through to the <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module. See the new <a href="https://tinybase.org/guides/schemas/schema-based-typing/">Schema-Based Typing</a> guide for instructions on how to use it.</p><p>This now means that there are <em>three</em> progressive ways to use TypeScript with <a href="https://tinybase.org/">TinyBase</a>:</p><ul><li>Basic Type Support (since v1.0)</li><li>Schema-based Typing (since v3.1)</li><li>ORM-like type definitions (since v2.2)</li></ul><p>These are each described in the new <a href="https://tinybase.org/guides/the-basics/tinybase-and-typescript/">TinyBase And TypeScript</a> guide.</p><p>Also in v3.1, the ORM-like type definition generation in the <a href="https://tinybase.org/api/tools/"><code>tools</code></a> module has been extended to emit <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module definitions.</p><p>Finally, v3.1.1 adds a <code>reuseRowIds</code> parameter to the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/addrow/"><code>addRow</code></a> method and the <a href="https://tinybase.org/api/ui-react/functions/store-hooks/useaddrowcallback/"><code>useAddRowCallback</code></a> hook. It defaults to <code>true</code>, for backwards compatibility, but if set to <code>false</code>, new <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> will not be reused unless the whole <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> is deleted.</p><h2 id="v3-0">v3.0</h2><p>This major new release adds key/value store functionality to <a href="https://tinybase.org/">TinyBase</a>. Alongside existing tabular data, it allows you to get, set, and listen to, individual <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> items, each with a unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>.</p>
353
353
 
354
354
  ```js
355
355
  store.setValues({employees: 3, open: true});
@@ -369,7 +369,7 @@ store.setValue('employees', 4);
369
369
  store.delListener(listenerId).delValues();
370
370
  ```
371
371
 
372
- <p><a href="https://beta.tinybase.org/guides/">Guides</a> and documentation have been fully updated, and certain demos - such as the <a href="https://beta.tinybase.org/demos/todo-app/todo-app-v2-indexes/">Todo App v2 (indexes)</a> demo, and the <a href="https://beta.tinybase.org/demos/countries/">Countries</a> demo - have been updated to use this new functionality.</p><p>If you use the optional ui-react module with <a href="https://beta.tinybase.org/">TinyBase</a>, v3.0 now uses and expects React v18.</p><p>In terms of core API changes in v3.0, there are some minor breaking changes (see below), but the majority of the alterations are additions.</p><p>The Store object gains the following:</p><ul><li>The setValues method, setPartialValues method, and setValue method, to set keyed value data into the Store.</li><li>The getValues method, getValueIds method, and getValue method, to get keyed value data out of the Store.</li><li>The delValues method and delValue method for removing keyed value data.</li><li>The addValuesListener method, addValueIdsListener method, addValueListener method, and addInvalidValueListener method, for listening to changes to keyed value data.</li><li>The hasValues method, hasValue method, and forEachValue method, for existence and enumeration purposes.</li><li>The getTablesJson method, getValuesJson method, setTablesJson method, and setValuesJson method, for reading and writing tabular and keyed value data to and from a JSON string. Also see below.</li><li>The getTablesSchemaJson method, getValuesSchemaJson method, setTablesSchema method, setValuesSchema method, delTablesSchema method, and delValuesSchema method, for reading and writing tabular and keyed value schemas for the Store. Also see below.</li></ul><p>The following types have been added to the store module:</p><ul><li>Values, Value, and ValueOrUndefined, representing keyed value data in a Store.</li><li>ValueListener and InvalidValueListener, to describe functions used to listen to (valid or invalid) changes to a Value.</li><li>ValuesSchema and ValueSchema, to describe the keyed Values that can be set in a Store and their types.</li><li>ValueCallback, MapValue, ChangedValues, and InvalidValues, which also correspond to their &#x27;Cell&#x27; equivalents.</li></ul><p>Additionally:</p><ul><li>The persisters&#x27; load method and startAutoLoad method take an optional <code>initialValues</code> parameter for setting Values when a persisted Store is bootstrapped.</li><li>The Checkpoints module will undo and redo changes to keyed values in the same way they do for tabular data.</li><li>The tools module provides a getStoreValuesSchema method for inferring value-based schemas. The getStoreApi method and getPrettyStoreApi method now also provides an ORM-like code-generated API for schematized key values.</li></ul><p>All attempts have been made to provide backwards compatibility and/or easy upgrade paths.</p><p>In previous versions, getJson method would get a JSON serialization of the Store&#x27;s tabular data. That functionality is now provided by the getTablesJson method, and the getJson method instead now returns a two-part array containing the tabular data and the keyed value data.</p><p>Similarly, the getSchemaJson method used to return the tabular schema, now provided by the getTablesSchemaJson method. The getSchemaJson method instead now returns a two-part array of tabular schema and the keyed value schema.</p><p>The setJson method used to take a serialization of just the tabular data object. That&#x27;s now provided by the setTablesJson method, and the setJson method instead expects a two-part array containing the tabular data and the keyed value data (as emitted by the getJson method). However, for backwards compatibility, if the setJson method is passed an object, it <em>will</em> set the tabular data, as it did prior to v3.0.</p><p>Along similar lines, the setSchema method&#x27;s previous behavior is now provided by the setTablesSchema method. The setSchema method now takes two arguments, the second of which is optional, also aiding backward compatibility. The delSchema method removes both types of schema.</p><h2 id="v2-2">v2.2</h2><p>This release includes a new tools module. These tools are not intended for production use, but are instead to be used as part of your engineering workflow to perform tasks like generating APIs from schemas, or schemas from data. For example:</p>
372
+ <p><a href="https://tinybase.org/guides/">Guides</a> and documentation have been fully updated, and certain demos - such as the <a href="https://tinybase.org/demos/todo-app/todo-app-v2-indexes/">Todo App v2 (indexes)</a> demo, and the <a href="https://tinybase.org/demos/countries/">Countries</a> demo - have been updated to use this new functionality.</p><p>If you use the optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module with <a href="https://tinybase.org/">TinyBase</a>, v3.0 now uses and expects React v18.</p><p>In terms of core API changes in v3.0, there are some minor breaking changes (see below), but the majority of the alterations are additions.</p><p>The <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> object gains the following:</p><ul><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setvalues/"><code>setValues</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setpartialvalues/"><code>setPartialValues</code></a> method, and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setvalue/"><code>setValue</code></a> method, to set keyed value data into the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getvalues/"><code>getValues</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getvalueids/"><code>getValueIds</code></a> method, and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getvalue/"><code>getValue</code></a> method, to get keyed value data out of the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/deleter/delvalues/"><code>delValues</code></a> method and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/deleter/delvalue/"><code>delValue</code></a> method for removing keyed value data.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addvalueslistener/"><code>addValuesListener</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addvalueidslistener/"><code>addValueIdsListener</code></a> method, addValueListener method, and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addinvalidvaluelistener/"><code>addInvalidValueListener</code></a> method, for listening to changes to keyed value data.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/hasvalues/"><code>hasValues</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/hasvalue/"><code>hasValue</code></a> method, and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/iterator/foreachvalue/"><code>forEachValue</code></a> method, for existence and enumeration purposes.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getvaluesjson/"><code>getValuesJson</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setvaluesjson/"><code>setValuesJson</code></a> method, for reading and writing tabular and keyed value data to and from a JSON string. Also see below.</li><li>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getvaluesschemajson/"><code>getValuesSchemaJson</code></a> method, setTablesSchema method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setvaluesschema/"><code>setValuesSchema</code></a> method, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/deleter/deltablesschema/"><code>delTablesSchema</code></a> method, and delValuesSchema method, for reading and writing tabular and keyed value schemas for the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>. Also see below.</li></ul><p>The following types have been added to the <a href="https://tinybase.org/api/store/"><code>store</code></a> module:</p><ul><li><a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>, <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>, and <a href="https://tinybase.org/api/store/type-aliases/store/valueorundefined/"><code>ValueOrUndefined</code></a>, representing keyed value data in a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>.</li><li><a href="https://tinybase.org/api/store/type-aliases/listener/valuelistener/"><code>ValueListener</code></a> and <a href="https://tinybase.org/api/store/type-aliases/listener/invalidvaluelistener/"><code>InvalidValueListener</code></a>, to describe functions used to listen to (valid or invalid) changes to a <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>.</li><li><a href="https://tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> and <a href="https://tinybase.org/api/store/type-aliases/schema/valueschema/"><code>ValueSchema</code></a>, to describe the keyed <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> that can be set in a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> and their types.</li><li><a href="https://tinybase.org/api/store/type-aliases/callback/valuecallback/"><code>ValueCallback</code></a>, <a href="https://tinybase.org/api/store/type-aliases/callback/mapvalue/"><code>MapValue</code></a>, <a href="https://tinybase.org/api/store/type-aliases/transaction/changedvalues/"><code>ChangedValues</code></a>, and <a href="https://tinybase.org/api/store/type-aliases/transaction/invalidvalues/"><code>InvalidValues</code></a>, which also correspond to their &#x27;<a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>&#x27; equivalents.</li></ul><p>Additionally:</p><ul><li>The persisters&#x27; <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/load/"><code>load</code></a> method and <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/startautoload/"><code>startAutoLoad</code></a> method take an optional <code>initialValues</code> parameter for setting <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> when a persisted <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> is bootstrapped.</li><li>The <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> module will undo and redo changes to keyed values in the same way they do for tabular data.</li><li>The <a href="https://tinybase.org/api/tools/"><code>tools</code></a> module provides a <a href="https://tinybase.org/api/tools/interfaces/tools/tools/methods/modelling/getstorevaluesschema/"><code>getStoreValuesSchema</code></a> method for inferring value-based schemas. The <a href="https://tinybase.org/api/tools/interfaces/tools/tools/methods/modelling/getstoreapi/"><code>getStoreApi</code></a> method and <a href="https://tinybase.org/api/tools/interfaces/tools/tools/methods/modelling/getprettystoreapi/"><code>getPrettyStoreApi</code></a> method now also provides an ORM-like code-generated API for schematized key values.</li></ul><p>All attempts have been made to provide backwards compatibility and/or easy upgrade paths.</p><p>In previous versions, <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getjson/"><code>getJson</code></a> method would get a JSON serialization of the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>&#x27;s tabular data. That functionality is now provided by the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, and the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getjson/"><code>getJson</code></a> method instead now returns a two-part array containing the tabular data and the keyed value data.</p><p>Similarly, the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getschemajson/"><code>getSchemaJson</code></a> method used to return the tabular schema, now provided by the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method. The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getschemajson/"><code>getSchemaJson</code></a> method instead now returns a two-part array of tabular schema and the keyed value schema.</p><p>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setjson/"><code>setJson</code></a> method used to take a serialization of just the tabular data object. That&#x27;s now provided by the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setjson/"><code>setJson</code></a> method instead expects a two-part array containing the tabular data and the keyed value data (as emitted by the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getjson/"><code>getJson</code></a> method). However, for backwards compatibility, if the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setjson/"><code>setJson</code></a> method is passed an object, it <em>will</em> set the tabular data, as it did prior to v3.0.</p><p>Along similar lines, the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setschema/"><code>setSchema</code></a> method&#x27;s previous behavior is now provided by the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/settablesschema/"><code>setTablesSchema</code></a> method. The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/setter/setschema/"><code>setSchema</code></a> method now takes two arguments, the second of which is optional, also aiding backward compatibility. The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/deleter/delschema/"><code>delSchema</code></a> method removes both types of schema.</p><h2 id="v2-2">v2.2</h2><p>This release includes a new <a href="https://tinybase.org/api/tools/"><code>tools</code></a> module. These tools are not intended for production use, but are instead to be used as part of your engineering workflow to perform tasks like generating APIs from schemas, or schemas from data. For example:</p>
373
373
 
374
374
  ```js
375
375
  import {createTools} from 'tinybase/tools';
@@ -409,7 +409,7 @@ npx tinybase getStoreApi schema.json shop api
409
409
  Implementation: [...]/api/shop.ts
410
410
  ```
411
411
 
412
- <p>Finally, the tools module also provides ways to track the overall size and structure of a Store for use while debugging.</p><h2 id="v2-1">v2.1</h2><p>This release allows you to create indexes where a single Row Id can exist in multiple slices. You can utilize this to build simple keyword searches, for example.</p><p>Simply provide a custom getSliceIdOrIds function in the setIndexDefinition method that returns an array of Slice Ids, rather than a single Id:</p>
412
+ <p>Finally, the <a href="https://tinybase.org/api/tools/"><code>tools</code></a> module also provides ways to track the overall size and structure of a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> for use while debugging.</p><h2 id="v2-1">v2.1</h2><p>This release allows you to create indexes where a single <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> can exist in multiple slices. You can utilize this to build simple keyword searches, for example.</p><p>Simply provide a custom getSliceIdOrIds function in the <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/methods/configuration/setindexdefinition/"><code>setIndexDefinition</code></a> method that returns an array of <a href="https://tinybase.org/api/indexes/type-aliases/concept/slice/"><code>Slice</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>, rather than a single <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>:</p>
413
413
 
414
414
  ```js
415
415
  import {createIndexes} from 'tinybase';
@@ -433,7 +433,7 @@ console.log(indexes.getSliceRowIds('containsLetter', 'x'));
433
433
  // -> ['felix', 'rex']
434
434
  ```
435
435
 
436
- <p>This functionality is showcased in the <a href="https://beta.tinybase.org/demos/word-frequencies/">Word Frequencies</a> demo if you would like to see it in action.</p><h2 id="v2-0">v2.0</h2><p><strong>Announcing the next major version of <a href="https://beta.tinybase.org/">TinyBase</a> 2.0!</strong> This is an exciting release that evolves <a href="https://beta.tinybase.org/">TinyBase</a> towards becoming a reactive, relational data store, complete with querying, sorting, and pagination. Here are a few of the highlights...</p><h3 id="query-engine">Query Engine</h3><p>The <a href="https://beta.tinybase.org/guides/making-queries/using-queries/">flagship feature</a> of this release is the new queries module. This allows you to build expressive queries against your data with a SQL-adjacent API that we&#x27;ve cheekily called <a href="https://beta.tinybase.org/guides/making-queries/tinyql/">TinyQL</a>. The query engine lets you select, join, filter, group, sort and paginate data. And of course, it&#x27;s all reactive!</p><p>The best way to see the power of this new engine is with the two new demos we&#x27;ve included this release:</p><p><img src="https://beta.tinybase.org/car-analysis.webp" alt="Thumbnail of demo" title="Thumbnail of demo"> The <a href="https://beta.tinybase.org/demos/car-analysis/">Car Analysis</a> demo showcases the analytical query capabilities of <a href="https://beta.tinybase.org/">TinyBase</a> v2.0, grouping and sorting dimensional data for lightweight analytical usage, graphing, and tabular display. <em><a href="https://beta.tinybase.org/demos/car-analysis/">Try this demo here</a>.</em></p><p><img src="https://beta.tinybase.org/movie-database.webp" alt="Thumbnail of demo" title="Thumbnail of demo"> The <a href="https://beta.tinybase.org/demos/movie-database/">Movie Database</a> demo showcases the relational query capabilities of <a href="https://beta.tinybase.org/">TinyBase</a> v2.0, joining together information about movies, directors, and actors from across multiple source tables. <em><a href="https://beta.tinybase.org/demos/movie-database/">Try this demo here</a>.</em></p><h3 id="sorting-and-pagination">Sorting and Pagination</h3><p>To complement the query engine, you can now sort and paginate Row Ids. This makes it very easy to build grid-like user interfaces (also shown in the demos above). To achieve this, the Store now includes the getSortedRowIds method (and the addSortedRowIdsListener method for reactivity), and the Queries object includes the equivalent getResultSortedRowIds method and addResultSortedRowIdsListener method.</p><p>These are also exposed in the optional ui-react module via the useSortedRowIds hook, the useResultSortedRowIds hook, the SortedTableView component and the ResultSortedTableView component, and so on.</p><h3 id="queries-in-the-ui-react-module">Queries in the ui-react module</h3><p>The v2.0 query functionality is fully supported by the ui-react module (to match support for Store, Metrics, Indexes, and Relationship objects). The useCreateQueries hook memoizes the creation of app- or component-wide Query objects; and the useResultTable hook, useResultRow hook, useResultCell hook (and so on) let you bind you component to the results of a query.</p><p>This is, of course, supplemented with higher-level components: the ResultTableView component, the ResultRowView component, the ResultCellView component, and so on. See the <a href="https://beta.tinybase.org/guides/using-queries/building-a-ui-with-queries/">Building A UI With Queries</a> guide for more details.</p><h3 id="it-s-a-big-release">It&#x27;s a big release!</h3><p>Thank you for all your support as we brought this important new release to life, and we hope you enjoy using it as much as we did building it. Please provide feedback via <a href="https://github.com/tinyplex/tinybase">Github</a> and <a href="https://twitter.com/tinybasejs">Twitter</a>!</p><h2 id="v1-3">v1.3</h2><p>Adds support for explicit transaction start and finish methods, as well as listeners for transactions finishing.</p><p>The startTransaction method and finishTransaction method allow you to explicitly enclose a transaction that will make multiple mutations to the Store, buffering all calls to the relevant listeners until it completes when you call the finishTransaction method.</p><p>Unlike the transaction method, this approach is useful when you have a more &#x27;open-ended&#x27; transaction, such as one containing mutations triggered from other events that are asynchronous or not occurring inline to your code. You must remember to also call the finishTransaction method explicitly when the transaction is started with the startTransaction method, of course.</p>
436
+ <p>This functionality is showcased in the <a href="https://tinybase.org/demos/word-frequencies/">Word Frequencies</a> demo if you would like to see it in action.</p><h2 id="v2-0">v2.0</h2><p><strong>Announcing the next major version of <a href="https://tinybase.org/">TinyBase</a> 2.0!</strong> This is an exciting release that evolves <a href="https://tinybase.org/">TinyBase</a> towards becoming a reactive, relational data store, complete with querying, sorting, and pagination. Here are a few of the highlights...</p><h3 id="query-engine">Query Engine</h3><p>The <a href="https://tinybase.org/guides/making-queries/using-queries/">flagship feature</a> of this release is the new <a href="https://tinybase.org/api/queries/"><code>queries</code></a> module. This allows you to build expressive queries against your data with a SQL-adjacent API that we&#x27;ve cheekily called <a href="https://tinybase.org/guides/making-queries/tinyql/">TinyQL</a>. The query engine lets you select, join, filter, group, sort and paginate data. And of course, it&#x27;s all reactive!</p><p>The best way to see the power of this new engine is with the two new demos we&#x27;ve included this release:</p><p><img src="https://tinybase.org/car-analysis.webp" alt="Thumbnail of demo" title="Thumbnail of demo"> The <a href="https://tinybase.org/demos/car-analysis/">Car Analysis</a> demo showcases the analytical query capabilities of <a href="https://tinybase.org/">TinyBase</a> v2.0, grouping and sorting dimensional data for lightweight analytical usage, graphing, and tabular display. <em><a href="https://tinybase.org/demos/car-analysis/">Try this demo here</a>.</em></p><p><img src="https://tinybase.org/movie-database.webp" alt="Thumbnail of demo" title="Thumbnail of demo"> The <a href="https://tinybase.org/demos/movie-database/">Movie Database</a> demo showcases the relational query capabilities of <a href="https://tinybase.org/">TinyBase</a> v2.0, joining together information about movies, directors, and actors from across multiple source tables. <em><a href="https://tinybase.org/demos/movie-database/">Try this demo here</a>.</em></p><h3 id="sorting-and-pagination">Sorting and Pagination</h3><p>To complement the query engine, you can now sort and paginate <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>. This makes it very easy to build grid-like user interfaces (also shown in the demos above). To achieve this, the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> now includes the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/getter/getsortedrowids/"><code>getSortedRowIds</code></a> method (and the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addsortedrowidslistener/"><code>addSortedRowIdsListener</code></a> method for reactivity), and the <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> object includes the equivalent <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/result/getresultsortedrowids/"><code>getResultSortedRowIds</code></a> method and <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/listener/addresultsortedrowidslistener/"><code>addResultSortedRowIdsListener</code></a> method.</p><p>These are also exposed in the optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module via the <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usesortedrowids/"><code>useSortedRowIds</code></a> hook, the <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresultsortedrowids/"><code>useResultSortedRowIds</code></a> hook, the <a href="https://tinybase.org/api/ui-react/functions/store-components/sortedtableview/"><code>SortedTableView</code></a> component and the <a href="https://tinybase.org/api/ui-react/functions/queries-components/resultsortedtableview/"><code>ResultSortedTableView</code></a> component, and so on.</p><h3 id="queries-in-the-ui-react-module"><a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> in the <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module</h3><p>The v2.0 query functionality is fully supported by the <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module (to match support for <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, <a href="https://tinybase.org/api/metrics/interfaces/metrics/metrics/"><code>Metrics</code></a>, <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a>, and <a href="https://tinybase.org/api/relationships/type-aliases/concept/relationship/"><code>Relationship</code></a> objects). The <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/usecreatequeries/"><code>useCreateQueries</code></a> hook memoizes the creation of app- or component-wide Query objects; and the <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresulttable/"><code>useResultTable</code></a> hook, <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresultrow/"><code>useResultRow</code></a> hook, <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useresultcell/"><code>useResultCell</code></a> hook (and so on) let you bind you component to the results of a query.</p><p>This is, of course, supplemented with higher-level components: the <a href="https://tinybase.org/api/ui-react/functions/queries-components/resulttableview/"><code>ResultTableView</code></a> component, the <a href="https://tinybase.org/api/ui-react/functions/queries-components/resultrowview/"><code>ResultRowView</code></a> component, the <a href="https://tinybase.org/api/ui-react/functions/queries-components/resultcellview/"><code>ResultCellView</code></a> component, and so on. See the <a href="https://tinybase.org/guides/using-queries/building-a-ui-with-queries/">Building A UI With Queries</a> guide for more details.</p><h3 id="it-s-a-big-release">It&#x27;s a big release!</h3><p>Thank you for all your support as we brought this important new release to life, and we hope you enjoy using it as much as we did building it. Please provide feedback via <a href="https://github.com/tinyplex/tinybase">Github</a> and <a href="https://twitter.com/tinybasejs">Twitter</a>!</p><h2 id="v1-3">v1.3</h2><p>Adds support for explicit transaction start and finish methods, as well as listeners for transactions finishing.</p><p>The <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/starttransaction/"><code>startTransaction</code></a> method and <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/finishtransaction/"><code>finishTransaction</code></a> method allow you to explicitly enclose a transaction that will make multiple mutations to the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, buffering all calls to the relevant listeners until it completes when you call the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/finishtransaction/"><code>finishTransaction</code></a> method.</p><p>Unlike the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/transaction/"><code>transaction</code></a> method, this approach is useful when you have a more &#x27;open-ended&#x27; transaction, such as one containing mutations triggered from other events that are asynchronous or not occurring inline to your code. You must remember to also call the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/finishtransaction/"><code>finishTransaction</code></a> method explicitly when the transaction is started with the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/starttransaction/"><code>startTransaction</code></a> method, of course.</p>
437
437
 
438
438
  ```js
439
439
  store.setTables({pets: {fido: {species: 'dog'}}});
@@ -446,4 +446,4 @@ store.finishTransaction();
446
446
  // -> 'Fido changed'
447
447
  ```
448
448
 
449
- <p>In addition, see the addWillFinishTransactionListener method and the addDidFinishTransactionListener method for details around listening to transactions completing.</p><p>Together, this release allows stores to couple their transaction life-cycles together, which we need for the query engine.</p><p>Note: this API was updated to be more comprehensive in v4.0.</p><h2 id="v1-2">v1.2</h2><p>This adds a way to revert transactions if they have not met certain conditions.</p><p>When using the transaction method, you can provide an optional <code>doRollback</code> callback which should return true if you want to revert the whole transaction at its conclusion.</p><p>The callback is provided with two objects, <code>changedCells</code> and <code>invalidCells</code>, which list all the net changes and invalid attempts at changes that were made during the transaction. You will most likely use the contents of those objects to decide whether the transaction should be rolled back.</p><p>Note: this API was updated to be more comprehensive in v4.0.</p><h2 id="v1-1">v1.1</h2><p>This release allows you to listen to invalid data being added to a Store, allowing you to gracefully handle errors, rather than them failing silently.</p><p>There is a new listener type InvalidCellListener and a addInvalidCellListener method in the Store interface.</p><p>These allow you to keep track of failed attempts to update the Store with invalid Cell data. These listeners can also be mutators, allowing you to address any failed writes programmatically.</p><p>For more information, please see the addInvalidCellListener method documentation. In particular, this explains how this listener behaves for a Store with a TablesSchema.</p>
449
+ <p>In addition, see the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addwillfinishtransactionlistener/"><code>addWillFinishTransactionListener</code></a> method and the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/adddidfinishtransactionlistener/"><code>addDidFinishTransactionListener</code></a> method for details around listening to transactions completing.</p><p>Together, this release allows stores to couple their transaction life-cycles together, which we need for the query engine.</p><p>Note: this API was updated to be more comprehensive in v4.0.</p><h2 id="v1-2">v1.2</h2><p>This adds a way to revert transactions if they have not met certain conditions.</p><p>When using the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/transaction/transaction/"><code>transaction</code></a> method, you can provide an optional <code>doRollback</code> callback which should return true if you want to revert the whole transaction at its conclusion.</p><p>The callback is provided with two objects, <code>changedCells</code> and <code>invalidCells</code>, which list all the net changes and invalid attempts at changes that were made during the transaction. You will most likely use the contents of those objects to decide whether the transaction should be rolled back.</p><p>Note: this API was updated to be more comprehensive in v4.0.</p><h2 id="v1-1">v1.1</h2><p>This release allows you to listen to invalid data being added to a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a>, allowing you to gracefully handle errors, rather than them failing silently.</p><p>There is a new listener type <a href="https://tinybase.org/api/store/type-aliases/listener/invalidcelllistener/"><code>InvalidCellListener</code></a> and a <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addinvalidcelllistener/"><code>addInvalidCellListener</code></a> method in the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> interface.</p><p>These allow you to keep track of failed attempts to update the <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> with invalid <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> data. These listeners can also be mutators, allowing you to address any failed writes programmatically.</p><p>For more information, please see the <a href="https://tinybase.org/api/store/interfaces/store/store/methods/listener/addinvalidcelllistener/"><code>addInvalidCellListener</code></a> method documentation. In particular, this explains how this listener behaves for a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> with a <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a>.</p>