tinybase 9.3.0-beta.1 → 9.4.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.
- package/min/omni/index.js +1 -1
- package/min/omni/index.js.gz +0 -0
- package/min/omni/with-schemas/index.js +1 -1
- package/min/omni/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-powersync/index.js +1 -1
- package/min/persisters/persister-powersync/index.js.gz +0 -0
- package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
- package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
- package/omni/index.js +0 -1
- package/omni/with-schemas/index.js +0 -1
- package/package.json +13 -8
- package/persisters/persister-powersync/index.js +0 -1
- package/persisters/persister-powersync/with-schemas/index.js +0 -1
- package/readme.md +14 -14
- package/releases.md +63 -63
- package/ui-svelte/index.js +1 -1
- package/ui-svelte/with-schemas/index.js +1 -1
- package/ui-svelte-dom/index.js +2 -2
- package/ui-svelte-dom/with-schemas/index.js +2 -2
- package/ui-svelte-inspector/index.js +2 -2
- package/ui-svelte-inspector/with-schemas/index.js +2 -2
package/releases.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<link rel="preload" as="image" href="https://
|
|
1
|
+
<link rel="preload" as="image" href="https://tinybase.org/shots/styled-chart-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/axis-overrides-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-svelte-full-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/partykit.gif"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/car-analysis-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/movie-database-demo.png"><p>This is a reverse chronological list of the major TinyBase releases, with highlighted features.</p><hr><h1 id="v9-3">v9.3</h1><p>TinyBase v9.3 lets multiple independently synchronized MergeableStores share one WebSocket connection. It also includes broad reliability and hardening work across core data, synchronization, persistence, UI integrations, packaging, and performance.</p><h2 id="multiple-stores-over-one-websocket">Multiple Stores Over One WebSocket</h2><p>Multiple WebSocket Synchronizers can now share a single physical WebSocket connection (<a href="https://github.com/tinyplex/tinybase/issues/177">#177</a>). This is useful when an application has several independently synchronized <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> instances but needs to limit its connection count.</p><p>Create the WebSocket with the <code>tinybase</code> subprotocol and provide a channel <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> as the third argument to each createWsSynchronizer call:</p>
|
|
2
2
|
|
|
3
3
|
```js
|
|
4
4
|
import {createMergeableStore} from 'tinybase';
|
|
@@ -35,13 +35,13 @@ await employeesSynchronizer.destroy();
|
|
|
35
35
|
await multistoreServer.destroy();
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
<p>Each channel extends the base URL path, so the example uses the logical paths <code>petShop/pets</code> and <code>petShop/employees</code>. Legacy clients can connect directly to those full paths, while omitting the channel <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> retains the existing signature and wire protocol. Multiplexing is supported by <a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> and <a href="https://beta.tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a>; <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> continues to use one URL path and Durable Object per WebSocket.</p><p>Channel <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> are not an authorization boundary: a client accepted on a base path can subscribe to any valid descendant channel. Authenticate and isolate untrusted clients by base path, and do not treat client <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> derived from <code>Sec-WebSocket-Key</code> as authenticated identities.</p><h2 id="reliability-and-hardening">Reliability And Hardening</h2><h3 id="core-data-and-apis">Core Data And APIs</h3><ul><li>Arbitrary <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> such as <code>__proto__</code>, <code>constructor</code>, and <code>toString</code> are now safe throughout <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a>, synchronization, and persistence.</li><li>Errors from transaction actions and pre-commit callbacks now roll back content, schemas, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> stamps and hashes, and temporary state across <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a>, and <a href="https://beta.tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a>; nested failures roll back the shared outer transaction, while post-commit listener failures no longer strand the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>Query definitions are staged before commit, and new <a href="https://beta.tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a>, <a href="https://beta.tinybase.org/api/metrics/type-aliases/metric/metric/"><code>Metric</code></a>, Query, and <a href="https://beta.tinybase.org/api/relationships/type-aliases/concept/relationship/"><code>Relationship</code></a> definitions are discarded if their <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> listener throws.</li><li>Deleting a Query definition now releases cached pre- and result Stores once nothing still references them.</li><li><a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> now atomically rejects HLCs that are not exactly 16 characters or are over five minutes in the future, carries overflowing 24-bit counters into wall-clock time, and verifies local stamps without mutating rejected caller payloads.</li><li>String Cells, <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>, and schema defaults using TinyBase's reserved leading <code>U+FFFD</code> or exact <code>U+FFFC</code> encodings are rejected, while invalid or schema-incompatible persisted encodings are ignored safely.</li><li>Object and array Cells and <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> now have an explicit JSON-compatible content contract, reject unserializable data, and no longer modify caller-owned or frozen containers during bulk writes.</li><li><a href="https://beta.tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> and <a href="https://beta.tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> now group, sort, and index equivalent object and array values consistently without stale results; direct rich <a href="https://beta.tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a> keys remain distinct from custom-function arrays that select multiple Slices.</li><li><a href="https://beta.tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a> and <a href="https://beta.tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> objects are cloned before normalization, making frozen schemas reusable and preserving the previous schema after an invalid replacement; schema JSON getters also preserve object and array defaults.</li><li><a href="https://beta.tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> receives cloned object and array values in public JavaScript form, with callback results validated and encoded only at the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> boundary.</li><li><a href="https://beta.tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> and <a href="https://beta.tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> now clean up <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> registrations safely, avoid duplicate listeners after recreation, and skip phantom checkpoints for structurally unchanged rich content.</li></ul><h3 id="synchronization"><a href="https://beta.tinybase.org/guides/synchronization/">Synchronization</a></h3><ul><li><a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> and <a href="https://beta.tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a> now share multiplex negotiation, decoding, channel-lifecycle, and cleanup behavior, and retain safe error listeners for their lifetimes.</li><li>Synchronizers reject pending requests on transport failure, remove built-in listeners when destroyed, and expose transport failures to custom register callbacks.</li><li><a href="https://beta.tinybase.org/api/synchronizer-broadcast-channel/interfaces/synchronizer/broadcastchannelsynchronizer/"><code>BroadcastChannelSynchronizer</code></a> validates message envelopes, while <a href="https://beta.tinybase.org/api/synchronizer-local/interfaces/synchronizer/localsynchronizer/"><code>LocalSynchronizer</code></a> snapshots scheduled recipients and cancels deliveries when destroyed.</li><li>WebSocket fragments now split by UTF-8 byte size at code-point boundaries and use at most 1,000 fragments.</li><li>Malformed WebSocket traffic reports error 14 and closes the offending peer with status <code>1007</code> before relay; complete messages and multiplex envelopes are limited to 16 MiB, with oversize input closing only its sender.</li><li>Offline and startup queues, pending requests, incomplete fragments, and socket buffering are bounded; queued traffic expires or coalesces, while overload reports error 15, closes peers with status <code>1013</code> where appropriate, and stops accepting new requests when the pending map is full.</li><li>Multiplexed channels keep independent timeout and error handling, clear failed subscriptions for retry, and settle immediately around closing or closed sockets; reconnect handshakes and queued replays cannot consume replacement connection state.</li><li><a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> setup, teardown, <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> retries, path resubscription, and destruction now clean up deterministically; subscriptions are acknowledged before persisted startup, destroy closes clients and awaits the WebSocketServer, and stale path cleanup cannot remove replacements.</li><li>All path and client <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> listeners still run when one throws, listener and ignored-error failures no longer strand server state, and <a href="https://beta.tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a> applies the same outbound safety checks as <a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a>.</li><li><a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> reports an empty path before its first connection, correctly types synchronous errors and asynchronous namespace responses, and lets subclasses observe malformed traffic.</li><li>PartyKit now persists and broadcasts only authorized changes, leaves rooms uninitialized after fully rejected first writes, serializes writes, validates incoming content and stored keys, and accepts empty HTTP responses on the client.</li></ul><h3 id="persistence"><a href="https://beta.tinybase.org/guides/persistence/">Persistence</a></h3><ul><li>Remote Persisters preserve ETags until successful downloads, reject failed responses, serialize polling, and abort active polls when stopped or destroyed.</li><li><a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> operations now await queued work; shared schedulers attribute errors to the correct owner and survive failures in ignored-error handlers.</li><li>Repeated destruction shares one completion Promise, waits for active work, restores idle status despite cleanup failures, and releases shared scheduler state.</li><li>Concurrent automatic lifecycle calls support falsey handles, retain only the latest registration, wait for setup and cleanup during stop or destroy, and stop both auto-load and auto-save even if one cleanup fails.</li><li>Auto-load startup closes missed-change windows and preserves notification ordering; steady-state inline changes apply synchronously without redundant saves, while no-content notifications during a save coalesce into a trailing load.</li><li>Database transaction failures roll back; remote libSQL uses one transaction session while local file clients retain their connection, and tabular Persisters replace every table-name placeholder, enforce collision-safe <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> uniqueness, and reject configurations that cannot preserve merge metadata.</li><li>PostgreSQL auto-load shares notification resources until the final owner stops and releases reserved clients after setup failure.</li><li>SQLite auto-load establishes its baseline before use, defers update-hook work until the triggering write completes, drains pending work on stop, and allows asynchronous change-listener cleanup.</li><li>IndexedDB waits for transaction completion, reports aborts and blocked opens, uses read-only loads, and serializes and drains changed-content polling.</li><li>Durable Object KV persistence batches limit-safe writes transactionally and ignores unrelated or malformed keys; Durable Object SQL preserves empty <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and safely quotes generated table names.</li><li>React Native MMKV preserves deletion tombstones and contains malformed content and listener failures; Automerge and Yjs validate TinyBase document roots before loading or applying changes, while Automerge still allows unrelated root metadata.</li><li>Browser storage, IndexedDB, PowerSync, SQLite, PostgreSQL, Automerge, and Yjs notifications route parsing and listener failures through ignored-error handling.</li><li>File persistence atomically replaces data while preserving modes and symbolic links, and its auto-load follows replacements without duplicate self-loads; OPFS always closes successful writes and aborts failed ones.</li></ul><h3 id="ui-and-lifecycle">UI And Lifecycle</h3><ul><li>Solid primitives no longer register <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> listeners during server rendering.</li><li>React and Solid asynchronous resource hooks destroy stale or post-unmount results, hide resources during replacement, await destruction, contain failures, and serialize Solid replacements behind previous cleanup.</li><li>Solid and Svelte DOM and Inspector packages are explicitly client-only, so server builds fail cleanly during resolution.</li><li>Solid DOM table wrappers keep table, query, and slice metadata reactive, while Solid Inspector actions and custom <a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> renderers react to editability and <a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> changes.</li><li>Solid useUndoInformation and useRedoInformation now return Accessors for availability, checkpoint <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>, and label values.</li><li>Object and array editors mark JSON with the wrong container type invalid, and React, Solid, and Svelte paginators normalize boundary offsets and clamp previous navigation to zero.</li><li>React and Solid paginators defer offset corrections until after rendering, and Provider registrations in all three UI modules preserve the correct resource when duplicate <a href="https://beta.tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> owners are removed.</li></ul><h3 id="packaging-and-performance">Packaging And Performance</h3><ul><li>TinyBase errors now use compact numeric codes documented in the <a href="https://beta.tinybase.org/guides/error-codes/">Error Codes</a> guide.</li><li>The build now classifies Svelte modules correctly and verifies generated JavaScript exports against declared public values.</li><li>Accidental React, Solid, DOM, and IndexedDB helper exports have been removed, while createDurableObjectSqlStoragePersister is exported from the omni module as declared.</li><li>The getTransactionMergeableChanges declaration now distinguishes its default unhashed result from explicitly requested hashed changes.</li><li>Internal iteration paths now avoid unnecessary allocations, while invalid <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> JSON setters complete synchronously without creating Promises or microtasks.</li><li><a href="https://beta.tinybase.org/api/metrics/type-aliases/metric/metric/"><code>Metric</code></a> extrema and Cartesian chart summaries now handle large datasets without variadic argument limits or quadratic category de-duplication.</li></ul><hr><h1 id="v9-2">v9.2</h1><p>TinyBase v9.2 makes the library easier for coding agents and AI systems to discover, evaluate, understand, and use correctly.</p><p>Although there are no changes to TinyBase source code, this is more than just an AI-specific documentation pass. The package and website metadata now describes TinyBase using the concrete problems it solves: reactive in-memory data, offline and local-first applications, persistence, CRDTs, and synchronization. This helps search and retrieval systems connect an application requirement to TinyBase before the library name is already known.</p><h2 id="agent-documentation-and-retrieval">Agent <a href="https://beta.tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> And Retrieval</h2><p>The website now publishes a concise <a href="https://tinybase.org/llms.txt"><code>llms.txt</code></a> orientation file and a fuller <a href="https://tinybase.org/llms-full.txt"><code>llms-full.txt</code></a> agent guide. A new <a href="https://beta.tinybase.org/guides/the-basics/why-tinybase/">Why TinyBase?</a> guide explains when TinyBase is a good architectural fit, when it is not, and which <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, persistence, synchronization, and UI pieces to start with.</p><p>The repository also includes configuration for current documentation to be indexed by <a href="https://context7.com/">Context7</a>, as well as machine-readable structured metadata for ordinary search and retrieval systems.</p><h2 id="an-official-tinybase-skill">An Official TinyBase Skill</h2><p>The repository now contains an official <a href="https://tinybase.org/skills/build-with-tinybase/SKILL.md"><code>build-with-tinybase</code></a> agent skill. It guides coding agents through architecture selection, scaffolding, safe extension of generated applications, and behavioral verification.</p><p>The skill treats persistence and synchronization as behaviors to prove, not just code that compiles. It instructs agents to verify persisted state across a real reload and synchronized state between multiple clients.</p><h2 id="agent-friendly-scaffolding">Agent-Friendly Scaffolding</h2><p>The <a href="https://github.com/tinyplex/create-tinybase"><code>create-tinybase</code></a> scaffolding tool now exposes its current options as JSON, documents its non-interactive mode, and generates an architecture-specific <code>AGENTS.md</code> in every new project. This gives agents a deterministic path from application requirements to a complete, working TinyBase app.</p><p>Agents can inspect the current generator contract with:</p>
|
|
38
|
+
<p>Each channel extends the base URL path, so the example uses the logical paths <code>petShop/pets</code> and <code>petShop/employees</code>. Legacy clients can connect directly to those full paths, while omitting the channel <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> retains the existing signature and wire protocol. Multiplexing is supported by <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> and <a href="https://tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a>; <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> continues to use one URL path and Durable Object per WebSocket.</p><p>Channel <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> are not an authorization boundary: a client accepted on a base path can subscribe to any valid descendant channel. Authenticate and isolate untrusted clients by base path, and do not treat client <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> derived from <code>Sec-WebSocket-Key</code> as authenticated identities.</p><h2 id="reliability-and-hardening">Reliability And Hardening</h2><h3 id="breaking-ish-changes">Breaking-ish <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a></h3><ul><li>Errors use compact numeric codes.</li><li>Failed transactions now rollback.</li><li>Certain previously accepted/reserved or unserializable values are rejected.</li><li>Client-only Solid and Svelte exports now correctly fail server resolution.</li><li>Solid's <a href="https://tinybase.org/api/ui-react/type-aliases/checkpoints/undoorredoinformation/"><code>UndoOrRedoInformation</code></a> changed from values to accessors.</li><li>Over-eager runtime exports disappeared from the Svelte package.</li></ul><p>The full explanations for these and many other changes are below:</p><h3 id="core-data-and-apis">Core Data And APIs</h3><ul><li>Arbitrary <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> such as <code>__proto__</code>, <code>constructor</code>, and <code>toString</code> are now safe throughout <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a>, synchronization, and persistence.</li><li>Errors from transaction actions and pre-commit callbacks now roll back content, schemas, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> stamps and hashes, and temporary state across <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a>, and <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a>; nested failures roll back the shared outer transaction, while post-commit listener failures no longer strand the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>Query definitions are staged before commit, and new <a href="https://tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a>, <a href="https://tinybase.org/api/metrics/type-aliases/metric/metric/"><code>Metric</code></a>, Query, and <a href="https://tinybase.org/api/relationships/type-aliases/concept/relationship/"><code>Relationship</code></a> definitions are discarded if their <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> listener throws.</li><li>Deleting a Query definition now releases cached pre- and result Stores once nothing still references them.</li><li><a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> now atomically rejects HLCs that are not exactly 16 characters or are over five minutes in the future, carries overflowing 24-bit counters into wall-clock time, and verifies local stamps without mutating rejected caller payloads.</li><li>String Cells, <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>, and schema defaults using TinyBase's reserved leading <code>U+FFFD</code> or exact <code>U+FFFC</code> encodings are rejected, while invalid or schema-incompatible persisted encodings are ignored safely.</li><li>Object and array Cells and <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> now have an explicit JSON-compatible content contract, reject unserializable data, and no longer modify caller-owned or frozen containers during bulk writes.</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> and <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> now group, sort, and index equivalent object and array values consistently without stale results; direct rich <a href="https://tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a> keys remain distinct from custom-function arrays that select multiple Slices.</li><li><a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a> and <a href="https://tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> objects are cloned before normalization, making frozen schemas reusable and preserving the previous schema after an invalid replacement; schema JSON getters also preserve object and array defaults.</li><li><a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> receives cloned object and array values in public JavaScript form, with callback results validated and encoded only at the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> boundary.</li><li><a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> and <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> now clean up <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> registrations safely, avoid duplicate listeners after recreation, and skip phantom checkpoints for structurally unchanged rich content.</li></ul><h3 id="synchronization"><a href="https://tinybase.org/guides/synchronization/">Synchronization</a></h3><ul><li><a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> and <a href="https://tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a> now share multiplex negotiation, decoding, channel-lifecycle, and cleanup behavior, and retain safe error listeners for their lifetimes.</li><li>Synchronizers reject pending requests on transport failure, remove built-in listeners when destroyed, and expose transport failures to custom register callbacks.</li><li><a href="https://tinybase.org/api/synchronizer-broadcast-channel/interfaces/synchronizer/broadcastchannelsynchronizer/"><code>BroadcastChannelSynchronizer</code></a> validates message envelopes, while <a href="https://tinybase.org/api/synchronizer-local/interfaces/synchronizer/localsynchronizer/"><code>LocalSynchronizer</code></a> snapshots scheduled recipients and cancels deliveries when destroyed.</li><li>WebSocket fragments now split by UTF-8 byte size at code-point boundaries and use at most 1,000 fragments.</li><li>Malformed WebSocket traffic reports error 14 and closes the offending peer with status <code>1007</code> before relay; complete messages and multiplex envelopes are limited to 16 MiB, with oversize input closing only its sender.</li><li>Offline and startup queues, pending requests, incomplete fragments, and socket buffering are bounded; queued traffic expires or coalesces, while overload reports error 15, closes peers with status <code>1013</code> where appropriate, and stops accepting new requests when the pending map is full.</li><li>Multiplexed channels keep independent timeout and error handling, clear failed subscriptions for retry, and settle immediately around closing or closed sockets; reconnect handshakes and queued replays cannot consume replacement connection state.</li><li><a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> setup, teardown, <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> retries, path resubscription, and destruction now clean up deterministically; subscriptions are acknowledged before persisted startup, destroy closes clients and awaits the WebSocketServer, and stale path cleanup cannot remove replacements.</li><li>All path and client <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> listeners still run when one throws, listener and ignored-error failures no longer strand server state, and <a href="https://tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a> applies the same outbound safety checks as <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a>.</li><li><a href="https://tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> reports an empty path before its first connection, correctly types synchronous errors and asynchronous namespace responses, and lets subclasses observe malformed traffic.</li><li>PartyKit now persists and broadcasts only authorized changes, leaves rooms uninitialized after fully rejected first writes, serializes writes, validates incoming content and stored keys, and accepts empty HTTP responses on the client.</li></ul><h3 id="persistence"><a href="https://tinybase.org/guides/persistence/">Persistence</a></h3><ul><li>Remote Persisters preserve ETags until successful downloads, reject failed responses, serialize polling, and abort active polls when stopped or destroyed.</li><li><a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> operations now await queued work; shared schedulers attribute errors to the correct owner and survive failures in ignored-error handlers.</li><li>Repeated destruction shares one completion Promise, waits for active work, restores idle status despite cleanup failures, and releases shared scheduler state.</li><li>Concurrent automatic lifecycle calls support falsey handles, retain only the latest registration, wait for setup and cleanup during stop or destroy, and stop both auto-load and auto-save even if one cleanup fails.</li><li>Auto-load startup closes missed-change windows and preserves notification ordering; steady-state inline changes apply synchronously without redundant saves, while no-content notifications during a save coalesce into a trailing load.</li><li>Database transaction failures roll back; remote libSQL uses one transaction session while local file clients retain their connection, and tabular Persisters replace every table-name placeholder, enforce collision-safe <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> uniqueness, and reject configurations that cannot preserve merge metadata.</li><li>PostgreSQL auto-load shares notification resources until the final owner stops and releases reserved clients after setup failure.</li><li>SQLite auto-load establishes its baseline before use, defers update-hook work until the triggering write completes, drains pending work on stop, and allows asynchronous change-listener cleanup.</li><li>IndexedDB waits for transaction completion, reports aborts and blocked opens, uses read-only loads, and serializes and drains changed-content polling.</li><li>Durable Object KV persistence batches limit-safe writes transactionally and ignores unrelated or malformed keys; Durable Object SQL preserves empty <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and safely quotes generated table names.</li><li>React Native MMKV preserves deletion tombstones and contains malformed content and listener failures; Automerge and Yjs validate TinyBase document roots before loading or applying changes, while Automerge still allows unrelated root metadata.</li><li>Browser storage, IndexedDB, PowerSync, SQLite, PostgreSQL, Automerge, and Yjs notifications route parsing and listener failures through ignored-error handling.</li><li>File persistence atomically replaces data while preserving modes and symbolic links, and its auto-load follows replacements without duplicate self-loads; OPFS always closes successful writes and aborts failed ones.</li></ul><h3 id="ui-and-lifecycle">UI And Lifecycle</h3><ul><li>Solid primitives no longer register <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> listeners during server rendering.</li><li>React and Solid asynchronous resource hooks destroy stale or post-unmount results, hide resources during replacement, await destruction, contain failures, and serialize Solid replacements behind previous cleanup.</li><li>Solid and Svelte DOM and Inspector packages are explicitly client-only, so server builds fail cleanly during resolution.</li><li>Solid DOM table wrappers keep table, query, and slice metadata reactive, while Solid Inspector actions and custom <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> renderers react to editability and <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/id/"><code>Id</code></a> changes.</li><li>Solid useUndoInformation and useRedoInformation now return Accessors for availability, checkpoint <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>, and label values.</li><li>Object and array editors mark JSON with the wrong container type invalid, and React, Solid, and Svelte paginators normalize boundary offsets and clamp previous navigation to zero.</li><li>React and Solid paginators defer offset corrections until after rendering, and Provider registrations in all three UI modules preserve the correct resource when duplicate <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> owners are removed.</li></ul><h3 id="packaging-and-performance">Packaging And Performance</h3><ul><li>TinyBase errors now use compact numeric codes documented in the <a href="https://tinybase.org/guides/error-codes/">Error Codes</a> guide.</li><li>The build now classifies Svelte modules correctly and verifies generated JavaScript exports against declared public values.</li><li>Accidental React, Solid, DOM, and IndexedDB helper exports have been removed, while createDurableObjectSqlStoragePersister is exported from the omni module as declared.</li><li>The getTransactionMergeableChanges declaration now distinguishes its default unhashed result from explicitly requested hashed changes.</li><li>Internal iteration paths now avoid unnecessary allocations, while invalid <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> JSON setters complete synchronously without creating Promises or microtasks.</li><li><a href="https://tinybase.org/api/metrics/type-aliases/metric/metric/"><code>Metric</code></a> extrema and Cartesian chart summaries now handle large datasets without variadic argument limits or quadratic category de-duplication.</li></ul><hr><h1 id="v9-2">v9.2</h1><p>TinyBase v9.2 makes the library easier for coding agents and AI systems to discover, evaluate, understand, and use correctly.</p><p>Although there are no changes to TinyBase source code, this is more than just an AI-specific documentation pass. The package and website metadata now describes TinyBase using the concrete problems it solves: reactive in-memory data, offline and local-first applications, persistence, CRDTs, and synchronization. This helps search and retrieval systems connect an application requirement to TinyBase before the library name is already known.</p><h2 id="agent-documentation-and-retrieval">Agent <a href="https://tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> And Retrieval</h2><p>The website now publishes a concise <a href="https://tinybase.org/llms.txt"><code>llms.txt</code></a> orientation file and a fuller <a href="https://tinybase.org/llms-full.txt"><code>llms-full.txt</code></a> agent guide. A new <a href="https://tinybase.org/guides/the-basics/why-tinybase/">Why TinyBase?</a> guide explains when TinyBase is a good architectural fit, when it is not, and which <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, persistence, synchronization, and UI pieces to start with.</p><p>The repository also includes configuration for current documentation to be indexed by <a href="https://context7.com/">Context7</a>, as well as machine-readable structured metadata for ordinary search and retrieval systems.</p><h2 id="an-official-tinybase-skill">An Official TinyBase Skill</h2><p>The repository now contains an official <a href="https://tinybase.org/skills/build-with-tinybase/SKILL.md"><code>build-with-tinybase</code></a> agent skill. It guides coding agents through architecture selection, scaffolding, safe extension of generated applications, and behavioral verification.</p><p>The skill treats persistence and synchronization as behaviors to prove, not just code that compiles. It instructs agents to verify persisted state across a real reload and synchronized state between multiple clients.</p><h2 id="agent-friendly-scaffolding">Agent-Friendly Scaffolding</h2><p>The <a href="https://github.com/tinyplex/create-tinybase"><code>create-tinybase</code></a> scaffolding tool now exposes its current options as JSON, documents its non-interactive mode, and generates an architecture-specific <code>AGENTS.md</code> in every new project. This gives agents a deterministic path from application requirements to a complete, working TinyBase app.</p><p>Agents can inspect the current generator contract with:</p>
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
41
|
npm create tinybase@latest -- --list-options
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
<p>The generated guidance records the chosen language, UI framework, persistence, synchronization, and schema options, identifies the important files, and states the verification expected for that architecture.</p><p>If you're a human, you shouldn't notice or mind these changes. If you're an agent, we hope this makes it easier to find and use TinyBase correctly. Either way, let us know how it goes!</p><hr><h1 id="v9-1">v9.1</h1><h2 id="required-schema-fields">Required Schema Fields</h2><p><a href="https://
|
|
44
|
+
<p>The generated guidance records the chosen language, UI framework, persistence, synchronization, and schema options, identifies the important files, and states the verification expected for that architecture.</p><p>If you're a human, you shouldn't notice or mind these changes. If you're an agent, we hope this makes it easier to find and use TinyBase correctly. Either way, let us know how it goes!</p><hr><h1 id="v9-1">v9.1</h1><h2 id="required-schema-fields">Required Schema Fields</h2><p><a href="https://tinybase.org/guides/schemas/">Schemas</a> can now mark 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> as required without providing a default value (<a href="https://github.com/tinyplex/tinybase/issues/173">#173</a>). Full writes now reject Rows or <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> that omit a required non-default field, while preserving the existing rule that a <code>default</code> also implies 'requiredness' (and will be filled automatically if omitted).</p>
|
|
45
45
|
|
|
46
46
|
```js
|
|
47
47
|
import {createStore} from 'tinybase';
|
|
@@ -64,7 +64,7 @@ console.log(requiredSchemaStore.getRow('pets', 'felix'));
|
|
|
64
64
|
// -> {}
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
<p>The v9.1.1 patch also updates the schematizers for Zod, Valibot, ArkType, TypeBox, Yup, and Effect Schema so that required fields in those libraries are reflected as <code>required: true</code> in the generated TinyBase schemas.</p><h2 id="custom-sorting">Custom Sorting</h2><p>This release adds custom sorting for sorted <a href="https://
|
|
67
|
+
<p>The v9.1.1 patch also updates the schematizers for Zod, Valibot, ArkType, TypeBox, Yup, and Effect Schema so that required fields in those libraries are reflected as <code>required: true</code> in the generated TinyBase schemas.</p><h2 id="custom-sorting">Custom Sorting</h2><p>This release adds custom sorting for sorted <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> APIs, so applications can opt into numeric or domain-specific ordering without changing TinyBase's existing alphanumeric default behavior.</p><p>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getsortedrowids/"><code>getSortedRowIds</code></a> method and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addsortedrowidslistener/"><code>addSortedRowIdsListener</code></a> method now support a custom <code>sorter</code> function in the <a href="https://tinybase.org/api/store/type-aliases/store/sortedrowidsargs/"><code>SortedRowIdsArgs</code></a> object. The <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usesortedrowids/"><code>useSortedRowIds</code></a> hook and getSortedRowIds Svelte function also accept the sorter positionally (<a href="https://github.com/tinyplex/tinybase/issues/190">#190</a>, <a href="https://github.com/tinyplex/tinybase/issues/213">#213</a>).</p>
|
|
68
68
|
|
|
69
69
|
```js
|
|
70
70
|
const numericSortStore = createStore();
|
|
@@ -83,7 +83,7 @@ console.log(
|
|
|
83
83
|
// -> ['1', '2', '10']
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
<p><strong>Breaking change:</strong> In the <code>ui-solid</code> and <code>ui-svelte</code> modules, the positional <a href="https://
|
|
86
|
+
<p><strong>Breaking change:</strong> In the <code>ui-solid</code> and <code>ui-svelte</code> modules, the positional <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> argument for <code>useSortedRowIds</code> and <code>getSortedRowIds</code> respectively has moved one slot later to make room for a positional custom sorter. If you pass a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> as the final positional argument, add <code>undefined</code> before it, or switch to the object argument form.</p><h2 id="index-presence-helpers"><a href="https://tinybase.org/api/indexes/type-aliases/concept/index/"><code>Index</code></a> Presence Helpers</h2><p>The <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> interface already exposes the <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/methods/getter/hasindex/"><code>hasIndex</code></a> method and <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/methods/getter/hasslice/"><code>hasSlice</code></a> method. This release also adds reactive helpers for UI integrations: <code>useHasIndex</code> and <code>useHasSlice</code> for React and Solid, and <code>hasIndex</code> and <code>hasSlice</code> for Svelte (<a href="https://github.com/tinyplex/tinybase/issues/163">#163</a>). The <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> interface also now exposes a <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/methods/listener/addhasindexlistener/"><code>addHasIndexListener</code></a> method and <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/methods/listener/addhasslicelistener/"><code>addHasSliceListener</code></a> method.</p><hr><h1 id="v9-0">v9.0</h1><p>This release has no new features; just fixes and reliability improvements.</p><p>TinyBase v9.0 is all about addressing issues from the community - and making local-first apps behave better in production. The areas addressed include persistence, synchronization, schema defaults, infrastructure limits, and edge-case query semantics.</p><p>There is one new configuration option (for more selective <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> persistence), but otherwise the wider theme is reliability. This release hardens WebSocket synchronization, Durable Object storage, PowerSync startup, custom <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> loading, and a few type and documentation edges so that apps recover and sync more cleanly under real-world conditions.</p><p>We hope you enjoy using TinyBase and if you find further issues, keep them coming!</p><h2 id="persistence-subsets"><a href="https://tinybase.org/guides/persistence/">Persistence</a> Subsets</h2><p>This release adds finer-grained configuration for tabular database Persisters, allowing <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> persistence to be limited to selected <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> (<a href="https://github.com/tinyplex/tinybase/issues/279">#279</a>).</p><p>For apps that keep durable state and UI-only state in the same <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, the <a href="https://tinybase.org/api/persisters/type-aliases/configuration/dpctabularvalues/"><code>DpcTabularValues</code></a> <code>load</code> and <code>save</code> properties can now use an array of <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> instead of a simple boolean:</p>
|
|
87
87
|
|
|
88
88
|
```js
|
|
89
89
|
const valuesSubsetDatabasePersisterConfig = {
|
|
@@ -98,8 +98,8 @@ console.log(valuesSubsetDatabasePersisterConfig.values.load);
|
|
|
98
98
|
// -> ['selectedPet', 'open']
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
<p>When a subset is configured, unlisted <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> are not saved, and unlisted columns in the <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> database table are left untouched.</p><h2 id="websocket-synchronization-fixes">WebSocket <a href="https://beta.tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>WebSocket Synchronizers can now fragment large synchronization payloads and reassemble them on receipt. This helps deployments behind infrastructure with WebSocket message size limits, such as Cloudflare Workers and Durable Objects (<a href="https://github.com/tinyplex/tinybase/issues/261">#261</a>).</p><p>The createWsSynchronizer and <a href="https://beta.tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> functions now accept an optional fragment size argument. Incomplete fragment buffers expire using the existing request timeout, which can also now be set on createWsServer. Durable Object servers can override the getFragmentSize and <a href="https://beta.tinybase.org/api/synchronizer-ws-server-durable-object/classes/creation/wsserverdurableobject/methods/getter/getrequesttimeoutseconds/"><code>getRequestTimeoutSeconds</code></a> methods to set the same behavior for messages they send.</p><p>The WebSocket <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> documentation now also clarifies that <a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> paths come from WebSocket URL paths, not <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>, so clients that need separate synchronization groups should connect to different URL paths (<a href="https://github.com/tinyplex/tinybase/issues/206">#206</a>).</p><p>When a persisted <a href="https://beta.tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> path starts after having no connected clients, it now loads its persisted <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> before starting synchronization. This means the first client to reconnect is sent only the data it is missing, instead of receiving the whole persisted <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> as a fresh change (<a href="https://github.com/tinyplex/tinybase/issues/205">#205</a>).</p><h2 id="schema-default-synchronization-fixes">Schema Default <a href="https://beta.tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>Schema defaults inserted automatically into MergeableStores now use neutral timestamps, so defaulted <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> and Cells no longer overwrite newer synced data from another peer. Explicit writes of default values still receive normal timestamps (<a href="https://github.com/tinyplex/tinybase/issues/167">#167</a>).</p><h2 id="powersync-persistence-fixes">PowerSync <a href="https://beta.tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The PowerSync <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> now updates existing tabular rows before inserting missing ones, instead of replacing whole rows during upserts. This avoids flooding PowerSync upload queues with replacement writes when schema validation causes loaded data to be written back unchanged on startup (<a href="https://github.com/tinyplex/tinybase/issues/262">#262</a>).</p><h2 id="custom-persister-loading-fixes">Custom <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> Loading Fixes</h2><p>Custom Persisters can now return <code>undefined</code> from <code>getPersisted</code> to indicate that there is no persisted content. Loading then uses <code>initialContent</code> if it was provided, or otherwise leaves the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> unchanged without invoking the ignored error handler (<a href="https://github.com/tinyplex/tinybase/issues/161">#161</a>).</p><h2 id="durable-object-persistence-fixes">Durable Object <a href="https://beta.tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The Durable Object SQL Storage <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode now stores table row data as one SQL row per TinyBase <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, instead of one SQL row per <a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. This reduces the number of SQLite writes for wide Rows while preserving the fragmented mode's protection from Cloudflare's 2MB row limit. Existing cell-level fragmented data is still loaded and is cleaned up when the <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> is next saved (<a href="https://github.com/tinyplex/tinybase/issues/268">#268</a>).</p><h2 id="query-transaction-fixes">Query Transaction Fixes</h2><p>Grouped queries, including those with having clauses, now correctly return their current result when a query definition is added during an active <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> transaction (<a href="https://github.com/tinyplex/tinybase/issues/259">#259</a>).</p><h2 id="query-documentation-clarifications">Query <a href="https://beta.tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> Clarifications</h2><p>The <a href="https://beta.tinybase.org/guides/using-queries/tinyql/">TinyQL</a> documentation now explicitly describes that a <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> only appears in a query result when at least one selected <a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or calculated value is defined. If all selected values for a <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> resolve to <code>undefined</code>, no <a href="https://beta.tinybase.org/api/queries/type-aliases/result/resultrow/"><code>ResultRow</code></a> is created for that <a href="https://beta.tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> (<a href="https://github.com/tinyplex/tinybase/issues/183">#183</a>).</p><h2 id="type-fixes">Type Fixes</h2><p>The schema-aware <a href="https://beta.tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablecontent/"><code>MergeableContent</code></a>, <a href="https://beta.tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablechanges/"><code>MergeableChanges</code></a>, persisted content, and <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> listener types now validate content being set or loaded in the same way as <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> setters. This catches invalid <a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or <a href="https://beta.tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a> <a href="https://beta.tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and values in custom Persisters and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> setters (<a href="https://github.com/tinyplex/tinybase/issues/178">#178</a>).</p><h2 id="breaking-change">Breaking Change</h2><p>This release is a major version because the Durable Object SQL Storage <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode uses a new storage layout. TinyBase v9.0 can read the old cell-level fragmented data written by earlier releases, but once it saves the new row-level fragmented data, older TinyBase versions are not designed to read that data back. Apps using fragmented Durable Object SQL storage should not roll those Durable Objects back to an earlier TinyBase version after v9.0 has written to them.</p><h2 id="thank-you">Thank You</h2><p>Thanks to everyone whose reports and fixes shaped this release:</p><p><a href="https://github.com/dheerajvs">Dheeraj</a>, <a href="https://github.com/jakubriedl">Jakub Riedl</a>, <a href="https://github.com/patrykwegrzyn">Patryk Wegrzyn</a>, <a href="https://github.com/dsrominiyi">Damilola Romniyi</a>, <a href="https://github.com/a11rew">Andrew Glago</a>, <a href="https://github.com/wattroll">wattroll</a>, <a href="https://github.com/willhoney7">Will Honey</a>, and <a href="https://github.com/danielberndt">Daniel Berndt</a>.</p><p>Could not do it without you!</p><hr><h1 id="v8-5">v8.5</h1><h2 id="react-chart-components">React Chart Components</h2><p>This release adds the new <a href="https://beta.tinybase.org/api/ui-react-dom-charts/"><code>ui-react-dom-charts</code></a> module, providing reactive SVG chart components for React apps.</p><p>The <a href="https://beta.tinybase.org/api/ui-react-dom-charts/functions/store-components/linechart/"><code>LineChart</code></a> component and <a href="https://beta.tinybase.org/api/ui-react-dom-charts/functions/store-components/barchart/"><code>BarChart</code></a> component can render data directly from a <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> <a href="https://beta.tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, or from a <a href="https://beta.tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> <a href="https://beta.tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>, using the same Provider context patterns as the rest of the React UI modules. For more complex charts, the <a href="https://beta.tinybase.org/api/ui-react-dom-charts/functions/store-components/cartesianchart/"><code>CartesianChart</code></a> component can compose multiple <a href="https://beta.tinybase.org/api/ui-react-dom-charts/functions/store-components/lineseries/"><code>LineSeries</code></a> component children and <a href="https://beta.tinybase.org/api/ui-react-dom-charts/functions/store-components/barseries/"><code>BarSeries</code></a> component children in one SVG.</p><p><img src="https://beta.tinybase.org/shots/styled-chart-react-demo.png" alt="LineChart component (React)" title="[`LineChart`](/api/ui-react-dom-charts/functions/store-components/linechart/)
|
|
102
|
-
component (React)"></p><p>A chart can be bound to a <a href="https://
|
|
101
|
+
<p>When a subset is configured, unlisted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> are not saved, and unlisted columns in the <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> database table are left untouched.</p><h2 id="websocket-synchronization-fixes">WebSocket <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>WebSocket Synchronizers can now fragment large synchronization payloads and reassemble them on receipt. This helps deployments behind infrastructure with WebSocket message size limits, such as Cloudflare Workers and Durable Objects (<a href="https://github.com/tinyplex/tinybase/issues/261">#261</a>).</p><p>The createWsSynchronizer and <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> functions now accept an optional fragment size argument. Incomplete fragment buffers expire using the existing request timeout, which can also now be set on createWsServer. Durable Object servers can override the getFragmentSize and <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/classes/creation/wsserverdurableobject/methods/getter/getrequesttimeoutseconds/"><code>getRequestTimeoutSeconds</code></a> methods to set the same behavior for messages they send.</p><p>The WebSocket <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> documentation now also clarifies that <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> paths come from WebSocket URL paths, not <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a>, so clients that need separate synchronization groups should connect to different URL paths (<a href="https://github.com/tinyplex/tinybase/issues/206">#206</a>).</p><p>When a persisted <a href="https://tinybase.org/api/synchronizer-ws-server/interfaces/server/wsserver/"><code>WsServer</code></a> path starts after having no connected clients, it now loads its persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> before starting synchronization. This means the first client to reconnect is sent only the data it is missing, instead of receiving the whole persisted <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> as a fresh change (<a href="https://github.com/tinyplex/tinybase/issues/205">#205</a>).</p><h2 id="schema-default-synchronization-fixes">Schema Default <a href="https://tinybase.org/guides/synchronization/">Synchronization</a> Fixes</h2><p>Schema defaults inserted automatically into MergeableStores now use neutral timestamps, so defaulted <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> and Cells no longer overwrite newer synced data from another peer. Explicit writes of default values still receive normal timestamps (<a href="https://github.com/tinyplex/tinybase/issues/167">#167</a>).</p><h2 id="powersync-persistence-fixes">PowerSync <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The PowerSync <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> now updates existing tabular rows before inserting missing ones, instead of replacing whole rows during upserts. This avoids flooding PowerSync upload queues with replacement writes when schema validation causes loaded data to be written back unchanged on startup (<a href="https://github.com/tinyplex/tinybase/issues/262">#262</a>).</p><h2 id="custom-persister-loading-fixes">Custom <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> Loading Fixes</h2><p>Custom Persisters can now return <code>undefined</code> from <code>getPersisted</code> to indicate that there is no persisted content. Loading then uses <code>initialContent</code> if it was provided, or otherwise leaves the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> unchanged without invoking the ignored error handler (<a href="https://github.com/tinyplex/tinybase/issues/161">#161</a>).</p><h2 id="durable-object-persistence-fixes">Durable Object <a href="https://tinybase.org/guides/persistence/">Persistence</a> Fixes</h2><p>The Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode now stores table row data as one SQL row per TinyBase <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>, instead of one SQL row per <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>. This reduces the number of SQLite writes for wide Rows while preserving the fragmented mode's protection from Cloudflare's 2MB row limit. Existing cell-level fragmented data is still loaded and is cleaned up when the <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> is next saved (<a href="https://github.com/tinyplex/tinybase/issues/268">#268</a>).</p><h2 id="query-transaction-fixes">Query Transaction Fixes</h2><p>Grouped queries, including those with having clauses, now correctly return their current result when a query definition is added during an active <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> transaction (<a href="https://github.com/tinyplex/tinybase/issues/259">#259</a>).</p><h2 id="query-documentation-clarifications">Query <a href="https://tinybase.org/guides/how-tinybase-is-built/documentation/">Documentation</a> Clarifications</h2><p>The <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> documentation now explicitly describes that a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> only appears in a query result when at least one selected <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or calculated value is defined. If all selected values for a <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> resolve to <code>undefined</code>, no <a href="https://tinybase.org/api/queries/type-aliases/result/resultrow/"><code>ResultRow</code></a> is created for that <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> (<a href="https://github.com/tinyplex/tinybase/issues/183">#183</a>).</p><h2 id="type-fixes">Type Fixes</h2><p>The schema-aware <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablecontent/"><code>MergeableContent</code></a>, <a href="https://tinybase.org/api/mergeable-store/type-aliases/mergeable/mergeablechanges/"><code>MergeableChanges</code></a>, persisted content, and <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> listener types now validate content being set or loaded in the same way as <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> setters. This catches invalid <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> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> and values in custom Persisters and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> setters (<a href="https://github.com/tinyplex/tinybase/issues/178">#178</a>).</p><h2 id="breaking-change">Breaking Change</h2><p>This release is a major version because the Durable Object SQL Storage <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s fragmented mode uses a new storage layout. TinyBase v9.0 can read the old cell-level fragmented data written by earlier releases, but once it saves the new row-level fragmented data, older TinyBase versions are not designed to read that data back. Apps using fragmented Durable Object SQL storage should not roll those Durable Objects back to an earlier TinyBase version after v9.0 has written to them.</p><h2 id="thank-you">Thank You</h2><p>Thanks to everyone whose reports and fixes shaped this release:</p><p><a href="https://github.com/dheerajvs">Dheeraj</a>, <a href="https://github.com/jakubriedl">Jakub Riedl</a>, <a href="https://github.com/patrykwegrzyn">Patryk Wegrzyn</a>, <a href="https://github.com/dsrominiyi">Damilola Romniyi</a>, <a href="https://github.com/a11rew">Andrew Glago</a>, <a href="https://github.com/wattroll">wattroll</a>, <a href="https://github.com/willhoney7">Will Honey</a>, and <a href="https://github.com/danielberndt">Daniel Berndt</a>.</p><p>Could not do it without you!</p><hr><h1 id="v8-5">v8.5</h1><h2 id="react-chart-components">React Chart Components</h2><p>This release adds the new <a href="https://tinybase.org/api/ui-react-dom-charts/"><code>ui-react-dom-charts</code></a> module, providing reactive SVG chart components for React apps.</p><p>The <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/linechart/"><code>LineChart</code></a> component and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barchart/"><code>BarChart</code></a> component can render data directly from a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>, or from a <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> <a href="https://tinybase.org/api/queries/type-aliases/result/resulttable/"><code>ResultTable</code></a>, using the same Provider context patterns as the rest of the React UI modules. For more complex charts, the <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/cartesianchart/"><code>CartesianChart</code></a> component can compose multiple <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/lineseries/"><code>LineSeries</code></a> component children and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/barseries/"><code>BarSeries</code></a> component children in one SVG.</p><p><img src="https://tinybase.org/shots/styled-chart-react-demo.png" alt="LineChart component (React)" title="[`LineChart`](/api/ui-react-dom-charts/functions/store-components/linechart/)
|
|
102
|
+
component (React)"></p><p>A chart can be bound to a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> with just the <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> and 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> to use for the x and y values:</p>
|
|
103
103
|
|
|
104
104
|
```jsx
|
|
105
105
|
import React from 'react';
|
|
@@ -136,7 +136,7 @@ console.log(app.firstChild?.nodeName.toLowerCase());
|
|
|
136
136
|
// -> 'svg'
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
<p>To plot multiple series in the same chart, use the <a href="https://
|
|
139
|
+
<p>To plot multiple series in the same chart, use the <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/cartesianchart/"><code>CartesianChart</code></a> component as the shared frame and declare each child series explicitly:</p>
|
|
140
140
|
|
|
141
141
|
```jsx
|
|
142
142
|
const MyCompositeChart = () => (
|
|
@@ -164,7 +164,7 @@ console.log(compositeChartApp.querySelectorAll('.line-series').length);
|
|
|
164
164
|
// -> 2
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
<p>The same CartesianChart frame can include zero or one <a href="https://
|
|
167
|
+
<p>The same CartesianChart frame can include zero or one <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/xaxis/"><code>XAxis</code></a> component and <a href="https://tinybase.org/api/ui-react-dom-charts/functions/store-components/yaxis/"><code>YAxis</code></a> component child. These configuration children let you override inferred axis titles, numeric bounds, explicit ticks, tick counts, tick formatters, and axis-specific class names without adding more top-level chart props.</p><p><img src="https://tinybase.org/shots/axis-overrides-react-demo.png" alt="Axis Overrides demo (React)" title="[Axis Overrides](/demos/chart-components-react/axis-overrides/) demo (React)"></p><p>The <a href="https://tinybase.org/demos/chart-components-react/axis-overrides/">Axis Overrides</a> demo shows this pattern with numeric timestamps formatted as dates on the x axis, and revenue ticks formatted as dollar amounts on the y axis.</p><p>The <a href="https://tinybase.org/demos/chart-components-react/time-axes/">Time Axes</a> demo focuses on date handling directly, showing ISO date strings that infer a time scale and Unix second timestamps that use <code>scale="time"</code> and <code>timestampUnit="second"</code>.</p><p>Chart presentation is handled with CSS. The chart components emit stable SVG class names for grid lines, axes, data marks, and tooltips, so you can keep data binding in props and visual styling in stylesheets.</p><p>Read more in the <a href="https://tinybase.org/guides/building-uis-with-react/using-charts/">Using Charts</a> guide and the <a href="https://tinybase.org/demos/chart-components-react/">Chart Components (React)</a> demos.</p><p>The <code>create-tinybase</code> CLI tool also now includes a Charting app option, so you can scaffold a complete editable table with reactive chart output by running <code>npm create tinybase@latest</code>.</p><p>There are no intended breaking changes in this release. Please try the new chart components and let us know which chart types or styling hooks would be most useful next.</p><hr><h1 id="v8-4">v8.4</h1><h2 id="solid-dom-components-and-inspector">Solid DOM Components And Inspector</h2><p>This release completes TinyBase's Solid support with two new additions: the <a href="https://tinybase.org/api/ui-solid-dom/"><code>ui-solid-dom</code></a> module and the <a href="https://tinybase.org/api/ui-solid-inspector/"><code>ui-solid-inspector</code></a> module.</p><p>The <a href="https://tinybase.org/api/ui-solid-dom/"><code>ui-solid-dom</code></a> module provides browser-ready Solid components for rendering and editing TinyBase data as HTML tables. They mirror the React DOM components, but use Solid components and Accessors throughout.</p><p><img src="https://tinybase.org/shots/sortedtableinhtmltable-solid-demo.png" alt="SortedTableInHtmlTable (Solid)" title="SortedTableInHtmlTable (Solid)"></p><p>Alongside the table components, the new <a href="https://tinybase.org/api/ui-solid-inspector/"><code>ui-solid-inspector</code></a> module brings the TinyBase development inspector to Solid apps too, making it easy to inspect and edit Stores, <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 <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> during development:</p><p><img src="https://tinybase.org/shots/inspector-solid-demo.png" alt="Inspector (Solid)" title="Inspector (Solid)"></p><p>A small Solid app can use both modules together:</p>
|
|
168
168
|
|
|
169
169
|
```jsx
|
|
170
170
|
import {render} from 'solid-js/web';
|
|
@@ -202,7 +202,7 @@ console.log(typeof Inspector);
|
|
|
202
202
|
disposeAppSolid();
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
-
<p>Read more in the <a href="https://
|
|
205
|
+
<p>Read more in the <a href="https://tinybase.org/guides/building-uis-with-solid/using-solid-dom-components/">Using Solid DOM Components</a> guide and the Inspector (Solid) demo.</p><h2 id="new-solid-demos">New Solid <a href="https://tinybase.org/demos/">Demos</a></h2><p>This release also adds a complete set of Solid UI component demos, plus a <a href="https://tinybase.org/demos/countries/">Countries</a> demo and an Inspector demo, so you can see the new modules working across Stores, <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>, <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a>, and editable views.</p><p><img src="https://tinybase.org/shots/editablevalueview-solid-demo.png" alt="EditableValueView (Solid)" title="EditableValueView (Solid)"></p><p>These demos intentionally mirror the React set where possible, making it easier to compare implementation patterns across frameworks.</p><p>There are no intended breaking changes in this release. If you spot any issues with the new Solid DOM components or the Solid inspector, please let us know!</p><hr><h1 id="v8-3">v8.3</h1><h2 id="solid-support">Solid Support</h2><p>This release adds the new <a href="https://tinybase.org/api/ui-solid/"><code>ui-solid</code></a> module, bringing TinyBase's reactive <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> bindings to Solid apps. It provides Solid primitives that return Accessor functions, listener primitives that clean up with Solid's lifecycle, Provider context helpers, and view components for rendering <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> data directly in a Solid component tree.</p><p>The primitives follow Solid's fine-grained reactivity model. They read TinyBase data immediately, then update the Accessor when the underlying <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> data changes:</p>
|
|
206
206
|
|
|
207
207
|
```js
|
|
208
208
|
const solidStore = createStore().setCell('pets', 'fido', 'color', 'brown');
|
|
@@ -217,7 +217,7 @@ createRoot((dispose) => {
|
|
|
217
217
|
});
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
<p>The module also includes Solid view components and a <a href="https://
|
|
220
|
+
<p>The module also includes Solid view components and a <a href="https://tinybase.org/api/the-essentials/using-react/provider/"><code>Provider</code></a> component, so you can assemble UI directly from TinyBase data while still taking advantage of Solid's selective updates:</p>
|
|
221
221
|
|
|
222
222
|
```jsx
|
|
223
223
|
const solidApp = document.createElement('div');
|
|
@@ -240,7 +240,7 @@ console.log(solidApp.textContent);
|
|
|
240
240
|
disposeSolid();
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
<p>Read more in the <a href="https://
|
|
243
|
+
<p>Read more in the <a href="https://tinybase.org/guides/building-uis-with-solid/">Building UIs With Solid</a> guides and the <a href="https://tinybase.org/api/ui-solid/"><code>ui-solid</code></a> module documentation.</p><p>A huge thanks to <a href="https://github.com/djgrant">Daniel Grant</a> for designing and implementing this new Solid support! Please let us know how it works for you and if you have any feedback or suggestions.</p><h2 id="queries-from-queries"><a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> From <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a></h2><p>Also in this release, <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> queries can now use the result of another query as their source. This lets you build complex results in small, readable steps - for example, first finding all dogs, and then querying that result to find just the brown ones:</p>
|
|
244
244
|
|
|
245
245
|
```js
|
|
246
246
|
import {createQueries} from 'tinybase';
|
|
@@ -265,7 +265,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
265
265
|
// -> {fido: {color: 'brown'}}
|
|
266
266
|
```
|
|
267
267
|
|
|
268
|
-
<p>The <code>true</code> argument tells setQueryDefinition that <code>dogs</code> is another query result, not a <a href="https://
|
|
268
|
+
<p>The <code>true</code> argument tells setQueryDefinition that <code>dogs</code> is another query result, not a <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a> in the underlying <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>. This works in query clauses too, so you can select or join from query results as your <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> definitions become more modular.</p><h2 id="schematizer-enums"><a href="https://tinybase.org/api/schematizers/interfaces/schematizer/schematizer/"><code>Schematizer</code></a> Enums</h2><p>This release addresses enum types in the schematizers. For example, Zod enums are now schematized as string types, rather than being rejected as invalid. This is also now documented accordingly.</p><p>There are no intended breaking changes in this release. If you try the new Solid bindings in particular, please let us know how they fit your expectations of building Solid apps - and good luck!</p><hr><h1 id="v8-2">v8.2</h1><h2 id="svelte-dom-components-and-inspector">Svelte DOM Components And Inspector</h2><p>This release completes TinyBase's Svelte support with two new additions: the <a href="https://tinybase.org/api/ui-svelte-dom/"><code>ui-svelte-dom</code></a> module and the <a href="https://tinybase.org/api/ui-svelte-inspector/"><code>ui-svelte-inspector</code></a> module.</p><p>The <a href="https://tinybase.org/api/ui-svelte-dom/"><code>ui-svelte-dom</code></a> module provides browser-ready Svelte components for rendering and editing TinyBase data as HTML tables. They mirror the React DOM components, but use Svelte component composition and props throughout:</p><p><img src="https://tinybase.org/shots/sortedtableinhtmltable-svelte-demo.png" alt="SortedTableInHtmlTable (Svelte)" title="SortedTableInHtmlTable (Svelte)"></p>
|
|
269
269
|
|
|
270
270
|
```svelte
|
|
271
271
|
<script>
|
|
@@ -281,7 +281,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
281
281
|
<TableInHtmlTable tableId="pets" {store} editable />
|
|
282
282
|
```
|
|
283
283
|
|
|
284
|
-
<p>Alongside the table components, the new <a href="https://
|
|
284
|
+
<p>Alongside the table components, the new <a href="https://tinybase.org/api/ui-svelte-inspector/"><code>ui-svelte-inspector</code></a> module brings the TinyBase development inspector to Svelte apps too, making it easy to inspect and edit Stores, <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 <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> during development:</p><p><img src="https://tinybase.org/shots/inspector-svelte-demo.png" alt="Inspector (Svelte)" title="Inspector (Svelte)"></p>
|
|
285
285
|
|
|
286
286
|
```svelte
|
|
287
287
|
<script>
|
|
@@ -299,7 +299,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
299
299
|
</Provider>
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
-
<p>Read more in the <a href="https://
|
|
302
|
+
<p>Read more in the <a href="https://tinybase.org/guides/building-uis-with-svelte/using-svelte-dom-components/">Using Svelte DOM Components</a> guide and the <a href="https://tinybase.org/guides/inspecting-data/">Inspecting Data</a> guide.</p><h2 id="new-demos">New <a href="https://tinybase.org/demos/">Demos</a></h2><p>This release also adds a complete set of Svelte UI component demos, plus an Inspector demo, so you can see the new modules working across Stores, <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>, <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a>, and editable views.</p><p><img src="https://tinybase.org/shots/editablevalueview-svelte-full-demo.png" alt="EditableValueView (Svelte)" title="EditableValueView (Svelte)"></p><p>These demos intentionally mirror the React set where possible, making it easier to compare implementation patterns across frameworks.</p><p>There are no intended breaking changes in this release. If you spot any issues with the new Svelte DOM components or the Svelte inspector, please let us know!</p><hr><h1 id="v8-1">v8.1</h1><h2 id="svelte-support">Svelte Support</h2><p>This highly-anticipated release introduces the new <a href="https://tinybase.org/api/ui-svelte/"><code>ui-svelte</code></a> module, bringing native Svelte 5 runes-based reactive bindings to TinyBase. The module provides reactive functions and view components for building reactive UIs without any additional state management.</p><p>Reactive functions return a reactive object backed by Svelte's reactivity. Any component that reads <code>current</code> from it will automatically re-render when the underlying TinyBase data changes:</p>
|
|
303
303
|
|
|
304
304
|
```svelte
|
|
305
305
|
<script>
|
|
@@ -313,7 +313,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
313
313
|
<p>Color: {color.current}</p>
|
|
314
314
|
```
|
|
315
315
|
|
|
316
|
-
<p>The <a href="https://
|
|
316
|
+
<p>The <a href="https://tinybase.org/api/ui-svelte/functions/getter/getcell/"><code>getCell</code></a> function and the <a href="https://tinybase.org/api/ui-svelte/functions/getter/getvalue/"><code>getValue</code></a> function provide a writable <code>current</code> property that pairs naturally with Svelte's <code>bind:</code> directive for two-way data binding:</p>
|
|
317
317
|
|
|
318
318
|
```svelte
|
|
319
319
|
<script>
|
|
@@ -325,7 +325,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
325
325
|
<input bind:value={color.current} />
|
|
326
326
|
```
|
|
327
327
|
|
|
328
|
-
<p>All reactive functions accept reactive getter functions as parameters — the <a href="https://
|
|
328
|
+
<p>All reactive functions accept reactive getter functions as parameters — the <a href="https://tinybase.org/api/ui-svelte/type-aliases/identity/maybegetter/"><code>MaybeGetter</code></a> type (<code>T | (() => T)</code>) — so passing <code>() => rowId</code> from a <code>$state</code> variable causes the function to reactively track which row it reads, without unmounting and remounting.</p><p>The module further includes a provider component and context helpers for sharing TinyBase objects across a component tree, and many built-in view components for assembling UIs directly from <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> data.</p><p>Read more in the <a href="https://tinybase.org/api/ui-svelte/"><code>ui-svelte</code></a> module documentation and the <a href="https://tinybase.org/guides/building-uis-with-svelte/">Building UIs With Svelte</a> guide.</p><h2 id="new-demos">New <a href="https://tinybase.org/demos/">Demos</a></h2><p>To showcase the new Svelte support, we have created two new Svelte-specific demos: a <a href="https://tinybase.org/demos/hello-world/hello-world-svelte/">Hello World (Svelte)</a> demo and a <a href="https://tinybase.org/demos/countries/countries-svelte/">Countries (Svelte)</a> demo. Check them out to see the new module in action.</p><p>The <code>create-tinybase</code> CLI tool also now includes an option to create a Svelte demo project, so you can easily get started with Svelte and TinyBase in exactly the same way you can with React:</p>
|
|
329
329
|
|
|
330
330
|
```bash
|
|
331
331
|
> npm create tinybase@latest
|
|
@@ -333,7 +333,7 @@ console.log(queryQueries.getResultTable('brownDogs'));
|
|
|
333
333
|
📦 Creating your project...
|
|
334
334
|
```
|
|
335
335
|
|
|
336
|
-
<h2 id="breaking-changes">Breaking <a href="https://
|
|
336
|
+
<h2 id="breaking-changes">Breaking <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a></h2><p>If you tried the <a href="https://tinybase.org/api/ui-svelte/"><code>ui-svelte</code></a> module in earlier beta releases, there are some intentional breaking changes made to ensure the <a href="https://tinybase.org/api/">API</a> is more idiomatic for Svelte. What was <code>useX</code> is now a reactive <code>getX</code> or <code>hasX</code> function, so for example <code>useCell</code> has become the <a href="https://tinybase.org/api/ui-svelte/functions/getter/getcell/"><code>getCell</code></a> function and <code>useHasCell</code> has become the <a href="https://tinybase.org/api/ui-svelte/functions/getter/hascell/"><code>hasCell</code></a> function. Context lookups also use <code>getX</code>, as with the <a href="https://tinybase.org/api/ui-svelte/functions/getter/getmetrics/"><code>getMetrics</code></a> function, but those return TinyBase objects directly from Provider context rather than reactive <code>current</code>-based wrappers. <a href="https://tinybase.org/api/ui-svelte/functions/listener/">Listener functions</a> now use <code>onX</code>; so for example <code>useCellListener</code> has become the <a href="https://tinybase.org/api/ui-svelte/functions/listener/oncell/"><code>onCell</code></a> function. The old <code>useBindableCell</code> and <code>useBindableValue</code> beta names have also gone away because the <a href="https://tinybase.org/api/ui-svelte/functions/getter/getcell/"><code>getCell</code></a> function and <a href="https://tinybase.org/api/ui-svelte/functions/getter/getvalue/"><code>getValue</code></a> function expose the writable scalar accessors directly.</p><p>This release also contains a minor breaking change since v8.0. The <code>tinybase/omni</code> module no longer includes the <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module, <a href="https://tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module, or <a href="https://tinybase.org/api/ui-react-inspector/"><code>ui-react-inspector</code></a> module. Since the <a href="https://tinybase.org/api/ui-svelte/"><code>ui-svelte</code></a> module exports many of the same names, including both in a single flat namespace would cause silent name collisions.</p><p>If you were importing React UI helpers from <code>tinybase/omni</code>, update your imports:</p>
|
|
337
337
|
|
|
338
338
|
```js ignore
|
|
339
339
|
// Before
|
|
@@ -344,7 +344,7 @@ import {createStore} from 'tinybase/omni';
|
|
|
344
344
|
import {useCell, Provider} from 'tinybase/ui-react';
|
|
345
345
|
```
|
|
346
346
|
|
|
347
|
-
<p>(Sorry about that!)</p><h2 id="we-need-your-help">We need your help</h2><p>We hope you enjoy exploring this early new Svelte support. But we really need feedback on how it works and whether or not you find it easy and idiomatic to work with! Please let us know in the issues, discussions, or on social media. Thanks and good luck!</p><hr><h1 id="v8-0">v8.0</h1><h2 id="object-and-array-types">Object And Array Types</h2><p>This release extends the range of types that a <a href="https://
|
|
347
|
+
<p>(Sorry about that!)</p><h2 id="we-need-your-help">We need your help</h2><p>We hope you enjoy exploring this early new Svelte support. But we really need feedback on how it works and whether or not you find it easy and idiomatic to work with! Please let us know in the issues, discussions, or on social media. Thanks and good luck!</p><hr><h1 id="v8-0">v8.0</h1><h2 id="object-and-array-types">Object And Array Types</h2><p>This release extends the range of types that 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> can hold. Previously, TinyBase supported <code>string</code>, <code>number</code>, <code>boolean</code>, and (since v7.0) <code>null</code>. Now you can also store plain JavaScript <strong>objects</strong> and <strong>arrays</strong> directly in a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</p>
|
|
348
348
|
|
|
349
349
|
```js
|
|
350
350
|
const store = createStore();
|
|
@@ -362,7 +362,7 @@ console.log(store.getCell('pets', 'fido', 'vaccinations'));
|
|
|
362
362
|
// -> ['rabies', 'distemper', 'parvovirus']
|
|
363
363
|
```
|
|
364
364
|
|
|
365
|
-
<p>Internally, objects and arrays are stored as JSON-encoded strings with a special prefix character, so they round-trip transparently through persistence layers. But in and out of your application code, the <a href="https://
|
|
365
|
+
<p>Internally, objects and arrays are stored as JSON-encoded strings with a special prefix character, so they round-trip transparently through persistence layers. But in and out of your application code, the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> <a href="https://tinybase.org/api/">API</a> always expects or returns them as native JavaScript values.</p><p><a href="https://tinybase.org/guides/schemas/">Schemas</a> also gain <code>object</code> and <code>array</code> as valid types:</p>
|
|
366
366
|
|
|
367
367
|
```js
|
|
368
368
|
store.setTablesSchema({
|
|
@@ -380,7 +380,7 @@ console.log(store.getRow('pets', 'fido'));
|
|
|
380
380
|
store.delSchema();
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
-
<p>Note that TinyBase does not deeply validate the contents of objects or arrays when a schema is applied - it simply checks that the value is of the right top-level type. For deeper validation, consider combining with a <a href="https://
|
|
383
|
+
<p>Note that TinyBase does not deeply validate the contents of objects or arrays when a schema is applied - it simply checks that the value is of the right top-level type. For deeper validation, consider combining with a <a href="https://tinybase.org/guides/the-basics/using-middleware/">Middleware</a> callback. On which note...</p><h2 id="introducing-middleware">Introducing <a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a></h2><p>This release introduces a powerful new system for intercepting and transforming data as it flows into your TinyBase <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>. <a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> callbacks can be registered to fire before data is written to the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, allowing you to modify, validate, or even reject changes before they take effect.</p>
|
|
384
384
|
|
|
385
385
|
```jsx
|
|
386
386
|
import {createMiddleware} from 'tinybase';
|
|
@@ -396,7 +396,7 @@ middleware.addWillSetCellCallback((tableId, rowId, cellId, cell) => {
|
|
|
396
396
|
});
|
|
397
397
|
```
|
|
398
398
|
|
|
399
|
-
<p>Read more in our new comprehensive <a href="https://
|
|
399
|
+
<p>Read more in our new comprehensive <a href="https://tinybase.org/guides/using-middleware/">Using Middleware</a> guide, which includes examples of using <a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> for data validation, transformation, and more.</p><p><a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> complements listeners but is distinct in that it runs before changes are applied to the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>, whereas listeners run after. <a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> can modify the data that listeners see, and can prevent changes from being applied at all by returning <code>undefined</code>. In conjunction with schemas, <a href="https://tinybase.org/api/middleware/interfaces/middleware/middleware/"><code>Middleware</code></a> provides a powerful way to enforce data integrity and implement complex data transformations - and it should work in synchronization environments too.</p><p>Many, many thanks to <a href="https://github.com/bitmage">Brandon Mason</a> for designing and implementing this concept. Despite the major version number, we trust there are no breaking changes in this release. But please let us know if you find any!</p><hr><h1 id="v7-3">v7.3</h1><h2 id="introducing-state-hooks">Introducing State Hooks</h2><p>This release introduces a new family of convenience hooks that follow React's <code>useState</code> pattern, making it even easier to read and write TinyBase data in your React components.</p><p>Each state hook returns a tuple containing both the current value and a setter function, eliminating the need to use separate getter and setter hooks.</p><p><a href="https://tinybase.org/api/ui-react/functions/state-hooks/">State hooks</a> combine the functionality of getter hooks (like the <a href="https://tinybase.org/api/the-essentials/using-react/userow/"><code>useRow</code></a> hook) and setter callback hooks (like the <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usesetrowcallback/"><code>useSetRowCallback</code></a> hook) into a single, convenient <a href="https://tinybase.org/api/">API</a> that feels just like React's <code>useState</code>:</p>
|
|
400
400
|
|
|
401
401
|
```jsx
|
|
402
402
|
import {useCellState} from 'tinybase/ui-react';
|
|
@@ -418,7 +418,7 @@ const PetEditor = () => {
|
|
|
418
418
|
};
|
|
419
419
|
```
|
|
420
420
|
|
|
421
|
-
<h2 id="available-state-hooks">Available State Hooks</h2><p>This release includes eight new state hooks covering the most common data access patterns:</p><ul><li>The <a href="https://
|
|
421
|
+
<h2 id="available-state-hooks">Available State Hooks</h2><p>This release includes eight new state hooks covering the most common data access patterns:</p><ul><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usetablesstate/"><code>useTablesState</code></a> hook for reading and writing all <a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usetablestate/"><code>useTableState</code></a> hook for reading and writing a single <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/userowstate/"><code>useRowState</code></a> hook for reading and writing a single <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usecellstate/"><code>useCellState</code></a> hook for reading and writing a single <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usevaluesstate/"><code>useValuesState</code></a> hook for reading and writing all <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usevaluestate/"><code>useValueState</code></a> hook for reading and writing a single <a href="https://tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/useparamvaluesstate/"><code>useParamValuesState</code></a> hook for reading and writing all query <a href="https://tinybase.org/api/queries/type-aliases/params/paramvalues/"><code>ParamValues</code></a></li><li>The <a href="https://tinybase.org/api/ui-react/functions/state-hooks/useparamvaluestate/"><code>useParamValueState</code></a> hook for reading and writing a single query <a href="https://tinybase.org/api/queries/type-aliases/params/paramvalue/"><code>ParamValue</code></a></li></ul><p>These hopefully mean less boilerplate, are particularly useful when building forms, editors, or any interactive UI that needs bidirectional data binding.</p><h2 id="demo-updates">Demo Updates</h2><p>We've updated a few of the demos to showcase these new state hooks:</p><ul><li>The <a href="https://tinybase.org/demos/countries/">Countries</a> demo now uses the <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usecellstate/"><code>useCellState</code></a> hook for the star/unstar toggle functionality.</li><li>The <a href="https://tinybase.org/demos/todo-app/">Todo App</a> demo uses the <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usecellstate/"><code>useCellState</code></a> hook to simplify todo completion toggling, and the <a href="https://tinybase.org/api/ui-react/functions/state-hooks/usevaluestate/"><code>useValueState</code></a> hook for managing the selected type filter.</li><li>The <a href="https://tinybase.org/demos/car-analysis/">Car Analysis</a> demo uses the <a href="https://tinybase.org/api/ui-react/functions/state-hooks/useparamvaluestate/"><code>useParamValueState</code></a> hook to manage query parameters for dimensions, measures, and aggregates. Much more elegant!</li></ul><p>Check out these demos to see the state hooks in action.</p><hr><h1 id="v7-2">v7.2</h1><h2 id="introducing-parameterized-queries">Introducing Parameterized <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a>!</h2><p>This release introduces parameterized queries to <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> - finally!</p><p>These allow you to define queries using named 'params' that you can then easily update to change the query's results - without redefining the whole query each time.</p><p>Let's take a look with a simple example:</p>
|
|
422
422
|
|
|
423
423
|
```js
|
|
424
424
|
store.setTable('pets', {
|
|
@@ -446,7 +446,7 @@ console.log(queries.getResultTable('petsBySpecies'));
|
|
|
446
446
|
// -> {felix: {age: 1}}
|
|
447
447
|
```
|
|
448
448
|
|
|
449
|
-
<p>You can of course have multiple params in a query definition, and use them in any part of the query definition that you would like. Listeners also work as expected - if you are listening to a query's results, and you change a param that affects those results, your listener will be called accordingly.</p><p>This is TinyBase so you should not be too surprised... but params themselves are reactive! You can get and listen to their values with the <a href="https://
|
|
449
|
+
<p>You can of course have multiple params in a query definition, and use them in any part of the query definition that you would like. Listeners also work as expected - if you are listening to a query's results, and you change a param that affects those results, your listener will be called accordingly.</p><p>This is TinyBase so you should not be too surprised... but params themselves are reactive! You can get and listen to their values with the <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/getter/getparamvalue/"><code>getParamValue</code></a> method and <a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/listener/addparamvaluelistener/"><code>addParamValueListener</code></a> method, for example.</p><p>For React users, we also shipped a bunch of new hooks that cover params in exactly the way you would expect, including the <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/usesetparamvaluecallback/"><code>useSetParamValueCallback</code></a> hook and the <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/usesetparamvaluescallback/"><code>useSetParamValuesCallback</code></a> hook, which let you easily update param values from, say, an event handler in your application.</p><p>We know this has been a long-awaited feature, so we hope you enjoy it! See the <a href="https://tinybase.org/guides/using-queries/tinyql/">TinyQL</a> guide for more details, and please let us know how it goes!</p><h2 id="demos"><a href="https://tinybase.org/demos/">Demos</a></h2><p>We have updated the <a href="https://tinybase.org/demos/movie-database/">Movie Database</a> demo to use parameterized queries, and as a result is more efficient and easier to (we think) understand. See the <code>yearGenreMovies</code>, <code>directedMovies</code>, and <code>appearedMovies</code> queries to see params in action.</p><p>We have also updated the <a href="https://tinybase.org/demos/car-analysis/">Car Analysis</a> demo to use just one single parameterized query for the whole app!</p><h2 id="full-api-additions">Full <a href="https://tinybase.org/api/">API</a> additions</h2><p>This release includes the following new <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> interface methods:</p><ul><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/getter/getparamvalues/"><code>getParamValues</code></a> method</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/getter/getparamvalue/"><code>getParamValue</code></a> method</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/configuration/setparamvalues/"><code>setParamValues</code></a> method</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/configuration/setparamvalue/"><code>setParamValue</code></a> method</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/listener/addparamvalueslistener/"><code>addParamValuesListener</code></a> method</li><li><a href="https://tinybase.org/api/queries/interfaces/queries/queries/methods/listener/addparamvaluelistener/"><code>addParamValueListener</code></a> method</li></ul><p>It also includes the following new React hooks:</p><ul><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useparamvalues/"><code>useParamValues</code></a> hook</li><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useparamvalue/"><code>useParamValue</code></a> hook</li><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/usesetparamvaluescallback/"><code>useSetParamValuesCallback</code></a> hook</li><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/usesetparamvaluecallback/"><code>useSetParamValueCallback</code></a> hook</li><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useparamvalueslistener/"><code>useParamValuesListener</code></a> hook</li><li><a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useparamvaluelistener/"><code>useParamValueListener</code></a> hook</li></ul><p>Check out the <a href="https://tinybase.org/api/">API</a> docs for each. They should seem very familiar.</p><p>Please check out this new release and let us know what you think!</p><hr><h1 id="v7-1">v7.1</h1><p>This release introduces <strong>Schematizers</strong>, a new system for converting schemas from popular validation libraries into TinyBase's schema format.</p><h2 id="schematizers">Schematizers</h2><p>Schematizers provide a bridge between external schema validation libraries (like Zod, TypeBox, and Valibot) and TinyBase's <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a> and <a href="https://tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> formats. Instead of manually writing TinyBase schemas, you can now convert existing schemas at runtime:</p>
|
|
450
450
|
|
|
451
451
|
```js
|
|
452
452
|
import {createZodSchematizer} from 'tinybase/schematizers/schematizer-zod';
|
|
@@ -471,7 +471,7 @@ console.log(schematizedStore.getRow('pets', 'fido'));
|
|
|
471
471
|
// -> {species: 'dog', age: 3, sold: false}
|
|
472
472
|
```
|
|
473
473
|
|
|
474
|
-
<p>Schematizers perform best-effort conversions, extracting basic type information (string, number, boolean), defaults, and nullable settings from your schemas.</p><p>This release includes support for:</p><ul><li><strong>Zod</strong> via the <a href="https://
|
|
474
|
+
<p>Schematizers perform best-effort conversions, extracting basic type information (string, number, boolean), defaults, and nullable settings from your schemas.</p><p>This release includes support for:</p><ul><li><strong>Zod</strong> via the <a href="https://tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer/"><code>createZodSchematizer</code></a> function</li><li><strong>TypeBox</strong> via the <a href="https://tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer/"><code>createTypeBoxSchematizer</code></a> function</li><li><strong>Valibot</strong> via the <a href="https://tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer/"><code>createValibotSchematizer</code></a> function</li><li><strong>ArkType</strong> via the <a href="https://tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer/"><code>createArkTypeSchematizer</code></a> function</li><li><strong>Yup</strong> via the <a href="https://tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer/"><code>createYupSchematizer</code></a> function</li><li><strong>Effect Schema</strong> via the <a href="https://tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer/"><code>createEffectSchematizer</code></a> function</li></ul><p>For more information, see the <a href="https://tinybase.org/guides/schemas/using-schematizers/">Using Schematizers</a> guide.</p><hr><h1 id="v7-0">v7.0</h1><p>This important (and slightly breaking!) release adds support for <code>null</code> as a valid <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> type, alongside <code>string</code>, <code>number</code>, and <code>boolean</code>.</p><h2 id="null-type-support">Null Type Support</h2><p>You can now set Cells and <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> to <code>null</code>:</p>
|
|
475
475
|
|
|
476
476
|
```js
|
|
477
477
|
store.setCell('pets', 'fido', 'species', 'dog');
|
|
@@ -503,7 +503,7 @@ store.setCell('pets', 'fido', 'species', null);
|
|
|
503
503
|
store.delSchema();
|
|
504
504
|
```
|
|
505
505
|
|
|
506
|
-
<h2 id="important-distinction-null-vs-undefined">Important Distinction: <code>null</code> vs <code>undefined</code></h2><p>It's crucial to understand the difference between <code>null</code> and <code>undefined</code> in TinyBase:</p><ul><li><code>null</code> is an explicit value. A <a href="https://
|
|
506
|
+
<h2 id="important-distinction-null-vs-undefined">Important Distinction: <code>null</code> vs <code>undefined</code></h2><p>It's crucial to understand the difference between <code>null</code> and <code>undefined</code> in TinyBase:</p><ul><li><code>null</code> is an explicit value. A <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> set to <code>null</code> exists in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li><code>undefined</code> means the <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> does not exist in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li></ul><p>This means that the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/hascell/"><code>hasCell</code></a> method will return <code>true</code> for a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> with a <code>null</code> value:</p>
|
|
507
507
|
|
|
508
508
|
```js
|
|
509
509
|
store.setCell('pets', 'fido', 'color', null);
|
|
@@ -517,7 +517,7 @@ console.log(store.hasCell('pets', 'fido', 'color'));
|
|
|
517
517
|
store.delTables();
|
|
518
518
|
```
|
|
519
519
|
|
|
520
|
-
<h2 id="breaking-change-database-persistence">Breaking Change: <a href="https://
|
|
520
|
+
<h2 id="breaking-change-database-persistence">Breaking Change: <a href="https://tinybase.org/guides/persistence/database-persistence/">Database Persistence</a></h2><p><strong>Important:</strong> This release includes a breaking change for applications using database persisters (the <a href="https://tinybase.org/api/persister-sqlite3/interfaces/persister/sqlite3persister/"><code>Sqlite3Persister</code></a>, <a href="https://tinybase.org/api/persister-postgres/interfaces/persister/postgrespersister/"><code>PostgresPersister</code></a>, or <a href="https://tinybase.org/api/persister-pglite/interfaces/persister/pglitepersister/"><code>PglitePersister</code></a> interfaces, for example).</p><p>SQL <code>NULL</code> values are now loaded as TinyBase <code>null</code> values. Previously, SQL <code>NULL</code> would result in Cells being absent from the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>. Now, SQL <code>NULL</code> maps directly to TinyBase <code>null</code>, which means:</p><ul><li><a href="https://tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a> loaded from SQL databases will be <strong>dense</strong> rather than <strong>sparse</strong></li><li>Every <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> will have every <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/id/"><code>Id</code></a> present in the table schema</li><li>Cells that were SQL <code>NULL</code> will have the value <code>null</code></li></ul><p>Example of the roundtrip transformation via a SQLite database:</p>
|
|
521
521
|
|
|
522
522
|
```js
|
|
523
523
|
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
|
|
@@ -548,7 +548,7 @@ console.log(store.getRow('pets', 'fido'));
|
|
|
548
548
|
// -> {species: 'dog', color: null}
|
|
549
549
|
```
|
|
550
550
|
|
|
551
|
-
<p>This is the correct semantic mapping since SQL databases have fixed schemas where every row must account for every column. See the <a href="https://
|
|
551
|
+
<p>This is the correct semantic mapping since SQL databases have fixed schemas where every row must account for every column. See the <a href="https://tinybase.org/guides/persistence/database-persistence/">Database Persistence</a> guide for more details.</p><h2 id="migration-guide">Migration Guide</h2><p>If you are using database persisters, you should:</p><ol><li><p><strong>Review your data access patterns</strong>: If you were checking <code>hasCell(...) === false</code> to detect missing data, you now need to check <code>getCell(...) === null</code> for null values.</p></li><li><p><strong>Update your schemas</strong>: Add <code>allowNull: true</code> to <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> definitions that should permit null values:</p></li></ol>
|
|
552
552
|
|
|
553
553
|
```js ignore
|
|
554
554
|
store.setTablesSchema({
|
|
@@ -560,7 +560,7 @@ store.setTablesSchema({
|
|
|
560
560
|
});
|
|
561
561
|
```
|
|
562
562
|
|
|
563
|
-
<ol start="3"><li><strong>Consider memory implications</strong>: Dense tables consume more memory than sparse tables. If you have large tables with many optional Cells, this could be significant.</li></ol><hr><h1 id="v6-7">v6.7</h1><p>This release includes support for the Origin Private File System (OPFS) in a browser. The <a href="https://
|
|
563
|
+
<ol start="3"><li><strong>Consider memory implications</strong>: Dense tables consume more memory than sparse tables. If you have large tables with many optional Cells, this could be significant.</li></ol><hr><h1 id="v6-7">v6.7</h1><p>This release includes support for the Origin Private File System (OPFS) in a browser. The <a href="https://tinybase.org/api/persister-browser/functions/creation/createopfspersister/"><code>createOpfsPersister</code></a> function is the main entry point, and is available in the existing <a href="https://tinybase.org/api/persister-browser/"><code>persister-browser</code></a> module:</p>
|
|
564
564
|
|
|
565
565
|
```js
|
|
566
566
|
import {createOpfsPersister} from 'tinybase/persisters/persister-browser';
|
|
@@ -580,7 +580,7 @@ await opfsPersister.load();
|
|
|
580
580
|
await opfsPersister.destroy();
|
|
581
581
|
```
|
|
582
582
|
|
|
583
|
-
<p>That's it! If you've used other TinyBase persisters, this <a href="https://
|
|
583
|
+
<p>That's it! If you've used other TinyBase persisters, this <a href="https://tinybase.org/api/">API</a> should be easy and familiar to use.</p><p>One caveat: observability in OPFS is not yet standardized in browsers. This means that the auto-load functionality of the persister may not work as expected, although a best effort is made using the experimental FileSystemObserverAPI, so please let us know how that works!</p><hr><h1 id="v6-6">v6.6</h1><p>This release improves the Inspector tool, making it easier to debug, inspect, and mutate your TinyBase stores.</p><p><img src="https://tinybase.org/shots/inspector-react-demo.png" alt="Inspector" title="Inspector"></p><p>As well as a modernized UI, new in this release is the ability to create, duplicate, or delete tables, rows, values and cells directly within the Inspector. Press the 'pencil' icon to start editing items, and then hover over the new icons to see how to manipulate the data.</p><p>See the <a href="https://tinybase.org/guides/inspecting-data/">Inspecting Data</a> guide for more information about how to use the Inspector in your application during development.</p><h1 id="v6-5">v6.5</h1><p>This release includes the new <a href="https://tinybase.org/api/persister-react-native-mmkv/"><code>persister-react-native-mmkv</code></a> module, which allows you to persist data in a React Native MMKV store via the <a href="https://github.com/mrousavy/react-native-mmkv">react-native-mmkv</a> library.</p><p>Usage should be as simple as this:</p>
|
|
584
584
|
|
|
585
585
|
```js ignore
|
|
586
586
|
import {createMMKV} from 'react-native-mmkv';
|
|
@@ -594,7 +594,7 @@ await persister.save();
|
|
|
594
594
|
// Store will be saved to the MMKV store.
|
|
595
595
|
```
|
|
596
596
|
|
|
597
|
-
<p>A huge shout out to <a href="https://github.com/JeremyBarbet">Jérémy Barbet</a> for this new persister!</p><hr><h1 id="v6-4">v6.4</h1><p>This release includes the new <a href="https://
|
|
597
|
+
<p>A huge shout out to <a href="https://github.com/JeremyBarbet">Jérémy Barbet</a> for this new persister!</p><hr><h1 id="v6-4">v6.4</h1><p>This release includes the new <a href="https://tinybase.org/api/persister-react-native-sqlite/"><code>persister-react-native-sqlite</code></a> module, which allows you to persist data in a React Native SQLite database via the <a href="https://github.com/andpor/react-native-sqlite-storage">react-native-sqlite-storage</a> library.</p><p>Usage should be as simple as this:</p>
|
|
598
598
|
|
|
599
599
|
```js ignore
|
|
600
600
|
import {enablePromise, openDatabase} from 'react-native-sqlite-storage';
|
|
@@ -610,7 +610,7 @@ await persister.save();
|
|
|
610
610
|
// Store will be saved to the database.
|
|
611
611
|
```
|
|
612
612
|
|
|
613
|
-
<p>Please let us know how you get on with this new <a href="https://
|
|
613
|
+
<p>Please let us know how you get on with this new <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>, and if you have any feedback or suggestions.</p><hr><h1 id="v6-3">v6.3</h1><p>This release includes the new <a href="https://tinybase.org/api/persister-durable-object-sql-storage/"><code>persister-durable-object-sql-storage</code></a> module, which allows you to persist data in a Cloudflare Durable Object's SQLite-based storage in conjunction with websocket-based synchronization (using the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> class).</p><p>Huge thanks to <a href="https://github.com/acoreyj">Corey Jepperson</a> for implementing the entirety of this functionality!</p>
|
|
614
614
|
|
|
615
615
|
```js ignore
|
|
616
616
|
import {createMergeableStore} from 'tinybase';
|
|
@@ -635,20 +635,20 @@ export class MyDurableObject extends WsServerDurableObject {
|
|
|
635
635
|
}
|
|
636
636
|
```
|
|
637
637
|
|
|
638
|
-
<p>Prior to this release, the only way to persist data in a Durable Object was to use the <a href="https://
|
|
638
|
+
<p>Prior to this release, the only way to persist data in a Durable Object was to use the <a href="https://tinybase.org/api/persister-durable-object-storage/"><code>persister-durable-object-storage</code></a> module, which uses CloudFlare's key-value storage backend behind the scenes.</p><p>However, Cloudflare's SQLite storage backend for Durable Objects offers significantly better pricing compared to the key-value storage backend. The SQLite storage backend is Cloudflare's recommended storage option for new Durable Object namespaces.</p><p>Note that, before using this persister, you must configure your Durable Object class to use SQLite storage by adding a migration to your <code>wrangler.toml</code> or <code>wrangler.json</code> configuration file. Use <code>new_sqlite_classes</code> in your migration configuration to enable SQLite storage for your Durable Object class. See the module documentation for more information.</p><p>This release also addresses a local-storage persistence issue, #<a href="https://github.com/tinyplex/tinybase/issues/257">257</a>.</p><hr><h1 id="v6-2">v6.2</h1><p>This release contains various packaging improvements and exposes some internal HLC functions that are useful for people building their own persisters or synchronizers.</p><h2 id="new-omni-module">New <code>omni</code> module</h2><p>There is a new <code>omni</code> module that is an explicit superset of everything in the TinyBase ecosystem. It exports the features and functionality of every <code>tinybase/*</code> module, including every persister, every synchronizer, and every UI component. This is useful for applications that want to use multiple facets of the overall TinyBase ecosystem and also benefit from the fact they share a lot of code internally.</p>
|
|
639
639
|
|
|
640
640
|
```js ignore
|
|
641
641
|
import {createStore, createSqliteBunPersister} from 'tinybase/omni';
|
|
642
642
|
```
|
|
643
643
|
|
|
644
|
-
<p>However, it should go without saying that you should only use the <code>omni</code> module if you have an aggressive tree-shaking bundler that can remove all the persisters, synchronizers, and so on, that you do <em>not</em> use. Experiment with different bundler configurations to see what works best for your usage.</p><h2 id="with-schema-exports">with-schema exports</h2><p>This release changes the <code>package.json</code> exports slightly so that imports of both <code>/with-schema</code> and non-schema'd versions of the modules resolve to the same JavaScript file. This reduces bundle size for apps that use both schema and non-schema imports.</p><h2 id="hlc-hash-functions">HLC & hash functions</h2><p>The <a href="https://
|
|
644
|
+
<p>However, it should go without saying that you should only use the <code>omni</code> module if you have an aggressive tree-shaking bundler that can remove all the persisters, synchronizers, and so on, that you do <em>not</em> use. Experiment with different bundler configurations to see what works best for your usage.</p><h2 id="with-schema-exports">with-schema exports</h2><p>This release changes the <code>package.json</code> exports slightly so that imports of both <code>/with-schema</code> and non-schema'd versions of the modules resolve to the same JavaScript file. This reduces bundle size for apps that use both schema and non-schema imports.</p><h2 id="hlc-hash-functions">HLC & hash functions</h2><p>The <a href="https://tinybase.org/api/common/"><code>common</code></a> module (and hence tinybase module) now export the <a href="https://tinybase.org/api/common/functions/stamps/gethlcfunctions/"><code>getHlcFunctions</code></a> function. This returns set of seven functions that can be used to create and manipulate HLC (Hybrid Logical Clock) timestamps.</p>
|
|
645
645
|
|
|
646
646
|
```js
|
|
647
647
|
import {getHlcFunctions} from 'tinybase';
|
|
648
648
|
const [getNextHlc, seenHlc, encodeHlc] = getHlcFunctions();
|
|
649
649
|
```
|
|
650
650
|
|
|
651
|
-
<p>There are also several functions to help hash tabular and key-value data in a way that is compatible with the internal <a href="https://
|
|
651
|
+
<p>There are also several functions to help hash tabular and key-value data in a way that is compatible with the internal <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> implementation. These include the <a href="https://tinybase.org/api/common/functions/hash/gethash/"><code>getHash</code></a> function and the <a href="https://tinybase.org/api/common/functions/hash/getcellhash/"><code>getCellHash</code></a> function, for example.</p><p>These are for pretty advanced use-cases! But you can use these in your own systems to ensure the timestamps and hashes are compatible with the ones generated in TinyBase <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> objects.</p><h2 id="moved-types">Moved types</h2><p>The rarely-used <a href="https://tinybase.org/api/common/type-aliases/stamps/getnow/"><code>GetNow</code></a> and <a href="https://tinybase.org/api/common/type-aliases/stamps/hash/"><code>Hash</code></a> types have been moved from the <a href="https://tinybase.org/api/mergeable-store/"><code>mergeable-store</code></a> module into the <a href="https://tinybase.org/api/common/"><code>common</code></a> module.</p><hr><h1 id="v6-1">v6.1</h1><h2 id="in-summary">In Summary</h2><ul><li><a href="#bun-sqlite">A new Persister for Bun</a>'s embedded SQLite database.</li><li><a href="#subset-persistence">Subset persistence</a> to load subsets of tables into a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li><a href="#destructured-object-arguments-for-sorted-row-ids">Destructured object arguments</a> for sorted <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> methods and hooks.</li><li><a href="#new-startautopersisting-method">A new startAutoPersisting method</a>.</li></ul><p>And more!</p><h2 id="bun-sqlite">Bun SQLite</h2><p>This release includes a new <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> for the <a href="https://bun.sh/docs/api/sqlite">embedded SQLite database</a> available in the Bun runtime.</p><p>You use it by passing a reference to a Bun Database object into the <a href="https://tinybase.org/api/persister-sqlite-bun/functions/creation/createsqlitebunpersister/"><code>createSqliteBunPersister</code></a> function:</p>
|
|
652
652
|
|
|
653
653
|
```js bun
|
|
654
654
|
import {Database} from 'bun:sqlite';
|
|
@@ -676,7 +676,7 @@ console.log(store.getTables());
|
|
|
676
676
|
await persister.destroy();
|
|
677
677
|
```
|
|
678
678
|
|
|
679
|
-
<p>There's more information the documentation for the new <a href="https://
|
|
679
|
+
<p>There's more information the documentation for the new <a href="https://tinybase.org/api/persister-sqlite-bun/"><code>persister-sqlite-bun</code></a> module.</p><h2 id="subset-persistence">Subset persistence</h2><p>Persisters that load and save data to an underlying database can now be configured to only load a <em>subset</em> of the rows in a table into a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</p><p>This is useful for reducing the amount of data that is loaded into memory, or for working with a subset of data that is relevant to the current user, for example.</p><p>Do this by specifying a <code>condition</code> in the <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> configuration. This is a single string argument which is used as a SQL <code>WHERE</code> clause when reading and observing data in the table.</p><p>For example, the following code will only load rows from the <code>pets</code> database table where the <code>sold</code> column is set to <code>0</code>:</p>
|
|
680
680
|
|
|
681
681
|
```js ignore
|
|
682
682
|
const subsetPersister = createSqliteWasmPersister(store, sqlite3, db, {
|
|
@@ -688,7 +688,7 @@ const subsetPersister = createSqliteWasmPersister(store, sqlite3, db, {
|
|
|
688
688
|
});
|
|
689
689
|
```
|
|
690
690
|
|
|
691
|
-
<p>See the '<a href="https://
|
|
691
|
+
<p>See the '<a href="https://tinybase.org/guides/persistence/database-persistence/#loading-subsets-of-database-tables">Loading subsets of database tables</a>' section of the <a href="https://tinybase.org/guides/persistence/database-persistence/">Database Persistence</a> guide for more details. And a huge thank you to Jakub Riedl (<a href="https://github.com/jakubriedl">@jakubriedl</a>) for landing this functionality!</p><h2 id="destructured-object-arguments-for-sorted-row-ids">Destructured object arguments for sorted <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></h2><p>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getsortedrowids/"><code>getSortedRowIds</code></a> method on the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> interface has a number of optional parameters and it can be tiresome to fill in the defaults if you only want to change the last one, for example. So this release introduces an override such that you can pass an object with the parameters as properties.</p><p>So instead of:</p>
|
|
692
692
|
|
|
693
693
|
```js ignore
|
|
694
694
|
store.getSortedRowIds('pets', undefined, undefined, undefined, 10);
|
|
@@ -700,7 +700,7 @@ store.getSortedRowIds('pets', undefined, undefined, undefined, 10);
|
|
|
700
700
|
store.getSortedRowIds({tableId: 'pets', limit: 10});
|
|
701
701
|
```
|
|
702
702
|
|
|
703
|
-
<p>This pattern is also made available to the <a href="https://
|
|
703
|
+
<p>This pattern is also made available to the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addsortedrowidslistener/"><code>addSortedRowIdsListener</code></a> method, the <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usesortedrowids/"><code>useSortedRowIds</code></a> hook, and the <a href="https://tinybase.org/api/ui-react/functions/store-hooks/usesortedrowidslistener/"><code>useSortedRowIdsListener</code></a> hook.</p><h2 id="new-startautopersisting-method">New <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/startautopersisting/"><code>startAutoPersisting</code></a> method</h2><p>The new <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/startautopersisting/"><code>startAutoPersisting</code></a> method and <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/stopautopersisting/"><code>stopAutoPersisting</code></a> method on the <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> interface act as convenience methods for starting (and stopping) both the automatic loading and saving of data.</p><h2 id="new-createmergeablestore-getnow-parameter">New createMergeableStore getNow parameter</h2><p>The <a href="https://tinybase.org/api/the-essentials/creating-stores/createmergeablestore/"><code>createMergeableStore</code></a> function now takes an optional <code>getNow</code> argument that lets you override the clock used to generate HLC timestamps.</p><h2 id="asynchronous-persister-synchronizer-methods">Asynchronous <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> & <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> methods</h2><p>Please note that some methods in the <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> and <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> APIs are now asynchronous. Although most implementations of these methods are synchronous, some (particularly for Postgres-based databases) are no longer so and you are recommended to await them all.</p><p>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/load/stopautoload/"><code>stopAutoLoad</code></a> method, the <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/save/stopautosave/"><code>stopAutoSave</code></a> method, and the <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/methods/lifecycle/destroy/"><code>destroy</code></a> method in the base <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> interface have been marked asynchronous and return Promises. The <a href="https://tinybase.org/api/synchronizers/interfaces/synchronizer/synchronizer/methods/synchronization/stopsync/"><code>stopSync</code></a> method in the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> interface and the <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/methods/lifecycle/destroy/"><code>destroy</code></a> method in the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> server interfaces should also be considered asynchronous.</p><hr><h1 id="v6-0">v6.0</h1><p>This major release is about updating dependencies and infrastructure rather than adding new features.</p><p>The most notable changes for users are:</p><ul><li>The package distribution only includes modern ESM packages (both minified and non-minified).</li><li>React 19 is now compatible as an optional peer dependency.</li><li>The tools module and TinyBase CLI have been removed.</li></ul><p>If you have been using CJS or UMD packages, you will need to update your bundling strategy for TinyBase (in the same way that you will have had to have done for React 19, for example) but this change should be compatible with most packaging tools. If you had been using the library directly a browser, you should consider the <a href="https://esm.sh/">esm.sh</a> CDN, as we have for our demos.</p><p>As a result of these changes, there have been some additional knock-on effects to the project and developer infrastructure as a whole. For example:</p><ul><li>The test suite has been updated to use <code>react-testing-library</code> instead of <code>react-test-renderer</code>.</li><li>The React <code>jsx-runtime</code> is used for JSX transformations.</li><li><a href="https://tinybase.org/demos/">Demos</a> (and CodePen examples) have been updated to use an <code>importmap</code> mapping the modules to the <a href="https://esm.sh/">esm.sh</a> CDN.</li><li>ESLint has finally been upgraded to v9.</li></ul><p>Note that TinyBase v6.0 adds no new functionality, so you can afford to stay on v5.4.x for a while if these changes are somehow incompatible for you. However, all future functionality changes and bug fixes <em>will</em> take effect as v6.x releases (and probably won't be back-ported to v5.4.x), so you should endeavor to upgrade as soon as you can.</p><p>Please let us know how these changes find you, and please file an issue on GitHub if you need help adapting to any of them.</p><hr><h1 id="v5-4">v5.4</h1><h2 id="durable-objects-synchronization">Durable Objects synchronization</h2><p>This release contains a new WebSocket synchronization server that runs on Cloudflare as a Durable Object.</p><p><embed src="https://tinybase.org/durable.svg" title="Durable Objects"></p><p>It's in the new <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/"><code>synchronizer-ws-server-durable-object</code></a> module, and you use it by extending the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a> class. Use the <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/functions/creation/getwsserverdurableobjectfetch/"><code>getWsServerDurableObjectFetch</code></a> function for conveniently binding your Cloudflare Worker to your Durable Object:</p>
|
|
704
704
|
|
|
705
705
|
```js ignore
|
|
706
706
|
import {
|
|
@@ -721,7 +721,7 @@ name = "MyDurableObjects"
|
|
|
721
721
|
class_name = "MyDurableObject"
|
|
722
722
|
```
|
|
723
723
|
|
|
724
|
-
<p>With this you can now easily connect and synchronize clients that are using the <a href="https://
|
|
724
|
+
<p>With this you can now easily connect and synchronize clients that are using the <a href="https://tinybase.org/api/synchronizer-ws-client/interfaces/synchronizer/wssynchronizer/"><code>WsSynchronizer</code></a> synchronizer.</p><h2 id="durable-objects-persistence">Durable Objects <a href="https://tinybase.org/guides/persistence/">Persistence</a></h2><p>But wait! There's more. Durable Objects also provide a storage mechanism, and sometimes you want TinyBase data to also be stored on the server (in case all the current clients disconnect and a new one joins, for example). So this release of TinyBase also includes a dedicated persister, the <a href="https://tinybase.org/api/persister-durable-object-storage/interfaces/persister/durableobjectstoragepersister/"><code>DurableObjectStoragePersister</code></a>, that also synchronizes the data to the Durable Object storage layer.</p><p>You create it with the <a href="https://tinybase.org/api/persister-durable-object-storage/functions/creation/createdurableobjectstoragepersister/"><code>createDurableObjectStoragePersister</code></a> function, and hook it into the Durable Object by returning it from the <a href="https://tinybase.org/api/synchronizer-ws-server-durable-object/classes/creation/wsserverdurableobject/methods/creation/createpersister/"><code>createPersister</code></a> method of your <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/wsserverdurableobject/"><code>WsServerDurableObject</code></a>:</p>
|
|
725
725
|
|
|
726
726
|
```js ignore
|
|
727
727
|
export class MyDurableObject extends WsServerDurableObject {
|
|
@@ -734,7 +734,7 @@ export class MyDurableObject extends WsServerDurableObject {
|
|
|
734
734
|
}
|
|
735
735
|
```
|
|
736
736
|
|
|
737
|
-
<p>You can get started quickly with this architecture using the Durable Objects option in the <a href="https://github.com/tinyplex/create-tinybase"><code>create-tinybase</code> tool</a>.</p><h2 id="server-reference-implementation">Server Reference Implementation</h2><p>Unrelated to Durable Objects, this release also includes the new <a href="https://beta.tinybase.org/api/synchronizer-ws-server-simple/"><code>synchronizer-ws-server-simple</code></a> module that contains a simple server implementation called <a href="https://beta.tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a>. Without the complications of listeners, persistence, or statistics, this is more suitable to be used as a reference implementation for other server environments.</p><h2 id="architectural-guide">Architectural Guide</h2><p>To go with this release, we have added new documentation on ways in which you can use TinyBase in an app architecture. Check it out in the new <a href="https://beta.tinybase.org/guides/the-basics/architectural-options/">Architectural Options</a> guide.</p><p>We've also started a new section of documentation for describing integrations, of which the <a href="https://beta.tinybase.org/guides/integrations/cloudflare-durable-objects/">Cloudflare Durable Objects</a> guide, of course, is the first new entry!</p><hr><h1 id="v5-3">v5.3</h1><p>This release is focussed on a few <a href="https://beta.tinybase.org/api/">API</a> improvements and quality-of-life changes. These include:</p><h2 id="react-ssr-support">React SSR support</h2><p>Thanks to contributor <a href="https://github.com/muhajirdev">Muhammad Muhajir</a> for ensuring that TinyBase runs in server-side rendering environments!</p><h2 id="in-the-persisters-module">In the <a href="https://beta.tinybase.org/api/persisters/"><code>persisters</code></a> module...</h2><p>All <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects now expose information about whether they are loading or saving. To access this <a href="https://beta.tinybase.org/api/persisters/enumerations/lifecycle/status/"><code>Status</code></a>, use:</p><ul><li>The <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/getstatus/"><code>getStatus</code></a> method, which will return 0 when it is idle, 1 when it is loading, and 2 when it is saving.</li><li>The <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/listener/addstatuslistener/"><code>addStatusListener</code></a> method, which lets you add a <a href="https://beta.tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function and which is called whenever the status changes.</li></ul><p>These make it possible to track background load and save activities, so that, for example, you can show a status-bar spinner of asynchronous persistence activity.</p><h2 id="in-the-synchronizers-module">In the <a href="https://beta.tinybase.org/api/synchronizers/"><code>synchronizers</code></a> module...</h2><p>Synchronizers are a sub-class of <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>, so all <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> objects now also have:</p><ul><li>The <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/getstatus/"><code>getStatus</code></a> method, which will return 0 when it is idle, 1 when it is 'loading' (ie inbound syncing), and 2 when it is 'saving' (ie outbound syncing).</li><li>The <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/listener/addstatuslistener/"><code>addStatusListener</code></a> method, which lets you add a <a href="https://beta.tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function and which is called whenever the status changes.</li></ul><h2 id="in-the-ui-react-module">In the <a href="https://beta.tinybase.org/api/ui-react/"><code>ui-react</code></a> module...</h2><p>There are corresponding hooks so that you can build these status changes into a React UI easily:</p><ul><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/persister-hooks/usepersisterstatus/"><code>usePersisterStatus</code></a> hook, which will return the status for an explicitly provided, or context-derived <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/persister-hooks/usepersisterstatuslistener/"><code>usePersisterStatusListener</code></a> hook, which lets you add your own <a href="https://beta.tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function to a <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/persister-hooks/usepersister/"><code>usePersister</code></a> hook, which lets you get direct access to a <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> from within your UI.</li></ul><p>And correspondingly for Synchronizers:</p><ul><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizerstatus/"><code>useSynchronizerStatus</code></a> hook, which will return the status for an explicitly provided, or context-derived <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizerstatuslistener/"><code>useSynchronizerStatusListener</code></a> hook, which lets you add your own <a href="https://beta.tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function to a <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizer/"><code>useSynchronizer</code></a> hook, which lets you get direct access to a <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> from within your UI.</li></ul><p>In addition, this module also now includes hooks for injecting objects into the Provider context scope imperatively, much like the existing <a href="https://beta.tinybase.org/api/ui-react/functions/store-hooks/useprovidestore/"><code>useProvideStore</code></a> hook:</p><ul><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/metrics-hooks/useprovidemetrics/"><code>useProvideMetrics</code></a> hook, which lets you imperatively register <a href="https://beta.tinybase.org/api/metrics/interfaces/metrics/metrics/"><code>Metrics</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/indexes-hooks/useprovideindexes/"><code>useProvideIndexes</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/relationships-hooks/useproviderelationships/"><code>useProvideRelationships</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/queries-hooks/useprovidequeries/"><code>useProvideQueries</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/checkpoints-hooks/useprovidecheckpoints/"><code>useProvideCheckpoints</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/persister-hooks/useprovidepersister/"><code>useProvidePersister</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects.</li><li>The <a href="https://beta.tinybase.org/api/ui-react/functions/synchronizer-hooks/useprovidesynchronizer/"><code>useProvideSynchronizer</code></a> hook, which lets you register <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> objects.</li></ul><p>All of these new methods have extensive documentation, each with examples to show how to use them.</p><p>Please provide feedback on this new release on GitHub!</p><hr><h1 id="v5-2">v5.2</h1><p>This release introduces new Persisters for... PostgreSQL! TinyBase now has two new <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> modules:</p><ul><li>The <a href="https://beta.tinybase.org/api/persister-postgres/"><code>persister-postgres</code></a> module provides the <a href="https://beta.tinybase.org/api/persister-postgres/interfaces/persister/postgrespersister/"><code>PostgresPersister</code></a>, which uses the excellent <a href="https://github.com/porsager/postgres"><code>postgres</code></a> module to bind to regular PostgreSQL databases, generally on a server.</li><li>The <a href="https://beta.tinybase.org/api/persister-pglite/"><code>persister-pglite</code></a> module provides the <a href="https://beta.tinybase.org/api/persister-pglite/interfaces/persister/pglitepersister/"><code>PglitePersister</code></a>, which uses the new and exciting <a href="https://github.com/electric-sql/pglite"><code>pglite</code></a> module for running PostgreSQL... in a browser!</li></ul><p>Conceptually, things behave in the same way as they do for the various SQLite persisters. Simply use the <a href="https://beta.tinybase.org/api/persister-postgres/functions/creation/createpostgrespersister/"><code>createPostgresPersister</code></a> function (or the similar <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/createpglitepersister/"><code>createPglitePersister</code></a> function) to persist your TinyBase data:</p>
|
|
737
|
+
<p>You can get started quickly with this architecture using the Durable Objects option in the <a href="https://github.com/tinyplex/create-tinybase"><code>create-tinybase</code> tool</a>.</p><h2 id="server-reference-implementation">Server Reference Implementation</h2><p>Unrelated to Durable Objects, this release also includes the new <a href="https://tinybase.org/api/synchronizer-ws-server-simple/"><code>synchronizer-ws-server-simple</code></a> module that contains a simple server implementation called <a href="https://tinybase.org/api/synchronizer-ws-server-simple/interfaces/server/wsserversimple/"><code>WsServerSimple</code></a>. Without the complications of listeners, persistence, or statistics, this is more suitable to be used as a reference implementation for other server environments.</p><h2 id="architectural-guide">Architectural Guide</h2><p>To go with this release, we have added new documentation on ways in which you can use TinyBase in an app architecture. Check it out in the new <a href="https://tinybase.org/guides/the-basics/architectural-options/">Architectural Options</a> guide.</p><p>We've also started a new section of documentation for describing integrations, of which the <a href="https://tinybase.org/guides/integrations/cloudflare-durable-objects/">Cloudflare Durable Objects</a> guide, of course, is the first new entry!</p><hr><h1 id="v5-3">v5.3</h1><p>This release is focussed on a few <a href="https://tinybase.org/api/">API</a> improvements and quality-of-life changes. These include:</p><h2 id="react-ssr-support">React SSR support</h2><p>Thanks to contributor <a href="https://github.com/muhajirdev">Muhammad Muhajir</a> for ensuring that TinyBase runs in server-side rendering environments!</p><h2 id="in-the-persisters-module">In the <a href="https://tinybase.org/api/persisters/"><code>persisters</code></a> module...</h2><p>All <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects now expose information about whether they are loading or saving. To access this <a href="https://tinybase.org/api/persisters/enumerations/lifecycle/status/"><code>Status</code></a>, use:</p><ul><li>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/getstatus/"><code>getStatus</code></a> method, which will return 0 when it is idle, 1 when it is loading, and 2 when it is saving.</li><li>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/listener/addstatuslistener/"><code>addStatusListener</code></a> method, which lets you add a <a href="https://tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function and which is called whenever the status changes.</li></ul><p>These make it possible to track background load and save activities, so that, for example, you can show a status-bar spinner of asynchronous persistence activity.</p><h2 id="in-the-synchronizers-module">In the <a href="https://tinybase.org/api/synchronizers/"><code>synchronizers</code></a> module...</h2><p>Synchronizers are a sub-class of <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>, so all <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> objects now also have:</p><ul><li>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/lifecycle/getstatus/"><code>getStatus</code></a> method, which will return 0 when it is idle, 1 when it is 'loading' (ie inbound syncing), and 2 when it is 'saving' (ie outbound syncing).</li><li>The <a href="https://tinybase.org/api/persisters/interfaces/persister/persister/methods/listener/addstatuslistener/"><code>addStatusListener</code></a> method, which lets you add a <a href="https://tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function and which is called whenever the status changes.</li></ul><h2 id="in-the-ui-react-module">In the <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module...</h2><p>There are corresponding hooks so that you can build these status changes into a React UI easily:</p><ul><li>The <a href="https://tinybase.org/api/ui-react/functions/persister-hooks/usepersisterstatus/"><code>usePersisterStatus</code></a> hook, which will return the status for an explicitly provided, or context-derived <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/persister-hooks/usepersisterstatuslistener/"><code>usePersisterStatusListener</code></a> hook, which lets you add your own <a href="https://tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function to a <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/persister-hooks/usepersister/"><code>usePersister</code></a> hook, which lets you get direct access to a <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> from within your UI.</li></ul><p>And correspondingly for Synchronizers:</p><ul><li>The <a href="https://tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizerstatus/"><code>useSynchronizerStatus</code></a> hook, which will return the status for an explicitly provided, or context-derived <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizerstatuslistener/"><code>useSynchronizerStatusListener</code></a> hook, which lets you add your own <a href="https://tinybase.org/api/persisters/type-aliases/listener/statuslistener/"><code>StatusListener</code></a> function to a <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/synchronizer-hooks/usesynchronizer/"><code>useSynchronizer</code></a> hook, which lets you get direct access to a <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> from within your UI.</li></ul><p>In addition, this module also now includes hooks for injecting objects into the Provider context scope imperatively, much like the existing <a href="https://tinybase.org/api/ui-react/functions/store-hooks/useprovidestore/"><code>useProvideStore</code></a> hook:</p><ul><li>The <a href="https://tinybase.org/api/ui-react/functions/metrics-hooks/useprovidemetrics/"><code>useProvideMetrics</code></a> hook, which lets you imperatively register <a href="https://tinybase.org/api/metrics/interfaces/metrics/metrics/"><code>Metrics</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/indexes-hooks/useprovideindexes/"><code>useProvideIndexes</code></a> hook, which lets you register <a href="https://tinybase.org/api/indexes/interfaces/indexes/indexes/"><code>Indexes</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/relationships-hooks/useproviderelationships/"><code>useProvideRelationships</code></a> hook, which lets you register <a href="https://tinybase.org/api/relationships/interfaces/relationships/relationships/"><code>Relationships</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/queries-hooks/useprovidequeries/"><code>useProvideQueries</code></a> hook, which lets you register <a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/checkpoints-hooks/useprovidecheckpoints/"><code>useProvideCheckpoints</code></a> hook, which lets you register <a href="https://tinybase.org/api/checkpoints/interfaces/checkpoints/checkpoints/"><code>Checkpoints</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/persister-hooks/useprovidepersister/"><code>useProvidePersister</code></a> hook, which lets you register <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects.</li><li>The <a href="https://tinybase.org/api/ui-react/functions/synchronizer-hooks/useprovidesynchronizer/"><code>useProvideSynchronizer</code></a> hook, which lets you register <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> objects.</li></ul><p>All of these new methods have extensive documentation, each with examples to show how to use them.</p><p>Please provide feedback on this new release on GitHub!</p><hr><h1 id="v5-2">v5.2</h1><p>This release introduces new Persisters for... PostgreSQL! TinyBase now has two new <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> modules:</p><ul><li>The <a href="https://tinybase.org/api/persister-postgres/"><code>persister-postgres</code></a> module provides the <a href="https://tinybase.org/api/persister-postgres/interfaces/persister/postgrespersister/"><code>PostgresPersister</code></a>, which uses the excellent <a href="https://github.com/porsager/postgres"><code>postgres</code></a> module to bind to regular PostgreSQL databases, generally on a server.</li><li>The <a href="https://tinybase.org/api/persister-pglite/"><code>persister-pglite</code></a> module provides the <a href="https://tinybase.org/api/persister-pglite/interfaces/persister/pglitepersister/"><code>PglitePersister</code></a>, which uses the new and exciting <a href="https://github.com/electric-sql/pglite"><code>pglite</code></a> module for running PostgreSQL... in a browser!</li></ul><p>Conceptually, things behave in the same way as they do for the various SQLite persisters. Simply use the <a href="https://tinybase.org/api/persister-postgres/functions/creation/createpostgrespersister/"><code>createPostgresPersister</code></a> function (or the similar <a href="https://tinybase.org/api/the-essentials/persisting-stores/createpglitepersister/"><code>createPglitePersister</code></a> function) to persist your TinyBase data:</p>
|
|
738
738
|
|
|
739
739
|
```js
|
|
740
740
|
import postgres from 'postgres';
|
|
@@ -771,7 +771,7 @@ await pgPersister.destroy();
|
|
|
771
771
|
await sql.end();
|
|
772
772
|
```
|
|
773
773
|
|
|
774
|
-
<p>Note that these two <a href="https://
|
|
774
|
+
<p>Note that these two <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects support both the <code>json</code> and <code>tabular</code> modes for saving TinyBase data into the database. See the <a href="https://tinybase.org/api/persisters/type-aliases/configuration/databasepersisterconfig/"><code>DatabasePersisterConfig</code></a> type for more details. (Note however that, like the SQLite Persisters, only the <code>json</code> mode is supported for <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> instances, due to their additional CRDT metadata.)</p><p>This release also exposes the new <a href="https://tinybase.org/api/persisters/functions/creation/createcustomsqlitepersister/"><code>createCustomSqlitePersister</code></a> function and <a href="https://tinybase.org/api/persisters/functions/creation/createcustompostgresqlpersister/"><code>createCustomPostgreSqlPersister</code></a> function at the top level of the persister module. These can be used to build <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> objects against SQLite and PostgreSQL SDKs (or forks) that are not already included with TinyBase.</p><h2 id="minor-breaking-change">Minor breaking change</h2><p>It's very unlikely to affect most apps, but also be aware that the <a href="https://tinybase.org/api/persisters/"><code>persisters</code></a> module and <a href="https://tinybase.org/api/synchronizers/"><code>synchronizers</code></a> module are no longer bundled in the 'master' tinybase module. If you are using them (most likely because you have built a custom <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> or <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>), you will need to update your imports accordingly to the standalone <code>tinybase/persisters</code> and <code>tinybase/synchronizers</code> versions of them. Apologies.</p><hr><h1 id="v5-1">v5.1</h1><p>This release lets you persist data on a server using the <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> function. This makes it possible for all clients to disconnect from a path, but, when they reconnect, for the data to still be present for them to sync with.</p><p>This is done by passing in a second argument to the <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> function that creates a <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> instance (for which also need to create or provide a <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a>) for a given path:</p>
|
|
775
775
|
|
|
776
776
|
```js
|
|
777
777
|
import {createFilePersister} from 'tinybase/persisters/persister-file';
|
|
@@ -788,7 +788,7 @@ const persistingServer = createWsServer(
|
|
|
788
788
|
await persistingServer.destroy();
|
|
789
789
|
```
|
|
790
790
|
|
|
791
|
-
<p>This is a very crude (and not production-safe!) example, but demonstrates a server that will create a file, based on any path that clients connect to, and persist data to it. See the <a href="https://
|
|
791
|
+
<p>This is a very crude (and not production-safe!) example, but demonstrates a server that will create a file, based on any path that clients connect to, and persist data to it. See the <a href="https://tinybase.org/api/synchronizer-ws-server/functions/creation/createwsserver/"><code>createWsServer</code></a> function documentation for more details.</p><p>This implementation is still experimental so please kick the tires!</p><p>There is one small breaking change in this release: the functions for creating <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> objects can now take optional onSend and onReceive callbacks that will fire whenever messages pass through the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>. See, for example, the <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/createwssynchronizer/"><code>createWsSynchronizer</code></a> function. These are suitable for debugging synchronization issues in a development environment.</p><hr><h1 id="v5-0">v5.0</h1><p>We're excited to announce this major release for TinyBase! It includes important data synchronization functionality and a range of other improvements.</p><h1 id="in-summary">In Summary</h1><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 TinyBase 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>TinyBase 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's look at the major functionality in more detail!</p><h2 id="the-new-mergeablestore-type">The New <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> Type</h2><p>A key part of TinyBase 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/the-essentials/creating-stores/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>
|
|
792
792
|
|
|
793
793
|
```js
|
|
794
794
|
const localStore1 = createMergeableStore();
|
|
@@ -806,7 +806,7 @@ console.log(localStore2.getContent());
|
|
|
806
806
|
// -> [{pets: {felix: {species: 'cat'}, fido: {species: 'dog'}}}, {}]
|
|
807
807
|
```
|
|
808
808
|
|
|
809
|
-
<p>Please read the new <a href="https://
|
|
809
|
+
<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 <a href="https://tinybase.org/api/">API</a>.</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/the-essentials/creating-stores/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><h2 id="the-new-synchronizer-framework">The New <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a> Framework</h2><p>The v5.0 release also introduces the new concept of synchronization. <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/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>
|
|
810
810
|
|
|
811
811
|
```js
|
|
812
812
|
// On a server machine:
|
|
@@ -841,7 +841,7 @@ await synchronizer2.destroy();
|
|
|
841
841
|
await server.destroy();
|
|
842
842
|
```
|
|
843
843
|
|
|
844
|
-
<p>This release includes three types of <a href="https://beta.tinybase.org/api/the-essentials/synchronizing-stores/synchronizer/"><code>Synchronizer</code></a>:</p><ul><li>The <a href="https://beta.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://beta.tinybase.org/api/synchronizer-broadcast-channel/interfaces/synchronizer/broadcastchannelsynchronizer/"><code>BroadcastChannelSynchronizer</code></a> uses the browser's BroadcastChannel <a href="https://beta.tinybase.org/api/">API</a> to communicate between different tabs and workers.</li><li>The <a href="https://beta.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://beta.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://beta.tinybase.org/api/synchronizer-ws-client/interfaces/synchronizer/wssynchronizer/"><code>WsSynchronizer</code></a> systems. This can be created using the <a href="https://beta.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://beta.tinybase.org/guides/synchronization/using-a-synchronizer/">Using A Synchronizer</a> guide for more details of how to synchronize your data.</p><h2 id="improved-module-folder-structure">Improved Module Folder Structure</h2><p>We have previously found issues with legacy bundlers and other tools that didn't fully support the new <code>exports</code> field in the module's package.</p><p>To mitigate that, the TinyBase 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><h2 id="breaking-changes-in-v5-0">Breaking <a href="https://beta.tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> in v5.0</h2><h3 id="module-file-structure">Module File Structure</h3><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 TinyBase - 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 when 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><h3 id="expo-sqlite-persister">Expo SQLite <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a></h3><p>Previously the <a href="https://beta.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 'next' package. In v5.0, the <a href="https://beta.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><h3 id="the-tinybase-inspector">The TinyBase Inspector</h3><p>Previously, the React-based inspector (then known as <code>StoreInspector</code>) resided in the debug version of the <a href="https://beta.tinybase.org/api/ui-react-dom/"><code>ui-react-dom</code></a> module. It now lives in its own <a href="https://beta.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 <a href="https://beta.tinybase.org/api/">API</a> documentation for details, or the <a href="https://beta.tinybase.org/demos/ui-components-react/inspector-react/"><inspector>(React)</inspector></a>demo, for example.</p><h3 id="api-changes"><a href="https://beta.tinybase.org/api/">API</a> <a href="https://beta.tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a></h3><p>The following changes have been made to the existing TinyBase <a href="https://beta.tinybase.org/api/">API</a> for consistency. These are less common parts of the <a href="https://beta.tinybase.org/api/">API</a> 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://beta.tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a> type.</li><li>The <a href="https://beta.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://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> or <a href="https://beta.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://beta.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://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> interface:</p><ul><li>There is a new <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/applychanges/"><code>applyChanges</code></a> method.</li><li>A <a href="https://beta.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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/gettransactionchanges/"><code>getTransactionChanges</code></a> method and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/gettransactionlog/"><code>getTransactionLog</code></a> method directly instead.</li><li>Similarly, a <a href="https://beta.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://beta.tinybase.org/api/persisters/"><code>persisters</code></a> module:</p><ul><li>The <a href="https://beta.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://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> can support <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/"><code>MergeableStore</code></a> as well as <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> objects.</li><li>A <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'s <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/load/load/"><code>load</code></a> method and <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/load/startautoload/"><code>startAutoLoad</code></a> method now take a <a href="https://beta.tinybase.org/api/store/type-aliases/store/content/"><code>Content</code></a> object as one parameter, rather than <a href="https://beta.tinybase.org/api/store/type-aliases/store/tables/"><code>Tables</code></a> and <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> as two.</li><li>If you create a custom <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>, the setPersisted method now receives changes made to a <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> directly by reference, rather than via a callback. Similarly, the <a href="https://beta.tinybase.org/api/persisters/type-aliases/creation/persisterlistener/"><code>PersisterListener</code></a> you register in your addPersisterListener implementation now takes <a href="https://beta.tinybase.org/api/store/type-aliases/store/content/"><code>Content</code></a> and <a href="https://beta.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://beta.tinybase.org/api/persister-partykit-server/"><code>persister-partykit-server</code></a> module has been renamed to the broadcastChanges method.</li></ul><hr><h1 id="v4-8">v4.8</h1><p>This release includes the new <a href="https://beta.tinybase.org/api/persister-powersync/"><code>persister-powersync</code></a> module, which provides a <a href="https://beta.tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> for <a href="https://www.powersync.com/">PowerSync'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://beta.tinybase.org/api/persister-powersync/functions/creation/createpowersyncpersister/"><code>createPowerSyncPersister</code></a> function; something like:</p>
|
|
844
|
+
<p>This release includes three types of <a href="https://tinybase.org/api/the-essentials/synchronizing-stores/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's BroadcastChannel <a href="https://tinybase.org/api/">API</a> 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><h2 id="improved-module-folder-structure">Improved Module Folder Structure</h2><p>We have previously found issues with legacy bundlers and other tools that didn't fully support the new <code>exports</code> field in the module's package.</p><p>To mitigate that, the TinyBase 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><h2 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</h2><h3 id="module-file-structure">Module File Structure</h3><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 TinyBase - 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 when 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><h3 id="expo-sqlite-persister">Expo SQLite <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a></h3><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 'next' 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><h3 id="the-tinybase-inspector">The TinyBase Inspector</h3><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 <a href="https://tinybase.org/api/">API</a> documentation for details, or the <a href="https://tinybase.org/demos/ui-components-react/inspector-react/"><inspector>(React)</inspector></a>demo, for example.</p><h3 id="api-changes"><a href="https://tinybase.org/api/">API</a> <a href="https://tinybase.org/api/store/type-aliases/transaction/changes/"><code>Changes</code></a></h3><p>The following changes have been made to the existing TinyBase <a href="https://tinybase.org/api/">API</a> for consistency. These are less common parts of the <a href="https://tinybase.org/api/">API</a> 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/the-essentials/creating-stores/store/"><code>Store</code></a> interface:</p><ul><li>There is a new <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/gettransactionchanges/"><code>getTransactionChanges</code></a> method and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/the-essentials/persisting-stores/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/the-essentials/creating-stores/store/"><code>Store</code></a> objects.</li><li>A <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a>'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/the-essentials/persisting-stores/persister/"><code>Persister</code></a>, the setPersisted method now receives changes made to a <a href="https://tinybase.org/api/the-essentials/creating-stores/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><hr><h1 id="v4-8">v4.8</h1><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/the-essentials/persisting-stores/persister/"><code>Persister</code></a> for <a href="https://www.powersync.com/">PowerSync'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>
|
|
845
845
|
|
|
846
846
|
```js ignore
|
|
847
847
|
const powerSync = usePowerSync();
|
|
@@ -855,7 +855,7 @@ const persister = createPowerSyncPersister(store, powerSync, {
|
|
|
855
855
|
});
|
|
856
856
|
```
|
|
857
857
|
|
|
858
|
-
<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://
|
|
858
|
+
<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/the-essentials/persisting-stores/persister/"><code>Persister</code></a> works for you.</p><hr><h1 id="v4-7">v4.7</h1><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/the-essentials/persisting-stores/persister/"><code>Persister</code></a> for <a href="https://turso.tech/libsql">Turso's LibSQL</a> database.</p><p>Use the <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> by passing in a reference to the LibSQL client to the createLibSQLPersister function; something like:</p>
|
|
859
859
|
|
|
860
860
|
```js ignore
|
|
861
861
|
const client = createClient({url: 'file:my.db'});
|
|
@@ -869,7 +869,7 @@ const persister = createLibSqlPersister(store, client, {
|
|
|
869
869
|
});
|
|
870
870
|
```
|
|
871
871
|
|
|
872
|
-
<p>This is the first version of this functionality, so please provide feedback on how it works for you!</p><hr><h1 id="v4-6">v4.6</h1><p>This release includes the new <a href="https://
|
|
872
|
+
<p>This is the first version of this functionality, so please provide feedback on how it works for you!</p><hr><h1 id="v4-6">v4.6</h1><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/the-essentials/persisting-stores/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/the-essentials/persisting-stores/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>
|
|
873
873
|
|
|
874
874
|
```js ignore
|
|
875
875
|
const electric = await electrify(connection, schema, config);
|
|
@@ -883,7 +883,7 @@ const persister = createElectricSqlPersister(store, electric, {
|
|
|
883
883
|
});
|
|
884
884
|
```
|
|
885
885
|
|
|
886
|
-
<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><hr><h1 id="v4-5">v4.5</h1><p>This release includes the new persister-expo-sqlite-next module, which provides a <a href="https://
|
|
886
|
+
<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><hr><h1 id="v4-5">v4.5</h1><p>This release includes the new persister-expo-sqlite-next module, which provides a <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> for the modern version of Expo's <a href="https://docs.expo.dev/versions/latest/sdk/sqlite">SQLite</a> library, designated 'next' as of November 2023. This <a href="https://tinybase.org/api/">API</a> should be used if you are installing the <code>expo-sqlite/next</code> module.</p><p>Note that TinyBase 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 TinyBase v5.0, this is now the default and legacy support has been removed.</p><p>Thank you to Expo for providing this functionality!</p><hr><h1 id="v4-4">v4.4</h1><p>This relatively straightforward release adds a selection of new listeners to the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> object, and their respective hooks. These are for listening to changes in the 'existence' of entities rather than to their value. For example, the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/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 TinyBase 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><hr><h1 id="v4-3">v4.3</h1><p>We're excited to announce TinyBase 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 "local-first" architecture and a "sharing-first" 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/the-essentials/creating-stores/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 <a href="https://tinybase.org/api/">API</a> to create connections to the server and a binding to your <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li></ul><p>A TinyBase server implementation on PartyKit can be as simple as this:</p>
|
|
887
887
|
|
|
888
888
|
```js ignore
|
|
889
889
|
import {TinyBasePartyKitServer} from 'tinybase/persisters/persister-partykit-server';
|
|
@@ -891,7 +891,7 @@ import {TinyBasePartyKitServer} from 'tinybase/persisters/persister-partykit-ser
|
|
|
891
891
|
export default class extends TinyBasePartyKitServer {}
|
|
892
892
|
```
|
|
893
893
|
|
|
894
|
-
<p>On the client, use the familiar <a href="https://
|
|
894
|
+
<p>On the client, use the familiar <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> <a href="https://tinybase.org/api/">API</a>, passing in a reference to a PartyKit socket object that's been configured to connect to your server deployment and named room:</p>
|
|
895
895
|
|
|
896
896
|
```js ignore
|
|
897
897
|
import {createPartyKitPersister} from 'tinybase/persisters/persister-partykit-client';
|
|
@@ -907,7 +907,7 @@ await persister.startAutoSave();
|
|
|
907
907
|
await persister.startAutoLoad();
|
|
908
908
|
```
|
|
909
909
|
|
|
910
|
-
<p>The <a href="https://
|
|
910
|
+
<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/the-essentials/persisting-stores/persister/"><code>Persister</code></a> use HTTPS to get or set full copies of the <a href="https://tinybase.org/api/the-essentials/creating-stores/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 TinyBase 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 'every write wins' than 'last write wins'. 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><hr><h1 id="v4-2">v4.2</h1><p>This release adds support for persisting TinyBase to a browser's IndexedDB storage. You'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/the-essentials/persisting-stores/persister/"><code>Persister</code></a>.</p><p>The <a href="https://tinybase.org/api/">API</a> is the same as for all the other <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> APIs:</p>
|
|
911
911
|
|
|
912
912
|
```js
|
|
913
913
|
import {createIndexedDbPersister} from 'tinybase/persisters/persister-indexed-db';
|
|
@@ -936,8 +936,8 @@ await indexedDbPersister.save();
|
|
|
936
936
|
await indexedDbPersister.destroy();
|
|
937
937
|
```
|
|
938
938
|
|
|
939
|
-
<p>Note that it is not possible to reactively detect changes to a browser's IndexedDB storage. A polling technique is used to load underlying changes if you choose to 'autoLoad' your data into TinyBase.</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><hr><h1 id="v4-1">v4.1</h1><p>This release introduces the new <a href="https://
|
|
940
|
-
TinyBase DOM Component"></p><h2 id="new-dom-components">New DOM Components</h2><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://
|
|
939
|
+
<p>Note that it is not possible to reactively detect changes to a browser's IndexedDB storage. A polling technique is used to load underlying changes if you choose to 'autoLoad' your data into TinyBase.</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><hr><h1 id="v4-1">v4.1</h1><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/shots/sortedtableinhtmltable-react-demo.png" alt="A TinyBase DOM Component" title="A
|
|
940
|
+
TinyBase DOM Component"></p><h2 id="new-dom-components">New DOM Components</h2><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-react/valuesinhtmltable-react">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-react/tableinhtmltable-react">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-react/sortedtableinhtmltable-react">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/other-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-react/sliceinhtmltable-react">demo</a></td></tr><tr><td><a href="https://tinybase.org/api/ui-react-dom/functions/other-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-react/relationshipinhtmltable-react">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-react/resulttableinhtmltable-react">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-react/resultsortedtableinhtmltable-react">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-react/editablecellview-react">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-react/editablevalueview-react">demo</a></td></tr></tbody></table></div><p>These pre-built components are showcased in the <a href="https://tinybase.org/demos/ui-components-react/">UI Components (React)</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>
|
|
941
941
|
|
|
942
942
|
```jsx
|
|
943
943
|
import {SortedTableInHtmlTable} from 'tinybase/ui-react-dom';
|
|
@@ -971,7 +971,7 @@ console.log(app.innerHTML);
|
|
|
971
971
|
root.unmount();
|
|
972
972
|
```
|
|
973
973
|
|
|
974
|
-
<p>The <a href="https://
|
|
974
|
+
<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><h2 id="the-new-inspector">The new Inspector</h2><p><img src="https://tinybase.org/shots/inspector-react-demo.png" alt="Inspector" title="Inspector"></p><p>The new <a href="https://tinybase.org/api/the-essentials/using-react/inspector/"><code>Inspector</code></a> component allows you to view, understand, and edit the content of a <a href="https://tinybase.org/api/the-essentials/creating-stores/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/the-essentials/using-react/inspector/"><code>Inspector</code></a> component where appropriate.</p><p>(NB: Previous to v5.0, this component was called <code>StoreInspector</code>.)</p><hr><h1 id="v4-0">v4.0</h1><p>This major release provides <a href="https://tinybase.org/api/the-essentials/persisting-stores/persister/"><code>Persister</code></a> modules that connect TinyBase 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/the-essentials/persisting-stores/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/the-essentials/persisting-stores/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><h2 id="sqlite-databases">SQLite databases</h2><p>You can persist <a href="https://tinybase.org/api/the-essentials/creating-stores/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/the-essentials/persisting-stores/persister/"><code>Persister</code></a> object and saves and loads the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> to and from a local SQLite database. It uses an explicit tabular one-to-one mapping for the 'pets' table:</p>
|
|
975
975
|
|
|
976
976
|
```js
|
|
977
977
|
store.setTables({pets: {fido: {species: 'dog'}}});
|
|
@@ -994,7 +994,7 @@ console.log(store.getTables());
|
|
|
994
994
|
await sqlitePersister.destroy();
|
|
995
995
|
```
|
|
996
996
|
|
|
997
|
-
<h2 id="crdt-frameworks">CRDT Frameworks</h2><p>CRDTs allow complex reconciliation and synchronization between clients. Yjs and Automerge are two popular examples. The <a href="https://
|
|
997
|
+
<h2 id="crdt-frameworks">CRDT Frameworks</h2><p>CRDTs allow complex reconciliation and synchronization between clients. Yjs and Automerge are two popular examples. The <a href="https://tinybase.org/api/">API</a> should be familiar! The following will persist a TinyBase <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> to a Yjs document:</p>
|
|
998
998
|
|
|
999
999
|
```js
|
|
1000
1000
|
import {createYjsPersister} from 'tinybase/persisters/persister-yjs';
|
|
@@ -1033,7 +1033,7 @@ await automergePersister.destroy();
|
|
|
1033
1033
|
store.delTables();
|
|
1034
1034
|
```
|
|
1035
1035
|
|
|
1036
|
-
<h2 id="new-methods">New methods</h2><p>There are three new methods on the <a href="https://
|
|
1036
|
+
<h2 id="new-methods">New methods</h2><p>There are three new methods on the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> object. The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getcontent/"><code>getContent</code></a> method lets you get the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>'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/mergeable-store/interfaces/mergeable/mergeablestore/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/the-essentials/creating-stores/store/"><code>Store</code></a>, allowing you to take changes from one <a href="https://tinybase.org/api/the-essentials/creating-stores/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><h2 id="breaking-changes">Breaking changes</h2><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/the-essentials/creating-stores/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><hr><h1 id="v3-3">v3.3</h1><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/the-essentials/creating-stores/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/the-essentials/creating-stores/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>
|
|
1037
1037
|
|
|
1038
1038
|
```js
|
|
1039
1039
|
store.setTable('pets', {
|
|
@@ -1043,7 +1043,7 @@ store.setTable('pets', {
|
|
|
1043
1043
|
});
|
|
1044
1044
|
```
|
|
1045
1045
|
|
|
1046
|
-
<p>Prior to v3.3, you could only get the <a href="https://
|
|
1046
|
+
<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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getcellids/"><code>getCellIds</code></a> method). But you can now use the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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>
|
|
1047
1047
|
|
|
1048
1048
|
```js
|
|
1049
1049
|
console.log(store.getCellIds('pets', 'fido')); // previously available
|
|
@@ -1053,7 +1053,7 @@ console.log(store.getTableCellIds('pets')); // new in v3.3
|
|
|
1053
1053
|
// -> ['species', 'friendly', 'legs']
|
|
1054
1054
|
```
|
|
1055
1055
|
|
|
1056
|
-
<p>You can register a listener to track the <a href="https://
|
|
1056
|
+
<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/mergeable-store/interfaces/mergeable/mergeablestore/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>
|
|
1057
1057
|
|
|
1058
1058
|
```js
|
|
1059
1059
|
let listenerId = store.addRowIdsListener(
|
|
@@ -1072,7 +1072,7 @@ store.delRow('pets', 'felix');
|
|
|
1072
1072
|
store.delListener(listenerId).delTables();
|
|
1073
1073
|
```
|
|
1074
1074
|
|
|
1075
|
-
<hr><h1 id="v3-2">v3.2</h1><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://
|
|
1075
|
+
<hr><h1 id="v3-2">v3.2</h1><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/the-essentials/creating-stores/store/"><code>Store</code></a>.</p><p>To use this, call the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addstarttransactionlistener/"><code>addStartTransactionListener</code></a> method on your <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>. The listener you add can itself mutate the data in the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</p><p>From this release onwards, listeners added with the existing <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/adddidfinishtransactionlistener/"><code>addDidFinishTransactionListener</code></a> method <em>cannot</em> mutate data.</p>
|
|
1076
1076
|
|
|
1077
1077
|
```js
|
|
1078
1078
|
const startListenerId = store.addStartTransactionListener(() => {
|
|
@@ -1109,7 +1109,7 @@ store
|
|
|
1109
1109
|
store.delTables();
|
|
1110
1110
|
```
|
|
1111
1111
|
|
|
1112
|
-
<p>This release also fixes a bug where using the explicit <a href="https://
|
|
1112
|
+
<p>This release also fixes a bug where using the explicit <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/starttransaction/"><code>startTransaction</code></a> method <em>inside</em> another listener could create infinite recursion.</p><hr><h1 id="v3-1">v3.1</h1><p>This new release adds a powerful schema-based type system to TinyBase.</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>
|
|
1113
1113
|
|
|
1114
1114
|
```ts ignore
|
|
1115
1115
|
// Import the 'with-schemas' definition:
|
|
@@ -1127,7 +1127,7 @@ store.setValues({employees: true}); // TypeScript error
|
|
|
1127
1127
|
store.setValues({employees: 3, website: 'pets.com'}); // TypeScript error
|
|
1128
1128
|
```
|
|
1129
1129
|
|
|
1130
|
-
<p>The schema-based typing is used comprehensively throughout every module - from the core <a href="https://
|
|
1130
|
+
<p>The schema-based typing is used comprehensively throughout every module - from the core <a href="https://tinybase.org/api/the-essentials/creating-stores/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 TinyBase:</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 tools 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/the-essentials/setting-data/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><hr><h1 id="v3-0">v3.0</h1><p>This major new release adds key/value store functionality to TinyBase. 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>
|
|
1131
1131
|
|
|
1132
1132
|
```js
|
|
1133
1133
|
store.setValues({employees: 3, open: true});
|
|
@@ -1147,7 +1147,7 @@ store.setValue('employees', 4);
|
|
|
1147
1147
|
store.delListener(listenerId).delValues();
|
|
1148
1148
|
```
|
|
1149
1149
|
|
|
1150
|
-
<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 <a href="https://beta.tinybase.org/api/ui-react/"><code>ui-react</code></a> module with TinyBase, v3.0 now uses and expects React v18.</p><p>In terms of core <a href="https://beta.tinybase.org/api/">API</a> 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://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> object gains the following:</p><ul><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setvalues/"><code>setValues</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setpartialvalues/"><code>setPartialValues</code></a> method, and <a href="https://beta.tinybase.org/api/the-essentials/setting-data/setvalue/"><code>setValue</code></a> method, to set keyed value data into the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvalues/"><code>getValues</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvalueids/"><code>getValueIds</code></a> method, and <a href="https://beta.tinybase.org/api/the-essentials/getting-data/getvalue/"><code>getValue</code></a> method, to get keyed value data out of the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delvalues/"><code>delValues</code></a> method and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delvalue/"><code>delValue</code></a> method for removing keyed value data.</li><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addvalueslistener/"><code>addValuesListener</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addvalueidslistener/"><code>addValueIdsListener</code></a> method, addValueListener method, and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addinvalidvaluelistener/"><code>addInvalidValueListener</code></a> method, for listening to changes to keyed value data.</li><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/hasvalues/"><code>hasValues</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/hasvalue/"><code>hasValue</code></a> method, and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/iterator/foreachvalue/"><code>forEachValue</code></a> method, for existence and enumeration purposes.</li><li>The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvaluesjson/"><code>getValuesJson</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvaluesschemajson/"><code>getValuesSchemaJson</code></a> method, setTablesSchema method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setvaluesschema/"><code>setValuesSchema</code></a> method, <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>. Also see below.</li></ul><p>The following types have been added to the <a href="https://beta.tinybase.org/api/store/"><code>store</code></a> module:</p><ul><li><a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a>, <a href="https://beta.tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>, and <a href="https://beta.tinybase.org/api/store/type-aliases/store/valueorundefined/"><code>ValueOrUndefined</code></a>, representing keyed value data in a <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li><a href="https://beta.tinybase.org/api/store/type-aliases/listener/valuelistener/"><code>ValueListener</code></a> and <a href="https://beta.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://beta.tinybase.org/api/store/type-aliases/store/value/"><code>Value</code></a>.</li><li><a href="https://beta.tinybase.org/api/store/type-aliases/schema/valuesschema/"><code>ValuesSchema</code></a> and <a href="https://beta.tinybase.org/api/store/type-aliases/schema/valueschema/"><code>ValueSchema</code></a>, to describe the keyed <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> that can be set in a <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> and their types.</li><li><a href="https://beta.tinybase.org/api/store/type-aliases/callback/valuecallback/"><code>ValueCallback</code></a>, <a href="https://beta.tinybase.org/api/store/type-aliases/callback/mapvalue/"><code>MapValue</code></a>, <a href="https://beta.tinybase.org/api/store/type-aliases/transaction/changedvalues/"><code>ChangedValues</code></a>, and <a href="https://beta.tinybase.org/api/store/type-aliases/transaction/invalidvalues/"><code>InvalidValues</code></a>, which also correspond to their '<a href="https://beta.tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>' equivalents.</li></ul><p>Additionally:</p><ul><li>The persisters' <a href="https://beta.tinybase.org/api/persisters/interfaces/persister/persister/methods/load/load/"><code>load</code></a> method and <a href="https://beta.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://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> when a persisted <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> is bootstrapped.</li><li>The <a href="https://beta.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 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 <a href="https://beta.tinybase.org/api/">API</a> 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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getjson/"><code>getJson</code></a> method would get a JSON serialization of the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>'s tabular data. That functionality is now provided by the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, and the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getschemajson/"><code>getSchemaJson</code></a> method used to return the tabular schema, now provided by the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method. The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setjson/"><code>setJson</code></a> method used to take a serialization of just the tabular data object. That's now provided by the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getjson/"><code>getJson</code></a> method). However, for backwards compatibility, if the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setschema/"><code>setSchema</code></a> method's previous behavior is now provided by the <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesschema/"><code>setTablesSchema</code></a> method. The <a href="https://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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://beta.tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delschema/"><code>delSchema</code></a> method removes both types of schema.</p><hr><h1 id="v2-2">v2.2</h1><p>Note: The tools module has been removed in TinyBase v6.0.</p><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>
|
|
1150
|
+
<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 TinyBase, v3.0 now uses and expects React v18.</p><p>In terms of core <a href="https://tinybase.org/api/">API</a> 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/the-essentials/creating-stores/store/"><code>Store</code></a> object gains the following:</p><ul><li>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setvalues/"><code>setValues</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setpartialvalues/"><code>setPartialValues</code></a> method, and <a href="https://tinybase.org/api/the-essentials/setting-data/setvalue/"><code>setValue</code></a> method, to set keyed value data into the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvalues/"><code>getValues</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvalueids/"><code>getValueIds</code></a> method, and <a href="https://tinybase.org/api/the-essentials/getting-data/getvalue/"><code>getValue</code></a> method, to get keyed value data out of the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>.</li><li>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delvalues/"><code>delValues</code></a> method and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delvalue/"><code>delValue</code></a> method for removing keyed value data.</li><li>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addvalueslistener/"><code>addValuesListener</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addvalueidslistener/"><code>addValueIdsListener</code></a> method, addValueListener method, and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/hasvalues/"><code>hasValues</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/hasvalue/"><code>hasValue</code></a> method, and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/iterator/foreachvalue/"><code>forEachValue</code></a> method, for existence and enumeration purposes.</li><li>The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvaluesjson/"><code>getValuesJson</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getvaluesschemajson/"><code>getValuesSchemaJson</code></a> method, setTablesSchema method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setvaluesschema/"><code>setValuesSchema</code></a> method, <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/the-essentials/creating-stores/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/the-essentials/creating-stores/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/the-essentials/creating-stores/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 '<a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a>' equivalents.</li></ul><p>Additionally:</p><ul><li>The persisters' <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/the-essentials/creating-stores/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 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 <a href="https://tinybase.org/api/">API</a> 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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getjson/"><code>getJson</code></a> method would get a JSON serialization of the <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a>'s tabular data. That functionality is now provided by the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesjson/"><code>getTablesJson</code></a> method, and the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getschemajson/"><code>getSchemaJson</code></a> method used to return the tabular schema, now provided by the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/gettablesschemajson/"><code>getTablesSchemaJson</code></a> method. The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setjson/"><code>setJson</code></a> method used to take a serialization of just the tabular data object. That's now provided by the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesjson/"><code>setTablesJson</code></a> method, and the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getjson/"><code>getJson</code></a> method). However, for backwards compatibility, if the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/setschema/"><code>setSchema</code></a> method's previous behavior is now provided by the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/setter/settablesschema/"><code>setTablesSchema</code></a> method. The <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/deleter/delschema/"><code>delSchema</code></a> method removes both types of schema.</p><hr><h1 id="v2-2">v2.2</h1><p>Note: The tools module has been removed in TinyBase v6.0.</p><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>
|
|
1151
1151
|
|
|
1152
1152
|
```js ignore
|
|
1153
1153
|
import {createTools} from 'tinybase/tools';
|
|
@@ -1187,7 +1187,7 @@ npx tinybase getStoreApi schema.json shop api
|
|
|
1187
1187
|
Implementation: [...]/api/shop.ts
|
|
1188
1188
|
```
|
|
1189
1189
|
|
|
1190
|
-
<p>Finally, the tools module also provides ways to track the overall size and structure of a <a href="https://
|
|
1190
|
+
<p>Finally, the tools module also provides ways to track the overall size and structure of a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> for use while debugging.</p><hr><h1 id="v2-1">v2.1</h1><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>
|
|
1191
1191
|
|
|
1192
1192
|
```js
|
|
1193
1193
|
import {createIndexes} from 'tinybase';
|
|
@@ -1211,7 +1211,7 @@ console.log(indexes.getSliceRowIds('containsLetter', 'x'));
|
|
|
1211
1211
|
// -> ['felix', 'rex']
|
|
1212
1212
|
```
|
|
1213
1213
|
|
|
1214
|
-
<p>This functionality is showcased in the <a href="https://
|
|
1214
|
+
<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><hr><h1 id="v2-0">v2.0</h1><p><strong>Announcing the next major version of TinyBase 2.0!</strong> This is an exciting release that evolves TinyBase towards becoming a reactive, relational data store, complete with querying, sorting, and pagination. Here are a few of the highlights...</p><h2 id="query-engine">Query Engine</h2><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 <a href="https://tinybase.org/api/">API</a> that we'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's all reactive!</p><p>The best way to see the power of this new engine is with the two new demos we've included this release:</p><p><img src="https://tinybase.org/shots/car-analysis-demo.png" alt="Car Analysis demo screenshot"></p><p>The <a href="https://tinybase.org/demos/car-analysis/">Car Analysis</a> demo showcases the analytical query capabilities of TinyBase 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/shots/movie-database-demo.png" alt="Movie Database demo screenshot"></p><p>The <a href="https://tinybase.org/demos/movie-database/">Movie Database</a> demo showcases the relational query capabilities of TinyBase 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><h2 id="sorting-and-pagination">Sorting and Pagination</h2><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/the-essentials/creating-stores/store/"><code>Store</code></a> now includes the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/getter/getsortedrowids/"><code>getSortedRowIds</code></a> method (and the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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><h2 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</h2><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/the-essentials/creating-stores/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><h2 id="it-s-a-big-release">It's a big release!</h2><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>, <a href="https://bsky.app/profile/tinybase.bsky.social">Bluesky</a>, and <a href="https://x.com/tinybasejs">X</a>!</p><hr><h1 id="v1-3">v1.3</h1><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/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/starttransaction/"><code>startTransaction</code></a> method and <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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/the-essentials/creating-stores/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/finishtransaction/"><code>finishTransaction</code></a> method.</p><p>Unlike the <a href="https://tinybase.org/api/the-essentials/setting-data/transaction/"><code>transaction</code></a> method, this approach is useful when you have a more 'open-ended' 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/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/finishtransaction/"><code>finishTransaction</code></a> method explicitly when the transaction is started with the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/transaction/starttransaction/"><code>startTransaction</code></a> method, of course.</p>
|
|
1215
1215
|
|
|
1216
1216
|
```js
|
|
1217
1217
|
store.setTables({pets: {fido: {species: 'dog'}}});
|
|
@@ -1224,4 +1224,4 @@ store.finishTransaction();
|
|
|
1224
1224
|
// -> 'Fido changed'
|
|
1225
1225
|
```
|
|
1226
1226
|
|
|
1227
|
-
<p>In addition, see the <a href="https://
|
|
1227
|
+
<p>In addition, see the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addwillfinishtransactionlistener/"><code>addWillFinishTransactionListener</code></a> method and the <a href="https://tinybase.org/api/mergeable-store/interfaces/mergeable/mergeablestore/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 <a href="https://tinybase.org/api/">API</a> was updated to be more comprehensive in v4.0.</p><hr><h1 id="v1-2">v1.2</h1><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/the-essentials/setting-data/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 <a href="https://tinybase.org/api/">API</a> was updated to be more comprehensive in v4.0.</p><hr><h1 id="v1-1">v1.1</h1><p>This release allows you to listen to invalid data being added to a <a href="https://tinybase.org/api/the-essentials/creating-stores/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/mergeable-store/interfaces/mergeable/mergeablestore/methods/listener/addinvalidcelllistener/"><code>addInvalidCellListener</code></a> method in the <a href="https://tinybase.org/api/the-essentials/creating-stores/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/the-essentials/creating-stores/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/mergeable-store/interfaces/mergeable/mergeablestore/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/the-essentials/creating-stores/store/"><code>Store</code></a> with a <a href="https://tinybase.org/api/store/type-aliases/schema/tablesschema/"><code>TablesSchema</code></a>.</p>
|