tinybase 7.3.1 → 7.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/@types/mergeable-store/with-schemas/index.d.ts +1 -1
  2. package/min/omni/index.js +1 -1
  3. package/min/omni/index.js.gz +0 -0
  4. package/min/omni/with-schemas/index.js +1 -1
  5. package/min/omni/with-schemas/index.js.gz +0 -0
  6. package/min/persisters/index.js +1 -1
  7. package/min/persisters/index.js.gz +0 -0
  8. package/min/persisters/persister-browser/index.js +1 -1
  9. package/min/persisters/persister-browser/index.js.gz +0 -0
  10. package/min/persisters/persister-browser/with-schemas/index.js +1 -1
  11. package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
  12. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  13. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  14. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  15. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  16. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  17. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  18. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  19. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  20. package/min/persisters/persister-durable-object-storage/index.js +1 -1
  21. package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
  22. package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
  23. package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
  24. package/min/persisters/persister-electric-sql/index.js +1 -1
  25. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  26. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  27. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  28. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  29. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  30. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  31. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  32. package/min/persisters/persister-file/index.js +1 -1
  33. package/min/persisters/persister-file/index.js.gz +0 -0
  34. package/min/persisters/persister-file/with-schemas/index.js +1 -1
  35. package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
  36. package/min/persisters/persister-libsql/index.js +1 -1
  37. package/min/persisters/persister-libsql/index.js.gz +0 -0
  38. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  39. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  40. package/min/persisters/persister-partykit-client/index.js +1 -1
  41. package/min/persisters/persister-partykit-client/index.js.gz +0 -0
  42. package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
  43. package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
  44. package/min/persisters/persister-partykit-server/index.js +1 -1
  45. package/min/persisters/persister-partykit-server/index.js.gz +0 -0
  46. package/min/persisters/persister-partykit-server/with-schemas/index.js +1 -1
  47. package/min/persisters/persister-partykit-server/with-schemas/index.js.gz +0 -0
  48. package/min/persisters/persister-pglite/index.js +1 -1
  49. package/min/persisters/persister-pglite/index.js.gz +0 -0
  50. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  51. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  52. package/min/persisters/persister-postgres/index.js +1 -1
  53. package/min/persisters/persister-postgres/index.js.gz +0 -0
  54. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  55. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  56. package/min/persisters/persister-powersync/index.js +1 -1
  57. package/min/persisters/persister-powersync/index.js.gz +0 -0
  58. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  59. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  60. package/min/persisters/persister-react-native-sqlite/index.js +1 -1
  61. package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
  62. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
  63. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
  64. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  65. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  66. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  67. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  68. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  69. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  70. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  71. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  72. package/min/persisters/persister-sqlite3/index.js +1 -1
  73. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  74. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  75. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  76. package/min/persisters/with-schemas/index.js +1 -1
  77. package/min/persisters/with-schemas/index.js.gz +0 -0
  78. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  79. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  80. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  81. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  82. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  83. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  84. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  85. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  86. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  87. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  88. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  89. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  90. package/min/ui-react-inspector/index.js +1 -1
  91. package/min/ui-react-inspector/index.js.gz +0 -0
  92. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  93. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  94. package/omni/index.js +21 -9
  95. package/omni/with-schemas/index.js +21 -9
  96. package/package.json +18 -18
  97. package/persisters/index.js +10 -1
  98. package/persisters/persister-browser/index.js +17 -1
  99. package/persisters/persister-browser/with-schemas/index.js +17 -1
  100. package/persisters/persister-cr-sqlite-wasm/index.js +10 -1
  101. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +10 -1
  102. package/persisters/persister-durable-object-sql-storage/index.js +10 -1
  103. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +10 -1
  104. package/persisters/persister-durable-object-storage/index.js +5 -6
  105. package/persisters/persister-durable-object-storage/with-schemas/index.js +5 -6
  106. package/persisters/persister-electric-sql/index.js +10 -1
  107. package/persisters/persister-electric-sql/with-schemas/index.js +10 -1
  108. package/persisters/persister-expo-sqlite/index.js +10 -1
  109. package/persisters/persister-expo-sqlite/with-schemas/index.js +10 -1
  110. package/persisters/persister-file/index.js +17 -1
  111. package/persisters/persister-file/with-schemas/index.js +17 -1
  112. package/persisters/persister-libsql/index.js +10 -1
  113. package/persisters/persister-libsql/with-schemas/index.js +10 -1
  114. package/persisters/persister-partykit-client/index.js +27 -2
  115. package/persisters/persister-partykit-client/with-schemas/index.js +27 -2
  116. package/persisters/persister-partykit-server/index.js +37 -2
  117. package/persisters/persister-partykit-server/with-schemas/index.js +37 -2
  118. package/persisters/persister-pglite/index.js +10 -1
  119. package/persisters/persister-pglite/with-schemas/index.js +10 -1
  120. package/persisters/persister-postgres/index.js +10 -1
  121. package/persisters/persister-postgres/with-schemas/index.js +10 -1
  122. package/persisters/persister-powersync/index.js +10 -1
  123. package/persisters/persister-powersync/with-schemas/index.js +10 -1
  124. package/persisters/persister-react-native-sqlite/index.js +10 -1
  125. package/persisters/persister-react-native-sqlite/with-schemas/index.js +10 -1
  126. package/persisters/persister-sqlite-bun/index.js +10 -1
  127. package/persisters/persister-sqlite-bun/with-schemas/index.js +10 -1
  128. package/persisters/persister-sqlite-wasm/index.js +10 -1
  129. package/persisters/persister-sqlite-wasm/with-schemas/index.js +10 -1
  130. package/persisters/persister-sqlite3/index.js +10 -1
  131. package/persisters/persister-sqlite3/with-schemas/index.js +10 -1
  132. package/persisters/with-schemas/index.js +10 -1
  133. package/readme.md +10 -2
  134. package/releases.md +1 -1
  135. package/synchronizers/synchronizer-ws-client/index.js +14 -1
  136. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +14 -1
  137. package/synchronizers/synchronizer-ws-server/index.js +14 -1
  138. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +14 -1
  139. package/synchronizers/synchronizer-ws-server-durable-object/index.js +14 -1
  140. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +14 -1
  141. package/ui-react-inspector/index.js +10 -1
  142. package/ui-react-inspector/with-schemas/index.js +10 -1
package/readme.md CHANGED
@@ -1,4 +1,12 @@
1
- <link rel="preload" as="image" href="https://tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/indexeddb.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/browser.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/cloudflare.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/postgresql.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/pglite.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/sqlite.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/bun.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/expo.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/electric.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/turso.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/powersync.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/partykit.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/yjs.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/crsqlite.png"><link rel="preload" as="image" href="https://tinybase.org/automerge.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/zod.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/typebox.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/valibot.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/arktype.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/yup.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/effect.svg?asImg"><link rel="preload" as="image" href="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge&amp;logo=bluesky&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%230285FF"><link rel="preload" as="image" href="https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%23000"><link rel="preload" as="image" href="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=Vitest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"><link rel="preload" as="image" href="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"><link rel="preload" as="image" href="https://tinybase.org/ui-react-dom.webp"><link rel="preload" as="image" href="https://tinybase.org/inspector.webp"><link rel="preload" as="image" href="https://github.com/fastrepl.png?size=48"><link rel="preload" as="image" href="https://github.com/expo.png?size=48"><link rel="preload" as="image" href="https://github.com/dylmye.png?size=48"><link rel="preload" as="image" href="https://github.com/ComputelessComputer.png?size=48"><link rel="preload" as="image" href="https://github.com/cancelself.png?size=48"><link rel="preload" as="image" href="https://github.com/cpojer.png?size=48"><link rel="preload" as="image" href="https://github.com/beekeeb.png?size=48"><link rel="preload" as="image" href="https://github.com/WonderPanda.png?size=48"><link rel="preload" as="image" href="https://github.com/arpitBhalla.png?size=48"><link rel="preload" as="image" href="https://github.com/behrends.png?size=48"><link rel="preload" as="image" href="https://github.com/betomoedano.png?size=48"><link rel="preload" as="image" href="https://github.com/brentvatne.png?size=48"><link rel="preload" as="image" href="https://github.com/byCedric.png?size=48"><link rel="preload" as="image" href="https://github.com/circadian-risk.png?size=48"><link rel="preload" as="image" href="https://github.com/cubecull.png?size=48"><link rel="preload" as="image" href="https://github.com/erwinkn.png?size=48"><link rel="preload" as="image" href="https://github.com/ezra-en.png?size=48"><link rel="preload" as="image" href="https://github.com/feychenie.png?size=48"><link rel="preload" as="image" href="https://github.com/flaming-codes.png?size=48"><link rel="preload" as="image" href="https://github.com/fostertheweb.png?size=48"><link rel="preload" as="image" href="https://github.com/Giulio987.png?size=48"><link rel="preload" as="image" href="https://github.com/hi-ogawa.png?size=48"><link rel="preload" as="image" href="https://github.com/itsdevcoffee.png?size=48"><link rel="preload" as="image" href="https://github.com/jbolda.png?size=48"><link rel="preload" as="image" href="https://github.com/Kayoo-asso.png?size=48"><link rel="preload" as="image" href="https://github.com/kotofurumiya.png?size=48"><link rel="preload" as="image" href="https://github.com/Kudo.png?size=48"><link rel="preload" as="image" href="https://github.com/learn-anything.png?size=48"><link rel="preload" as="image" href="https://github.com/lluc.png?size=48"><link rel="preload" as="image" href="https://github.com/marksteve.png?size=48"><link rel="preload" as="image" href="https://github.com/miking-the-viking.png?size=48"><link rel="preload" as="image" href="https://github.com/mjamesderocher.png?size=48"><link rel="preload" as="image" href="https://github.com/mouktardev.png?size=48"><link rel="preload" as="image" href="https://github.com/nickmessing.png?size=48"><link rel="preload" as="image" href="https://github.com/nikitavoloboev.png?size=48"><link rel="preload" as="image" href="https://github.com/nkzw-tech.png?size=48"><link rel="preload" as="image" href="https://github.com/palerdot.png?size=48"><link rel="preload" as="image" href="https://github.com/PorcoRosso85.png?size=48"><link rel="preload" as="image" href="https://github.com/primodiumxyz.png?size=48"><link rel="preload" as="image" href="https://github.com/shaneosullivan.png?size=48"><link rel="preload" as="image" href="https://github.com/sudo-self.png?size=48"><link rel="preload" as="image" href="https://github.com/SuperSonicHub1.png?size=48"><link rel="preload" as="image" href="https://github.com/threepointone.png?size=48"><link rel="preload" as="image" href="https://github.com/uptonking.png?size=48"><link rel="preload" as="image" href="https://github.com/ViktorZhurbin.png?size=48"><link rel="preload" as="image" href="https://github.com/wilkerlucio.png?size=48"><link rel="preload" as="image" href="https://synclets.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinywidgets.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinytick.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/youtube.webp"><section id="hero"><h2 id="a-reactive-data-store-sync-engine">A <em>reactive</em> data store &amp; <span><em>sync</em> engine</span></h2></section><p><a href="https://tinybase.org/guides/releases/#v7-3"><em>NEW!</em> v7.3 release</a></p><p><span id="one-with">&quot;The one with state hooks!&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/the-essentials/creating-stores/store/">Read the docs</a></p><hr><section><h2 id="it-s-reactive">It&#x27;s <em>Reactive</em></h2><p>TinyBase lets you <a href="#register-granular-listeners">listen to changes</a> made to any part of your data. This means your app will be fast, since you only spend rendering cycles on things that change. The optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and <a href="#pre-built-reactive-components">pre-built components</a> let you easily build fully reactive UIs on top of TinyBase. You even get a built-in <a href="#set-checkpoints-for-an-undo-stack">undo stack</a>, and <a href="#an-inspector-for-your-data">developer tools</a>!</p></section><section><h2 id="it-s-database-like">It&#x27;s <em>Database-Like</em></h2><p>Consumer app? Enterprise app? Or even a game? Model <a href="#start-with-a-simple-key-value-store">key-value data</a> and <a href="#level-up-to-use-tabular-data">tabular data</a> with optional typed <a href="#apply-schemas-to-tables-values">schematization</a>, whatever its data structures. There are built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, and tabular <a href="#model-table-relationships">relationships</a> APIs - and a powerful <a href="#build-complex-queries-with-tinyql">query engine</a> to select, join, filter, and group data (reactively!) without SQL.</p></section><section><h2 id="it-synchronizes">It <em>Synchronizes</em></h2><p>TinyBase has <a href="#synchronize-between-devices">native CRDT</a> support, meaning that you can deterministically <a href="https://tinybase.org/guides/synchronization/">synchronize</a> and merge data across multiple sources, clients, and servers. And although TinyBase is an in-memory data store, you can easily <a href="#persist-to-storage-databases-more">persist</a> your data to file, <a href="https://tinybase.org/api/persister-browser">browser storage</a>, <a href="https://tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://tinybase.org/guides/persistence/database-persistence/">SQLite or PostgreSQL databases</a>, and <a href="https://tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>.</p></section><section><h2 id="it-s-built-for-a-local-first-world">It&#x27;s Built For A <em>Local-First</em> World</h2><p>TinyBase works anywhere that JavaScript does, but it&#x27;s especially great for local-first apps: where data is stored locally on the user&#x27;s device and that can be run offline. It&#x27;s tiny by name, tiny by nature: just <a href="#did-we-say-tiny">5.4kB - 12.1kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends.</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img src="https://tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img src="https://tinybase.org/indexeddb.svg?asImg" width="48"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-browser"><img src="https://tinybase.org/browser.svg?asImg" width="48"> OPFS</a></div><div><a href="https://tinybase.org/guides/integrations/cloudflare-durable-objects"><img src="https://tinybase.org/cloudflare.svg?asImg" width="48"> Cloudflare</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/postgresql.svg?asImg" width="48"> PostgreSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/pglite.svg?asImg" width="48"> PGlite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/sqlite.svg?asImg" width="48"> SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/bun.svg?asImg" width="48"> Bun SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/expo.svg?asImg" width="48"> Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/electric.svg?asImg" width="48"> ElectricSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/turso.svg?asImg" width="48"> Turso</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/powersync.svg?asImg" width="48"> PowerSync</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img src="https://tinybase.org/partykit.svg?asImg" width="48"> PartyKit</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img src="https://tinybase.org/yjs.svg?asImg" width="48"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img src="https://tinybase.org/crsqlite.png" width="48"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img src="https://tinybase.org/automerge.svg?asImg" width="48"> Automerge</a></div><div><a href="https://tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer"><img src="https://tinybase.org/zod.svg?asImg" width="48"> Zod</a></div><div><a href="https://tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer"><img src="https://tinybase.org/typebox.svg?asImg" width="48"> TypeBox</a></div><div><a href="https://tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer"><img src="https://tinybase.org/valibot.svg?asImg" width="48"> Valibot</a></div><div><a href="https://tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer"><img src="https://tinybase.org/arktype.svg?asImg" width="48"> ArkType</a></div><div><a href="https://tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer"><img src="https://tinybase.org/yup.svg?asImg" width="48"> Yup</a></div><div><a href="https://tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer"><img src="https://tinybase.org/effect.svg?asImg" width="48"> Effect</a></div><p>(Baffled by all these logos? Check out our <a href="https://tinybase.org/guides/the-basics/architectural-options">architectural options</a> guide to make sense of it all!)</p></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://bsky.app/profile/tinybase.bsky.social"><img src="https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge&amp;logo=bluesky&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%230285FF"> </a><a href="https://x.com/tinybasejs" target="_blank"><img src="https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%23000"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=Vitest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/7.3.0" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/the-essentials/creating-stores/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
1
+ <link rel="preload" as="image" href="https://tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/indexeddb.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/browser.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/cloudflare.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/postgresql.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/pglite.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/sqlite.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/bun.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/expo.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/electric.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/turso.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/powersync.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/partykit.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/yjs.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/crsqlite.png"><link rel="preload" as="image" href="https://tinybase.org/automerge.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/zod.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/typebox.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/valibot.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/arktype.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/yup.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/effect.svg?asImg"><link rel="preload" as="image" href="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge&amp;logo=bluesky&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%230285FF"><link rel="preload" as="image" href="https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%23000"><link rel="preload" as="image" href="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"><link rel="preload" as="image" href="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=Vitest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"><link rel="preload" as="image" href="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"><link rel="preload" as="image" href="https://tinybase.org/ui-react-dom.webp"><link rel="preload" as="image" href="https://tinybase.org/inspector.webp"><link rel="preload" as="image" href="https://github.com/fastrepl.png?size=48"><link rel="preload" as="image" href="https://github.com/expo.png?size=48"><link rel="preload" as="image" href="https://github.com/dylmye.png?size=48"><link rel="preload" as="image" href="https://github.com/ComputelessComputer.png?size=48"><link rel="preload" as="image" href="https://github.com/cancelself.png?size=48"><link rel="preload" as="image" href="https://github.com/cpojer.png?size=48"><link rel="preload" as="image" href="https://github.com/beekeeb.png?size=48"><link rel="preload" as="image" href="https://github.com/WonderPanda.png?size=48"><link rel="preload" as="image" href="https://github.com/arpitBhalla.png?size=48"><link rel="preload" as="image" href="https://github.com/behrends.png?size=48"><link rel="preload" as="image" href="https://github.com/betomoedano.png?size=48"><link rel="preload" as="image" href="https://github.com/brentvatne.png?size=48"><link rel="preload" as="image" href="https://github.com/byCedric.png?size=48"><link rel="preload" as="image" href="https://github.com/circadian-risk.png?size=48"><link rel="preload" as="image" href="https://github.com/cubecull.png?size=48"><link rel="preload" as="image" href="https://github.com/erwinkn.png?size=48"><link rel="preload" as="image" href="https://github.com/ezra-en.png?size=48"><link rel="preload" as="image" href="https://github.com/feychenie.png?size=48"><link rel="preload" as="image" href="https://github.com/flaming-codes.png?size=48"><link rel="preload" as="image" href="https://github.com/fostertheweb.png?size=48"><link rel="preload" as="image" href="https://github.com/Giulio987.png?size=48"><link rel="preload" as="image" href="https://github.com/hi-ogawa.png?size=48"><link rel="preload" as="image" href="https://github.com/itsdevcoffee.png?size=48"><link rel="preload" as="image" href="https://github.com/jbolda.png?size=48"><link rel="preload" as="image" href="https://github.com/Kayoo-asso.png?size=48"><link rel="preload" as="image" href="https://github.com/kotofurumiya.png?size=48"><link rel="preload" as="image" href="https://github.com/Kudo.png?size=48"><link rel="preload" as="image" href="https://github.com/learn-anything.png?size=48"><link rel="preload" as="image" href="https://github.com/lluc.png?size=48"><link rel="preload" as="image" href="https://github.com/marksteve.png?size=48"><link rel="preload" as="image" href="https://github.com/miking-the-viking.png?size=48"><link rel="preload" as="image" href="https://github.com/mjamesderocher.png?size=48"><link rel="preload" as="image" href="https://github.com/mouktardev.png?size=48"><link rel="preload" as="image" href="https://github.com/nickmessing.png?size=48"><link rel="preload" as="image" href="https://github.com/nikitavoloboev.png?size=48"><link rel="preload" as="image" href="https://github.com/nkzw-tech.png?size=48"><link rel="preload" as="image" href="https://github.com/palerdot.png?size=48"><link rel="preload" as="image" href="https://github.com/PorcoRosso85.png?size=48"><link rel="preload" as="image" href="https://github.com/primodiumxyz.png?size=48"><link rel="preload" as="image" href="https://github.com/shaneosullivan.png?size=48"><link rel="preload" as="image" href="https://github.com/sudo-self.png?size=48"><link rel="preload" as="image" href="https://github.com/SuperSonicHub1.png?size=48"><link rel="preload" as="image" href="https://github.com/threepointone.png?size=48"><link rel="preload" as="image" href="https://github.com/uptonking.png?size=48"><link rel="preload" as="image" href="https://github.com/ViktorZhurbin.png?size=48"><link rel="preload" as="image" href="https://github.com/wilkerlucio.png?size=48"><link rel="preload" as="image" href="https://synclets.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinywidgets.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinytick.org/favicon.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/youtube.webp"><section id="hero"><h2 id="a-reactive-data-store-sync-engine">A <em>reactive</em> data store &amp; <span><em>sync</em> engine</span></h2></section><p><a href="https://tinybase.org/guides/releases/#v7-3"><em>NEW!</em> v7.3 release</a></p><p><span id="one-with">&quot;The one with state hooks!&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/the-essentials/creating-stores/store/">Read the docs</a></p><hr><section><h2 id="let-s-build-local-first-apps">Let&#x27;s build <em>local-first</em> apps</h2><p>Create a todo list, a chat app, a drawing tool, or a tic-tac-toe game - with sync &amp; persistence! - in less than 60 seconds.</p></section>
2
+
3
+ ```bash
4
+ > npm create tinybase@latest
5
+
6
+ 📦 Creating your project...
7
+ ```
8
+
9
+ <hr><section><h2 id="it-s-reactive">It&#x27;s <em>Reactive</em></h2><p>TinyBase lets you <a href="#register-granular-listeners">listen to changes</a> made to any part of your data. This means your app will be fast, since you only spend rendering cycles on things that change. The optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and <a href="#pre-built-reactive-components">pre-built components</a> let you easily build fully reactive UIs on top of TinyBase. You even get a built-in <a href="#set-checkpoints-for-an-undo-stack">undo stack</a>, and <a href="#an-inspector-for-your-data">developer tools</a>!</p></section><section><h2 id="it-s-database-like">It&#x27;s <em>Database-Like</em></h2><p>Consumer app? Enterprise app? Or even a game? Model <a href="#start-with-a-simple-key-value-store">key-value data</a> and <a href="#level-up-to-use-tabular-data">tabular data</a> with optional typed <a href="#apply-schemas-to-tables-values">schematization</a>, whatever its data structures. There are built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, and tabular <a href="#model-table-relationships">relationships</a> APIs - and a powerful <a href="#build-complex-queries-with-tinyql">query engine</a> to select, join, filter, and group data (reactively!) without SQL.</p></section><section><h2 id="it-synchronizes">It <em>Synchronizes</em></h2><p>TinyBase has <a href="#synchronize-between-devices">native CRDT</a> support, meaning that you can deterministically <a href="https://tinybase.org/guides/synchronization/">synchronize</a> and merge data across multiple sources, clients, and servers. And although TinyBase is an in-memory data store, you can easily <a href="#persist-to-storage-databases-more">persist</a> your data to file, <a href="https://tinybase.org/api/persister-browser">browser storage</a>, <a href="https://tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://tinybase.org/guides/persistence/database-persistence/">SQLite or PostgreSQL databases</a>, and <a href="https://tinybase.org/guides/persistence/third-party-crdt-persistence/">more</a>.</p></section><section><h2 id="it-s-built-for-a-local-first-world">It&#x27;s Built For A <em>Local-First</em> World</h2><p>TinyBase works anywhere that JavaScript does, but it&#x27;s especially great for local-first apps: where data is stored locally on the user&#x27;s device and that can be run offline. It&#x27;s tiny by name, tiny by nature: just <a href="#did-we-say-tiny">5.4kB - 12.1kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends.</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img src="https://tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img src="https://tinybase.org/indexeddb.svg?asImg" width="48"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-browser"><img src="https://tinybase.org/browser.svg?asImg" width="48"> OPFS</a></div><div><a href="https://tinybase.org/guides/integrations/cloudflare-durable-objects"><img src="https://tinybase.org/cloudflare.svg?asImg" width="48"> Cloudflare</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/postgresql.svg?asImg" width="48"> PostgreSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/pglite.svg?asImg" width="48"> PGlite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/sqlite.svg?asImg" width="48"> SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/bun.svg?asImg" width="48"> Bun SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/expo.svg?asImg" width="48"> Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/electric.svg?asImg" width="48"> ElectricSQL</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/turso.svg?asImg" width="48"> Turso</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://tinybase.org/powersync.svg?asImg" width="48"> PowerSync</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img src="https://tinybase.org/partykit.svg?asImg" width="48"> PartyKit</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img src="https://tinybase.org/yjs.svg?asImg" width="48"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img src="https://tinybase.org/crsqlite.png" width="48"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img src="https://tinybase.org/automerge.svg?asImg" width="48"> Automerge</a></div><div><a href="https://tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer"><img src="https://tinybase.org/zod.svg?asImg" width="48"> Zod</a></div><div><a href="https://tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer"><img src="https://tinybase.org/typebox.svg?asImg" width="48"> TypeBox</a></div><div><a href="https://tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer"><img src="https://tinybase.org/valibot.svg?asImg" width="48"> Valibot</a></div><div><a href="https://tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer"><img src="https://tinybase.org/arktype.svg?asImg" width="48"> ArkType</a></div><div><a href="https://tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer"><img src="https://tinybase.org/yup.svg?asImg" width="48"> Yup</a></div><div><a href="https://tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer"><img src="https://tinybase.org/effect.svg?asImg" width="48"> Effect</a></div><p>(Baffled by all these logos? Check out our <a href="https://tinybase.org/guides/the-basics/architectural-options">architectural options</a> guide to make sense of it all!)</p></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://bsky.app/profile/tinybase.bsky.social"><img src="https://img.shields.io/badge/Bluesky-Follow-blue?style=for-the-badge&amp;logo=bluesky&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%230285FF"> </a><a href="https://x.com/tinybasejs" target="_blank"><img src="https://img.shields.io/badge/%2F%20Twitter-Follow-blue?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%23000"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=Vitest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/7.3.2" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/the-essentials/creating-stores/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
2
10
 
3
11
  ```js
4
12
  import {createStore} from 'tinybase';
@@ -275,4 +283,4 @@ console.log(store.getCell('pets', 'felix', 'sold'));
275
283
  // -> false
276
284
  ```
277
285
 
278
- <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic <a href="https://tinybase.org/api/store/"><code>store</code></a> module alone, you&#x27;ll only add a gzipped <em>5.4kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>12.1kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>5.5kB</em>, the ui-react-dom components are another <em>3.8kB</em>, and everything is super fast. Life is easy when you have zero dependencies!</p><p>Read more about how TinyBase is structured and packaged in the <a href="https://tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>5.4kB</td><td>54.6kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.1kB</td><td>127.0kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>5.5kB</td><td>59.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>3.8kB</td><td>34.0kB</td></tr></tbody></table></div><section><h2 id="well-tested-and-documented">Well tested and documented.</h2><p>TinyBase has <em>100.0%</em> test coverage, including the code throughout the documentation - even on this page! The guides, demos, and API examples are designed to make it as easy as possible for you to get your TinyBase-powered app up and running.</p><p>Read more about how TinyBase is tested in the Unit <a href="https://tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Lines</th><td>2,408</td><td>2,408</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,617</td><td>2,617</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,046</td><td>1,046</td><td>100.0%</td></tr><tr><th class="right">Branches</th><td>906</td><td>906</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">7,268</td></tr><tr><th class="right">Assertions</th><td colspan="3">32,293</td></tr></tbody></table></div><hr><section id="sponsors"><h2 id="proud-to-be-supported-by">Proud to be supported by:</h2><a href="https://github.com/fastrepl" target="_blank"><img src="https://github.com/fastrepl.png?size=48" title="fastrepl" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/dylmye" target="_blank"><img src="https://github.com/dylmye.png?size=48" title="dylmye" width="48" height="48"></a><a href="https://github.com/ComputelessComputer" target="_blank"><img src="https://github.com/ComputelessComputer.png?size=48" title="ComputelessComputer" width="48" height="48"></a><a href="https://github.com/cancelself" target="_blank"><img src="https://github.com/cancelself.png?size=48" title="cancelself" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img src="https://github.com/cpojer.png?size=48" title="cpojer" width="48" height="48"></a><a href="https://github.com/beekeeb" target="_blank"><img src="https://github.com/beekeeb.png?size=48" title="beekeeb" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img src="https://github.com/WonderPanda.png?size=48" title="WonderPanda" width="48" height="48"></a><a href="https://github.com/arpitBhalla" target="_blank"><img src="https://github.com/arpitBhalla.png?size=48" title="arpitBhalla" width="48" height="48"></a></section><section id="users"><h2 id="excited-to-be-used-by">Excited to be used by:</h2><a href="https://github.com/behrends" target="_blank"><img src="https://github.com/behrends.png?size=48" title="behrends" width="48" height="48"></a><a href="https://github.com/betomoedano" target="_blank"><img src="https://github.com/betomoedano.png?size=48" title="betomoedano" width="48" height="48"></a><a href="https://github.com/brentvatne" target="_blank"><img src="https://github.com/brentvatne.png?size=48" title="brentvatne" width="48" height="48"></a><a href="https://github.com/byCedric" target="_blank"><img src="https://github.com/byCedric.png?size=48" title="byCedric" width="48" height="48"></a><a href="https://github.com/circadian-risk" target="_blank"><img src="https://github.com/circadian-risk.png?size=48" title="circadian-risk" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img src="https://github.com/cpojer.png?size=48" title="cpojer" width="48" height="48"></a><a href="https://github.com/cubecull" target="_blank"><img src="https://github.com/cubecull.png?size=48" title="cubecull" width="48" height="48"></a><a href="https://github.com/erwinkn" target="_blank"><img src="https://github.com/erwinkn.png?size=48" title="erwinkn" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/ezra-en" target="_blank"><img src="https://github.com/ezra-en.png?size=48" title="ezra-en" width="48" height="48"></a><a href="https://github.com/feychenie" target="_blank"><img src="https://github.com/feychenie.png?size=48" title="feychenie" width="48" height="48"></a><a href="https://github.com/flaming-codes" target="_blank"><img src="https://github.com/flaming-codes.png?size=48" title="flaming-codes" width="48" height="48"></a><a href="https://github.com/fostertheweb" target="_blank"><img src="https://github.com/fostertheweb.png?size=48" title="fostertheweb" width="48" height="48"></a><a href="https://github.com/Giulio987" target="_blank"><img src="https://github.com/Giulio987.png?size=48" title="Giulio987" width="48" height="48"></a><a href="https://github.com/hi-ogawa" target="_blank"><img src="https://github.com/hi-ogawa.png?size=48" title="hi-ogawa" width="48" height="48"></a><a href="https://github.com/itsdevcoffee" target="_blank"><img src="https://github.com/itsdevcoffee.png?size=48" title="itsdevcoffee" width="48" height="48"></a><a href="https://github.com/jbolda" target="_blank"><img src="https://github.com/jbolda.png?size=48" title="jbolda" width="48" height="48"></a><a href="https://github.com/Kayoo-asso" target="_blank"><img src="https://github.com/Kayoo-asso.png?size=48" title="Kayoo-asso" width="48" height="48"></a><a href="https://github.com/kotofurumiya" target="_blank"><img src="https://github.com/kotofurumiya.png?size=48" title="kotofurumiya" width="48" height="48"></a><a href="https://github.com/Kudo" target="_blank"><img src="https://github.com/Kudo.png?size=48" title="Kudo" width="48" height="48"></a><a href="https://github.com/learn-anything" target="_blank"><img src="https://github.com/learn-anything.png?size=48" title="learn-anything" width="48" height="48"></a><a href="https://github.com/lluc" target="_blank"><img src="https://github.com/lluc.png?size=48" title="lluc" width="48" height="48"></a><a href="https://github.com/marksteve" target="_blank"><img src="https://github.com/marksteve.png?size=48" title="marksteve" width="48" height="48"></a><a href="https://github.com/miking-the-viking" target="_blank"><img src="https://github.com/miking-the-viking.png?size=48" title="miking-the-viking" width="48" height="48"></a><a href="https://github.com/mjamesderocher" target="_blank"><img src="https://github.com/mjamesderocher.png?size=48" title="mjamesderocher" width="48" height="48"></a><a href="https://github.com/mouktardev" target="_blank"><img src="https://github.com/mouktardev.png?size=48" title="mouktardev" width="48" height="48"></a><a href="https://github.com/nickmessing" target="_blank"><img src="https://github.com/nickmessing.png?size=48" title="nickmessing" width="48" height="48"></a><a href="https://github.com/nikitavoloboev" target="_blank"><img src="https://github.com/nikitavoloboev.png?size=48" title="nikitavoloboev" width="48" height="48"></a><a href="https://github.com/nkzw-tech" target="_blank"><img src="https://github.com/nkzw-tech.png?size=48" title="nkzw-tech" width="48" height="48"></a><a href="https://github.com/palerdot" target="_blank"><img src="https://github.com/palerdot.png?size=48" title="palerdot" width="48" height="48"></a><a href="https://github.com/PorcoRosso85" target="_blank"><img src="https://github.com/PorcoRosso85.png?size=48" title="PorcoRosso85" width="48" height="48"></a><a href="https://github.com/primodiumxyz" target="_blank"><img src="https://github.com/primodiumxyz.png?size=48" title="primodiumxyz" width="48" height="48"></a><a href="https://github.com/shaneosullivan" target="_blank"><img src="https://github.com/shaneosullivan.png?size=48" title="shaneosullivan" width="48" height="48"></a><a href="https://github.com/sudo-self" target="_blank"><img src="https://github.com/sudo-self.png?size=48" title="sudo-self" width="48" height="48"></a><a href="https://github.com/SuperSonicHub1" target="_blank"><img src="https://github.com/SuperSonicHub1.png?size=48" title="SuperSonicHub1" width="48" height="48"></a><a href="https://github.com/threepointone" target="_blank"><img src="https://github.com/threepointone.png?size=48" title="threepointone" width="48" height="48"></a><a href="https://github.com/uptonking" target="_blank"><img src="https://github.com/uptonking.png?size=48" title="uptonking" width="48" height="48"></a><a href="https://github.com/ViktorZhurbin" target="_blank"><img src="https://github.com/ViktorZhurbin.png?size=48" title="ViktorZhurbin" width="48" height="48"></a><a href="https://github.com/wilkerlucio" target="_blank"><img src="https://github.com/wilkerlucio.png?size=48" title="wilkerlucio" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img src="https://github.com/WonderPanda.png?size=48" title="WonderPanda" width="48" height="48"></a></section><hr><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/the-essentials/creating-stores/store/">Read the docs</a></p><hr><section id="family"><h2 id="meet-the-family">Meet the family</h2><p>TinyBase is part of a group of small libraries designed to help make rich client and local-first apps easier to build. Check out the others!</p><p><a href="https://synclets.org" target="_blank"><img src="https://synclets.org/favicon.svg?asImg" width="48"><br><b>Synclets</b></a><br>An open, storage-agnostic, sync engine development kit.</p><p><a href="https://tinywidgets.org" target="_blank"><img src="https://tinywidgets.org/favicon.svg?asImg" width="48"><br><b>TinyWidgets</b></a><br>A collection of tiny, reusable, UI components.</p><p><a href="https://tinytick.org" target="_blank"><img src="https://tinytick.org/favicon.svg?asImg" width="48"><br><b>TinyTick</b></a><br>A tiny but very useful task orchestrator.</p></section><hr><section id="about"><h2 id="about">About</h2><p>Modern apps deserve better. Why trade reactive user experiences to be able to use relational data? Or sacrifice features for bundle size? And why does the cloud do all the work <a href="https://localfirstweb.dev/" target="_blank">anyway</a>?</p><p>Building TinyBase was originally an interesting exercise for <a rel="me" href="https://tripleodeon.com">me</a> in API design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.</p><p>It could not have been built without these great <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://tinybase.org/youtube.webp"></a></section>
286
+ <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic <a href="https://tinybase.org/api/store/"><code>store</code></a> module alone, you&#x27;ll only add a gzipped <em>5.4kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>12.1kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>5.5kB</em>, the ui-react-dom components are another <em>3.8kB</em>, and everything is super fast. Life is easy when you have zero dependencies!</p><p>Read more about how TinyBase is structured and packaged in the <a href="https://tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>5.4kB</td><td>54.6kB</td></tr><tr><th class="right">tinybase (complete)</th><td>12.1kB</td><td>127.0kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>5.5kB</td><td>59.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>3.8kB</td><td>34.0kB</td></tr></tbody></table></div><section><h2 id="well-tested-and-documented">Well tested and documented.</h2><p>TinyBase has <em>100.0%</em> test coverage, including the code throughout the documentation - even on this page! The guides, demos, and API examples are designed to make it as easy as possible for you to get your TinyBase-powered app up and running.</p><p>Read more about how TinyBase is tested in the Unit <a href="https://tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Lines</th><td>2,408</td><td>2,408</td><td>100.0%</td></tr><tr><th class="right">Statements</th><td>2,617</td><td>2,617</td><td>100.0%</td></tr><tr><th class="right">Functions</th><td>1,046</td><td>1,046</td><td>100.0%</td></tr><tr><th class="right">Branches</th><td>906</td><td>906</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">7,286</td></tr><tr><th class="right">Assertions</th><td colspan="3">32,322</td></tr></tbody></table></div><hr><section id="sponsors"><h2 id="proud-to-be-supported-by">Proud to be supported by:</h2><a href="https://github.com/fastrepl" target="_blank"><img src="https://github.com/fastrepl.png?size=48" title="fastrepl" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/dylmye" target="_blank"><img src="https://github.com/dylmye.png?size=48" title="dylmye" width="48" height="48"></a><a href="https://github.com/ComputelessComputer" target="_blank"><img src="https://github.com/ComputelessComputer.png?size=48" title="ComputelessComputer" width="48" height="48"></a><a href="https://github.com/cancelself" target="_blank"><img src="https://github.com/cancelself.png?size=48" title="cancelself" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img src="https://github.com/cpojer.png?size=48" title="cpojer" width="48" height="48"></a><a href="https://github.com/beekeeb" target="_blank"><img src="https://github.com/beekeeb.png?size=48" title="beekeeb" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img src="https://github.com/WonderPanda.png?size=48" title="WonderPanda" width="48" height="48"></a><a href="https://github.com/arpitBhalla" target="_blank"><img src="https://github.com/arpitBhalla.png?size=48" title="arpitBhalla" width="48" height="48"></a></section><section id="users"><h2 id="excited-to-be-used-by">Excited to be used by:</h2><a href="https://github.com/behrends" target="_blank"><img src="https://github.com/behrends.png?size=48" title="behrends" width="48" height="48"></a><a href="https://github.com/betomoedano" target="_blank"><img src="https://github.com/betomoedano.png?size=48" title="betomoedano" width="48" height="48"></a><a href="https://github.com/brentvatne" target="_blank"><img src="https://github.com/brentvatne.png?size=48" title="brentvatne" width="48" height="48"></a><a href="https://github.com/byCedric" target="_blank"><img src="https://github.com/byCedric.png?size=48" title="byCedric" width="48" height="48"></a><a href="https://github.com/circadian-risk" target="_blank"><img src="https://github.com/circadian-risk.png?size=48" title="circadian-risk" width="48" height="48"></a><a href="https://github.com/cpojer" target="_blank"><img src="https://github.com/cpojer.png?size=48" title="cpojer" width="48" height="48"></a><a href="https://github.com/cubecull" target="_blank"><img src="https://github.com/cubecull.png?size=48" title="cubecull" width="48" height="48"></a><a href="https://github.com/erwinkn" target="_blank"><img src="https://github.com/erwinkn.png?size=48" title="erwinkn" width="48" height="48"></a><a href="https://github.com/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/ezra-en" target="_blank"><img src="https://github.com/ezra-en.png?size=48" title="ezra-en" width="48" height="48"></a><a href="https://github.com/feychenie" target="_blank"><img src="https://github.com/feychenie.png?size=48" title="feychenie" width="48" height="48"></a><a href="https://github.com/flaming-codes" target="_blank"><img src="https://github.com/flaming-codes.png?size=48" title="flaming-codes" width="48" height="48"></a><a href="https://github.com/fostertheweb" target="_blank"><img src="https://github.com/fostertheweb.png?size=48" title="fostertheweb" width="48" height="48"></a><a href="https://github.com/Giulio987" target="_blank"><img src="https://github.com/Giulio987.png?size=48" title="Giulio987" width="48" height="48"></a><a href="https://github.com/hi-ogawa" target="_blank"><img src="https://github.com/hi-ogawa.png?size=48" title="hi-ogawa" width="48" height="48"></a><a href="https://github.com/itsdevcoffee" target="_blank"><img src="https://github.com/itsdevcoffee.png?size=48" title="itsdevcoffee" width="48" height="48"></a><a href="https://github.com/jbolda" target="_blank"><img src="https://github.com/jbolda.png?size=48" title="jbolda" width="48" height="48"></a><a href="https://github.com/Kayoo-asso" target="_blank"><img src="https://github.com/Kayoo-asso.png?size=48" title="Kayoo-asso" width="48" height="48"></a><a href="https://github.com/kotofurumiya" target="_blank"><img src="https://github.com/kotofurumiya.png?size=48" title="kotofurumiya" width="48" height="48"></a><a href="https://github.com/Kudo" target="_blank"><img src="https://github.com/Kudo.png?size=48" title="Kudo" width="48" height="48"></a><a href="https://github.com/learn-anything" target="_blank"><img src="https://github.com/learn-anything.png?size=48" title="learn-anything" width="48" height="48"></a><a href="https://github.com/lluc" target="_blank"><img src="https://github.com/lluc.png?size=48" title="lluc" width="48" height="48"></a><a href="https://github.com/marksteve" target="_blank"><img src="https://github.com/marksteve.png?size=48" title="marksteve" width="48" height="48"></a><a href="https://github.com/miking-the-viking" target="_blank"><img src="https://github.com/miking-the-viking.png?size=48" title="miking-the-viking" width="48" height="48"></a><a href="https://github.com/mjamesderocher" target="_blank"><img src="https://github.com/mjamesderocher.png?size=48" title="mjamesderocher" width="48" height="48"></a><a href="https://github.com/mouktardev" target="_blank"><img src="https://github.com/mouktardev.png?size=48" title="mouktardev" width="48" height="48"></a><a href="https://github.com/nickmessing" target="_blank"><img src="https://github.com/nickmessing.png?size=48" title="nickmessing" width="48" height="48"></a><a href="https://github.com/nikitavoloboev" target="_blank"><img src="https://github.com/nikitavoloboev.png?size=48" title="nikitavoloboev" width="48" height="48"></a><a href="https://github.com/nkzw-tech" target="_blank"><img src="https://github.com/nkzw-tech.png?size=48" title="nkzw-tech" width="48" height="48"></a><a href="https://github.com/palerdot" target="_blank"><img src="https://github.com/palerdot.png?size=48" title="palerdot" width="48" height="48"></a><a href="https://github.com/PorcoRosso85" target="_blank"><img src="https://github.com/PorcoRosso85.png?size=48" title="PorcoRosso85" width="48" height="48"></a><a href="https://github.com/primodiumxyz" target="_blank"><img src="https://github.com/primodiumxyz.png?size=48" title="primodiumxyz" width="48" height="48"></a><a href="https://github.com/shaneosullivan" target="_blank"><img src="https://github.com/shaneosullivan.png?size=48" title="shaneosullivan" width="48" height="48"></a><a href="https://github.com/sudo-self" target="_blank"><img src="https://github.com/sudo-self.png?size=48" title="sudo-self" width="48" height="48"></a><a href="https://github.com/SuperSonicHub1" target="_blank"><img src="https://github.com/SuperSonicHub1.png?size=48" title="SuperSonicHub1" width="48" height="48"></a><a href="https://github.com/threepointone" target="_blank"><img src="https://github.com/threepointone.png?size=48" title="threepointone" width="48" height="48"></a><a href="https://github.com/uptonking" target="_blank"><img src="https://github.com/uptonking.png?size=48" title="uptonking" width="48" height="48"></a><a href="https://github.com/ViktorZhurbin" target="_blank"><img src="https://github.com/ViktorZhurbin.png?size=48" title="ViktorZhurbin" width="48" height="48"></a><a href="https://github.com/wilkerlucio" target="_blank"><img src="https://github.com/wilkerlucio.png?size=48" title="wilkerlucio" width="48" height="48"></a><a href="https://github.com/WonderPanda" target="_blank"><img src="https://github.com/WonderPanda.png?size=48" title="WonderPanda" width="48" height="48"></a></section><hr><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/the-essentials/creating-stores/store/">Read the docs</a></p><hr><section id="family"><h2 id="meet-the-family">Meet the family</h2><p>TinyBase is part of a group of small libraries designed to help make rich client and local-first apps easier to build. Check out the others!</p><p><a href="https://synclets.org" target="_blank"><img src="https://synclets.org/favicon.svg?asImg" width="48"><br><b>Synclets</b></a><br>An open, storage-agnostic, sync engine development kit.</p><p><a href="https://tinywidgets.org" target="_blank"><img src="https://tinywidgets.org/favicon.svg?asImg" width="48"><br><b>TinyWidgets</b></a><br>A collection of tiny, reusable, UI components.</p><p><a href="https://tinytick.org" target="_blank"><img src="https://tinytick.org/favicon.svg?asImg" width="48"><br><b>TinyTick</b></a><br>A tiny but very useful task orchestrator.</p></section><hr><section id="about"><h2 id="about">About</h2><p>Modern apps deserve better. Why trade reactive user experiences to be able to use relational data? Or sacrifice features for bundle size? And why does the cloud do all the work <a href="https://localfirstweb.dev/" target="_blank">anyway</a>?</p><p>Building TinyBase was originally an interesting exercise for <a rel="me" href="https://tripleodeon.com">me</a> in API design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.</p><p>It could not have been built without these great <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://tinybase.org/youtube.webp"></a></section>
package/releases.md CHANGED
@@ -339,7 +339,7 @@ export class MyDurableObject extends WsServerDurableObject {
339
339
  }
340
340
  ```
341
341
 
342
- <p>You can get started quickly with this architecture using the <a href="https://github.com/tinyplex/vite-tinybase-ts-react-sync-durable-object">new Vite template</a> that accompanies this release.</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&#x27;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 API 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 &#x27;loading&#x27; (ie inbound syncing), and 2 when it is &#x27;saving&#x27; (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>
342
+ <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&#x27;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 API 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 &#x27;loading&#x27; (ie inbound syncing), and 2 when it is &#x27;saving&#x27; (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>
343
343
 
344
344
  ```js
345
345
  import postgres from 'postgres';
@@ -66,6 +66,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
66
66
  const objHas = (obj, id) => id in obj;
67
67
  const objForEach = (obj, cb) =>
68
68
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
69
+ const objToArray = (obj, cb) =>
70
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
71
+ const objMap = (obj, cb) =>
72
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
69
73
  const objSize = (obj) => size(objIds(obj));
70
74
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
71
75
  const objEnsure = (obj, id, getDefaultValue) => {
@@ -80,7 +84,16 @@ const jsonParse = JSON.parse;
80
84
  const jsonStringWithUndefined = (obj) =>
81
85
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
82
86
  const jsonParseWithUndefined = (str) =>
83
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
87
+ // JSON.parse reviver removes properties with undefined values
88
+ replaceUndefinedString(jsonParse(str));
89
+ const replaceUndefinedString = (obj) =>
90
+ obj === UNDEFINED
91
+ ? void 0
92
+ : isArray(obj)
93
+ ? arrayMap(obj, replaceUndefinedString)
94
+ : isObject(obj)
95
+ ? objMap(obj, replaceUndefinedString)
96
+ : obj;
84
97
 
85
98
  const MESSAGE_SEPARATOR = '\n';
86
99
  const ifPayloadValid = (payload, then) => {
@@ -66,6 +66,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
66
66
  const objHas = (obj, id) => id in obj;
67
67
  const objForEach = (obj, cb) =>
68
68
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
69
+ const objToArray = (obj, cb) =>
70
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
71
+ const objMap = (obj, cb) =>
72
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
69
73
  const objSize = (obj) => size(objIds(obj));
70
74
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
71
75
  const objEnsure = (obj, id, getDefaultValue) => {
@@ -80,7 +84,16 @@ const jsonParse = JSON.parse;
80
84
  const jsonStringWithUndefined = (obj) =>
81
85
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
82
86
  const jsonParseWithUndefined = (str) =>
83
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
87
+ // JSON.parse reviver removes properties with undefined values
88
+ replaceUndefinedString(jsonParse(str));
89
+ const replaceUndefinedString = (obj) =>
90
+ obj === UNDEFINED
91
+ ? void 0
92
+ : isArray(obj)
93
+ ? arrayMap(obj, replaceUndefinedString)
94
+ : isObject(obj)
95
+ ? objMap(obj, replaceUndefinedString)
96
+ : obj;
84
97
 
85
98
  const MESSAGE_SEPARATOR = '\n';
86
99
  const ifPayloadValid = (payload, then) => {
@@ -79,6 +79,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
79
79
  const objHas = (obj, id) => id in obj;
80
80
  const objForEach = (obj, cb) =>
81
81
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
82
+ const objToArray = (obj, cb) =>
83
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
84
+ const objMap = (obj, cb) =>
85
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
82
86
  const objSize = (obj) => size(objIds(obj));
83
87
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
84
88
  const objEnsure = (obj, id, getDefaultValue) => {
@@ -226,7 +230,16 @@ const jsonParse = JSON.parse;
226
230
  const jsonStringWithUndefined = (obj) =>
227
231
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
228
232
  const jsonParseWithUndefined = (str) =>
229
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
233
+ // JSON.parse reviver removes properties with undefined values
234
+ replaceUndefinedString(jsonParse(str));
235
+ const replaceUndefinedString = (obj) =>
236
+ obj === UNDEFINED
237
+ ? void 0
238
+ : isArray(obj)
239
+ ? arrayMap(obj, replaceUndefinedString)
240
+ : isObject(obj)
241
+ ? objMap(obj, replaceUndefinedString)
242
+ : obj;
230
243
 
231
244
  const MESSAGE_SEPARATOR = '\n';
232
245
  const ifPayloadValid = (payload, then) => {
@@ -79,6 +79,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
79
79
  const objHas = (obj, id) => id in obj;
80
80
  const objForEach = (obj, cb) =>
81
81
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
82
+ const objToArray = (obj, cb) =>
83
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
84
+ const objMap = (obj, cb) =>
85
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
82
86
  const objSize = (obj) => size(objIds(obj));
83
87
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
84
88
  const objEnsure = (obj, id, getDefaultValue) => {
@@ -226,7 +230,16 @@ const jsonParse = JSON.parse;
226
230
  const jsonStringWithUndefined = (obj) =>
227
231
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
228
232
  const jsonParseWithUndefined = (str) =>
229
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
233
+ // JSON.parse reviver removes properties with undefined values
234
+ replaceUndefinedString(jsonParse(str));
235
+ const replaceUndefinedString = (obj) =>
236
+ obj === UNDEFINED
237
+ ? void 0
238
+ : isArray(obj)
239
+ ? arrayMap(obj, replaceUndefinedString)
240
+ : isObject(obj)
241
+ ? objMap(obj, replaceUndefinedString)
242
+ : obj;
230
243
 
231
244
  const MESSAGE_SEPARATOR = '\n';
232
245
  const ifPayloadValid = (payload, then) => {
@@ -67,6 +67,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
67
67
  const objHas = (obj, id) => id in obj;
68
68
  const objForEach = (obj, cb) =>
69
69
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
70
+ const objToArray = (obj, cb) =>
71
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
72
+ const objMap = (obj, cb) =>
73
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
70
74
  const objValues = (obj) => object.values(obj);
71
75
  const objSize = (obj) => size(objIds(obj));
72
76
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
@@ -82,7 +86,16 @@ const jsonParse = JSON.parse;
82
86
  const jsonStringWithUndefined = (obj) =>
83
87
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
84
88
  const jsonParseWithUndefined = (str) =>
85
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
89
+ // JSON.parse reviver removes properties with undefined values
90
+ replaceUndefinedString(jsonParse(str));
91
+ const replaceUndefinedString = (obj) =>
92
+ obj === UNDEFINED
93
+ ? void 0
94
+ : isArray(obj)
95
+ ? arrayMap(obj, replaceUndefinedString)
96
+ : isObject(obj)
97
+ ? objMap(obj, replaceUndefinedString)
98
+ : obj;
86
99
 
87
100
  const MESSAGE_SEPARATOR = '\n';
88
101
  const ifPayloadValid = (payload, then) => {
@@ -67,6 +67,10 @@ const objNew = (entries = []) => object.fromEntries(entries);
67
67
  const objHas = (obj, id) => id in obj;
68
68
  const objForEach = (obj, cb) =>
69
69
  arrayForEach(objEntries(obj), ([id, value]) => cb(value, id));
70
+ const objToArray = (obj, cb) =>
71
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
72
+ const objMap = (obj, cb) =>
73
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
70
74
  const objValues = (obj) => object.values(obj);
71
75
  const objSize = (obj) => size(objIds(obj));
72
76
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
@@ -82,7 +86,16 @@ const jsonParse = JSON.parse;
82
86
  const jsonStringWithUndefined = (obj) =>
83
87
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
84
88
  const jsonParseWithUndefined = (str) =>
85
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
89
+ // JSON.parse reviver removes properties with undefined values
90
+ replaceUndefinedString(jsonParse(str));
91
+ const replaceUndefinedString = (obj) =>
92
+ obj === UNDEFINED
93
+ ? void 0
94
+ : isArray(obj)
95
+ ? arrayMap(obj, replaceUndefinedString)
96
+ : isObject(obj)
97
+ ? objMap(obj, replaceUndefinedString)
98
+ : obj;
86
99
 
87
100
  const MESSAGE_SEPARATOR = '\n';
88
101
  const ifPayloadValid = (payload, then) => {
@@ -212,7 +212,16 @@ const jsonStringWithMap = (obj) =>
212
212
  const jsonStringWithUndefined = (obj) =>
213
213
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
214
214
  const jsonParseWithUndefined = (str) =>
215
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
215
+ // JSON.parse reviver removes properties with undefined values
216
+ replaceUndefinedString(jsonParse(str));
217
+ const replaceUndefinedString = (obj) =>
218
+ obj === UNDEFINED
219
+ ? void 0
220
+ : isArray(obj)
221
+ ? arrayMap(obj, replaceUndefinedString)
222
+ : isObject(obj)
223
+ ? objMap(obj, replaceUndefinedString)
224
+ : obj;
216
225
 
217
226
  const collSizeN = (collSizer) => (coll) =>
218
227
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -212,7 +212,16 @@ const jsonStringWithMap = (obj) =>
212
212
  const jsonStringWithUndefined = (obj) =>
213
213
  jsonString(obj, (_key, value) => (isUndefined(value) ? UNDEFINED : value));
214
214
  const jsonParseWithUndefined = (str) =>
215
- jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
215
+ // JSON.parse reviver removes properties with undefined values
216
+ replaceUndefinedString(jsonParse(str));
217
+ const replaceUndefinedString = (obj) =>
218
+ obj === UNDEFINED
219
+ ? void 0
220
+ : isArray(obj)
221
+ ? arrayMap(obj, replaceUndefinedString)
222
+ : isObject(obj)
223
+ ? objMap(obj, replaceUndefinedString)
224
+ : obj;
216
225
 
217
226
  const collSizeN = (collSizer) => (coll) =>
218
227
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);