tinybase 9.5.0-beta.0 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/@types/_internal/store/with-schemas/index.d.ts +43 -8
  2. package/@types/mergeable-store/with-schemas/index.d.ts +30 -11
  3. package/@types/queries/index.d.ts +11 -11
  4. package/@types/queries/with-schemas/index.d.ts +17 -3
  5. package/@types/schematizers/index.d.ts +6 -4
  6. package/@types/schematizers/schematizer-arktype/index.d.ts +6 -6
  7. package/@types/schematizers/schematizer-arktype/with-schemas/index.d.ts +112 -1
  8. package/@types/schematizers/schematizer-effect/index.d.ts +9 -11
  9. package/@types/schematizers/schematizer-effect/with-schemas/index.d.ts +114 -1
  10. package/@types/schematizers/schematizer-typebox/index.d.ts +7 -7
  11. package/@types/schematizers/schematizer-typebox/with-schemas/index.d.ts +114 -1
  12. package/@types/schematizers/schematizer-valibot/index.d.ts +6 -6
  13. package/@types/schematizers/schematizer-valibot/with-schemas/index.d.ts +112 -1
  14. package/@types/schematizers/schematizer-yup/index.d.ts +5 -4
  15. package/@types/schematizers/schematizer-yup/with-schemas/index.d.ts +112 -1
  16. package/@types/schematizers/schematizer-zod/index.d.ts +6 -6
  17. package/@types/schematizers/schematizer-zod/with-schemas/index.d.ts +112 -1
  18. package/@types/schematizers/with-schemas/index.d.ts +113 -4
  19. package/@types/store/index.d.ts +175 -16
  20. package/@types/store/with-schemas/index.d.ts +238 -55
  21. package/@types/synchronizers/with-schemas/index.d.ts +12 -2
  22. package/@types/ui-react/with-schemas/index.d.ts +576 -7
  23. package/@types/ui-react-dom/index.d.ts +10 -10
  24. package/@types/ui-react-dom/with-schemas/index.d.ts +94 -10
  25. package/@types/ui-react-dom-charts/index.d.ts +7 -7
  26. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +7 -7
  27. package/@types/ui-react-inspector/index.d.ts +1 -1
  28. package/@types/ui-react-inspector/with-schemas/index.d.ts +1 -1
  29. package/@types/ui-solid/with-schemas/index.d.ts +340 -7
  30. package/@types/ui-solid-dom/index.d.ts +10 -10
  31. package/@types/ui-solid-dom/with-schemas/index.d.ts +94 -10
  32. package/@types/ui-solid-inspector/index.d.ts +1 -1
  33. package/@types/ui-solid-inspector/with-schemas/index.d.ts +1 -1
  34. package/@types/ui-svelte/with-schemas/index.d.ts +30 -0
  35. package/@types/ui-svelte-dom/index.d.ts +10 -10
  36. package/@types/ui-svelte-dom/with-schemas/index.d.ts +94 -10
  37. package/@types/ui-svelte-inspector/index.d.ts +1 -1
  38. package/@types/ui-svelte-inspector/with-schemas/index.d.ts +1 -1
  39. package/agents.md +4 -0
  40. package/index.js +76 -22
  41. package/mergeable-store/index.js +76 -22
  42. package/mergeable-store/with-schemas/index.js +76 -22
  43. package/min/index.js +1 -1
  44. package/min/index.js.gz +0 -0
  45. package/min/mergeable-store/index.js +1 -1
  46. package/min/mergeable-store/index.js.gz +0 -0
  47. package/min/mergeable-store/with-schemas/index.js +1 -1
  48. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  49. package/min/omni/index.js +1 -1
  50. package/min/omni/index.js.gz +0 -0
  51. package/min/omni/with-schemas/index.js +1 -1
  52. package/min/omni/with-schemas/index.js.gz +0 -0
  53. package/min/schematizers/index.js +1 -1
  54. package/min/schematizers/index.js.gz +0 -0
  55. package/min/schematizers/schematizer-arktype/index.js +1 -1
  56. package/min/schematizers/schematizer-arktype/index.js.gz +0 -0
  57. package/min/schematizers/schematizer-arktype/with-schemas/index.js +1 -1
  58. package/min/schematizers/schematizer-arktype/with-schemas/index.js.gz +0 -0
  59. package/min/schematizers/schematizer-effect/index.js +1 -1
  60. package/min/schematizers/schematizer-effect/index.js.gz +0 -0
  61. package/min/schematizers/schematizer-effect/with-schemas/index.js +1 -1
  62. package/min/schematizers/schematizer-effect/with-schemas/index.js.gz +0 -0
  63. package/min/schematizers/schematizer-typebox/index.js +1 -1
  64. package/min/schematizers/schematizer-typebox/index.js.gz +0 -0
  65. package/min/schematizers/schematizer-typebox/with-schemas/index.js +1 -1
  66. package/min/schematizers/schematizer-typebox/with-schemas/index.js.gz +0 -0
  67. package/min/schematizers/schematizer-valibot/index.js +1 -1
  68. package/min/schematizers/schematizer-valibot/index.js.gz +0 -0
  69. package/min/schematizers/schematizer-valibot/with-schemas/index.js +1 -1
  70. package/min/schematizers/schematizer-valibot/with-schemas/index.js.gz +0 -0
  71. package/min/schematizers/schematizer-yup/index.js +1 -1
  72. package/min/schematizers/schematizer-yup/index.js.gz +0 -0
  73. package/min/schematizers/schematizer-yup/with-schemas/index.js +1 -1
  74. package/min/schematizers/schematizer-yup/with-schemas/index.js.gz +0 -0
  75. package/min/schematizers/schematizer-zod/index.js +1 -1
  76. package/min/schematizers/schematizer-zod/index.js.gz +0 -0
  77. package/min/schematizers/schematizer-zod/with-schemas/index.js +1 -1
  78. package/min/schematizers/schematizer-zod/with-schemas/index.js.gz +0 -0
  79. package/min/schematizers/with-schemas/index.js +1 -1
  80. package/min/schematizers/with-schemas/index.js.gz +0 -0
  81. package/min/store/index.js +1 -1
  82. package/min/store/index.js.gz +0 -0
  83. package/min/store/with-schemas/index.js +1 -1
  84. package/min/store/with-schemas/index.js.gz +0 -0
  85. package/min/ui-react-inspector/index.js +1 -1
  86. package/min/ui-react-inspector/index.js.gz +0 -0
  87. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  88. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  89. package/min/ui-solid-inspector/index.js +1 -1
  90. package/min/ui-solid-inspector/index.js.gz +0 -0
  91. package/min/ui-solid-inspector/with-schemas/index.js +1 -1
  92. package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
  93. package/min/ui-svelte-inspector/index.js +1 -1
  94. package/min/ui-svelte-inspector/index.js.gz +0 -0
  95. package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
  96. package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
  97. package/min/with-schemas/index.js +1 -1
  98. package/min/with-schemas/index.js.gz +0 -0
  99. package/omni/index.js +76 -22
  100. package/omni/with-schemas/index.js +76 -22
  101. package/package.json +5 -5
  102. package/readme.md +3 -3
  103. package/releases.md +32 -2
  104. package/schematizers/index.js +54 -6
  105. package/schematizers/schematizer-arktype/index.js +99 -19
  106. package/schematizers/schematizer-arktype/with-schemas/index.js +99 -19
  107. package/schematizers/schematizer-effect/index.js +101 -11
  108. package/schematizers/schematizer-effect/with-schemas/index.js +101 -11
  109. package/schematizers/schematizer-typebox/index.js +87 -11
  110. package/schematizers/schematizer-typebox/with-schemas/index.js +87 -11
  111. package/schematizers/schematizer-valibot/index.js +125 -21
  112. package/schematizers/schematizer-valibot/with-schemas/index.js +125 -21
  113. package/schematizers/schematizer-yup/index.js +58 -14
  114. package/schematizers/schematizer-yup/with-schemas/index.js +58 -14
  115. package/schematizers/schematizer-zod/index.js +131 -12
  116. package/schematizers/schematizer-zod/with-schemas/index.js +131 -12
  117. package/schematizers/with-schemas/index.js +54 -6
  118. package/store/index.js +76 -22
  119. package/store/with-schemas/index.js +76 -22
  120. package/ui-react-inspector/index.js +76 -22
  121. package/ui-react-inspector/with-schemas/index.js +76 -22
  122. package/ui-solid-inspector/index.js +76 -22
  123. package/ui-solid-inspector/with-schemas/index.js +76 -22
  124. package/ui-svelte/index.js +1 -1
  125. package/ui-svelte/with-schemas/index.js +1 -1
  126. package/ui-svelte-dom/index.js +2 -2
  127. package/ui-svelte-dom/with-schemas/index.js +2 -2
  128. package/ui-svelte-inspector/index.js +78 -24
  129. package/ui-svelte-inspector/with-schemas/index.js +78 -24
  130. package/with-schemas/index.js +76 -22
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- <link rel="preload" as="image" href="https://tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/solid.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/svelte.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/shots/styled-chart-react-demo.png"><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/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/expo.png?size=48"><link rel="preload" as="image" href="https://github.com/braden-w.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/gonza224.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="local-first"><em>Local</em> first.</h2><h2 id="sync-on-demand"><em>Sync</em> on demand.</h2><h2 id="fast-always"><em>Fast</em> always.</h2><p>TinyBase is a reactive in-memory data store with persistence and synchronization for local-first JavaScript and TypeScript apps that need to feel instant, work offline, and stay consistent when they come back online.</p></section><p><a href="https://tinybase.org/guides/releases/#v9-4"><em>NEW!</em> v9.4 release</a></p><p><span id="one-with">&quot;The one with <code>selectAll</code>!&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="your-first-tinybase-app">Your first <em>TinyBase</em> app</h2><p>Create a todo list, a chat app, a drawing tool, a charting app, or a tic-tac-toe game - with sync &amp; persistence! - in less than 60s.</p></section>
1
+ <link rel="preload" as="image" href="https://tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/solid.svg?asImg"><link rel="preload" as="image" href="https://tinybase.org/svelte.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/shots/styled-chart-react-demo.png"><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/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/expo.png?size=48"><link rel="preload" as="image" href="https://github.com/braden-w.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/gonza224.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="local-first"><em>Local</em> first.</h2><h2 id="sync-on-demand"><em>Sync</em> on demand.</h2><h2 id="fast-always"><em>Fast</em> always.</h2><p>TinyBase is a reactive in-memory data store with persistence and synchronization for local-first JavaScript and TypeScript apps that need to feel instant, work offline, and stay consistent when they come back online.</p></section><p><a href="https://tinybase.org/guides/releases/#v9-5"><em>NEW!</em> v9.5 release</a></p><p><span id="one-with">&quot;The one with enums and unions!&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="your-first-tinybase-app">Your first <em>TinyBase</em> app</h2><p>Create a todo list, a chat app, a drawing tool, a charting app, or a tic-tac-toe game - with sync &amp; persistence! - in less than 60s.</p></section>
2
2
 
3
3
  ```bash
4
4
  > npm create tinybase@latest
@@ -6,7 +6,7 @@
6
6
  📦 Creating your project...
7
7
  ```
8
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>, <a href="#pre-built-reactive-components">pre-built components</a>, and <a href="#local-first-data-visualizations">charts</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-or-a-database">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">7.2kB - 16.2kB</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><h3 id="ui-frameworks"><a href="https://tinybase.org/guides/">UI Frameworks</a></h3><div><a href="https://tinybase.org/guides/building-uis-with-react/getting-started-with-ui-react"><img src="https://tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://tinybase.org/guides/building-uis-with-solid/getting-started-with-ui-solid"><img src="https://tinybase.org/solid.svg?asImg" width="48"> Solid</a></div><div><a href="https://tinybase.org/guides/building-uis-with-svelte/getting-started-with-ui-svelte"><img src="https://tinybase.org/svelte.svg?asImg" width="48"> Svelte</a></div><h3 id="storage-sync"><a href="https://tinybase.org/guides/persistence/">Storage &amp; Sync</a></h3><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><h3 id="schema-systems"><a href="https://tinybase.org/guides/schemas/using-schematizers/">Schema Systems</a></h3><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/9.4.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>
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>, <a href="#pre-built-reactive-components">pre-built components</a>, and <a href="#local-first-data-visualizations">charts</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-or-a-database">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">7.3kB - 16.4kB</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><h3 id="ui-frameworks"><a href="https://tinybase.org/guides/">UI Frameworks</a></h3><div><a href="https://tinybase.org/guides/building-uis-with-react/getting-started-with-ui-react"><img src="https://tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://tinybase.org/guides/building-uis-with-solid/getting-started-with-ui-solid"><img src="https://tinybase.org/solid.svg?asImg" width="48"> Solid</a></div><div><a href="https://tinybase.org/guides/building-uis-with-svelte/getting-started-with-ui-svelte"><img src="https://tinybase.org/svelte.svg?asImg" width="48"> Svelte</a></div><h3 id="storage-sync"><a href="https://tinybase.org/guides/persistence/">Storage &amp; Sync</a></h3><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><h3 id="schema-systems"><a href="https://tinybase.org/guides/schemas/using-schematizers/">Schema Systems</a></h3><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/9.5.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>
10
10
 
11
11
  ```js
12
12
  import {createStore} from 'tinybase';
@@ -283,4 +283,4 @@ console.log(store.getCell('pets', 'felix', 'sold'));
283
283
  // -> false
284
284
  ```
285
285
 
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>7.2kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>16.2kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>5.9kB</em>, the ui-react-dom components are another <em>4.3kB</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>7.2kB</td><td>77.7kB</td></tr><tr><th class="right">tinybase (complete)</th><td>16.2kB</td><td>185.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>5.9kB</td><td>64.2kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>4.3kB</td><td>38.4kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom-charts/">ui-react-dom-charts</a></th><td>8.7kB</td><td>64.9kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-solid/">ui-solid</a></th><td>5.8kB</td><td>63.2kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-solid-dom/">ui-solid-dom</a></th><td>4.9kB</td><td>48.0kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-svelte/">ui-svelte</a></th><td>5.1kB</td><td>62.5kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-svelte-dom/">ui-svelte-dom</a></th><td>6.0kB</td><td>62.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 <a href="https://tinybase.org/api/">API</a> 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">Tested lines</th><td>5,107</td><td>5,107</td><td>100.0%</td></tr><tr><th class="right">Tested statements</th><td>5,527</td><td>5,527</td><td>100.0%</td></tr><tr><th class="right">Tested functions</th><td>2,424</td><td>2,424</td><td>100.0%</td></tr><tr><th class="right">Tested branches</th><td>1,761</td><td>1,761</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">9,000</td></tr><tr><th class="right">Assertions</th><td colspan="3">37,880</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/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/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/braden-w" target="_blank"><img src="https://github.com/braden-w.png?size=48" title="braden-w" 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/gonza224" target="_blank"><img src="https://github.com/gonza224.png?size=48" title="gonza224" 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](/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>7.3kB</em> to your app. Incrementally add the other modules as you need more functionality, or get it all for <em>16.4kB</em>.</p><p>The optional <a href="https://tinybase.org/api/ui-react/"><code>ui-react</code></a> module is just <em>5.9kB</em>, the ui-react-dom components are another <em>4.3kB</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>7.3kB</td><td>79.8kB</td></tr><tr><th class="right">tinybase (complete)</th><td>16.4kB</td><td>187.8kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react/">ui-react</a></th><td>5.9kB</td><td>64.2kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom/">ui-react-dom</a></th><td>4.3kB</td><td>38.4kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-react-dom-charts/">ui-react-dom-charts</a></th><td>8.7kB</td><td>64.9kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-solid/">ui-solid</a></th><td>5.8kB</td><td>63.2kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-solid-dom/">ui-solid-dom</a></th><td>4.9kB</td><td>48.0kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-svelte/">ui-svelte</a></th><td>5.1kB</td><td>62.5kB</td></tr><tr><th class="right"><a href="https://tinybase.org/api/ui-svelte-dom/">ui-svelte-dom</a></th><td>6.0kB</td><td>62.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 <a href="https://tinybase.org/api/">API</a> 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">Tested lines</th><td>5,117</td><td>5,117</td><td>100.0%</td></tr><tr><th class="right">Tested statements</th><td>5,537</td><td>5,537</td><td>100.0%</td></tr><tr><th class="right">Tested functions</th><td>2,428</td><td>2,428</td><td>100.0%</td></tr><tr><th class="right">Tested branches</th><td>1,791</td><td>1,791</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">9,038</td></tr><tr><th class="right">Assertions</th><td colspan="3">38,113</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/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/expo" target="_blank"><img src="https://github.com/expo.png?size=48" title="expo" width="48" height="48"></a><a href="https://github.com/braden-w" target="_blank"><img src="https://github.com/braden-w.png?size=48" title="braden-w" 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/gonza224" target="_blank"><img src="https://github.com/gonza224.png?size=48" title="gonza224" 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](/api/) design, minification, and documentation. But now it has taken on a life of its own, and has grown beyond my wildest expectations.</p><p>It could not have been built without these great <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://tinybase.org/youtube.webp"></a></section>
package/releases.md CHANGED
@@ -1,7 +1,37 @@
1
- <link rel="preload" as="image" href="https://tinybase.org/shots/styled-chart-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/axis-overrides-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-svelte-full-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/partykit.gif"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/car-analysis-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/movie-database-demo.png"><p>This is a reverse chronological list of the major TinyBase releases, with highlighted features.</p><hr><h1 id="v9-4">v9.4</h1><h2 id="selectall"><code>selectAll</code></h2><p><a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> can now select every <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> present in a root or joined <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> with the <code>selectAll</code> keyword (as requested in issue <a href="https://github.com/tinyplex/tinybase/issues/40">#40</a>). Heterogeneous Rows are supported directly: each result <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> contains only its source <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>&#x27;s Cells, while the result <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>&#x27;s <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> are their reactive union.</p><p>Joined selections retain their <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> by default, or can take a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> prefix or mapping callback. Selection clauses are applied in declaration order, and source <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> within a <code>selectAll</code> function call are processed lexically, so collision behavior is deterministic.</p>
1
+ <link rel="preload" as="image" href="https://tinybase.org/shots/styled-chart-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/axis-overrides-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-solid-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-svelte-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/editablevalueview-svelte-full-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/inspector-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/partykit.gif"><link rel="preload" as="image" href="https://tinybase.org/shots/sortedtableinhtmltable-react-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/car-analysis-demo.png"><link rel="preload" as="image" href="https://tinybase.org/shots/movie-database-demo.png"><p>This is a reverse chronological list of the major TinyBase releases, with highlighted features.</p><hr><h1 id="v9-5">v9.5</h1><h2 id="schema-enums">Schema Enums</h2><p><a href="https://tinybase.org/api/store/type-aliases/schema/cellschema/"><code>CellSchema</code></a> and <a href="https://tinybase.org/api/store/type-aliases/schema/valueschema/"><code>ValueSchema</code></a> can now use an <code>enum</code> property instead of <code>type</code> to allow only specific primitive values (as requested in issue <a href="https://github.com/tinyplex/tinybase/issues/38">#38</a>). Enums must be non-empty, can mix strings, finite numbers, and booleans, and continue to use <code>allowNull</code> when <code>null</code> is also valid.</p>
2
2
 
3
3
  ```js
4
- import {createQueries, createStore} from 'tinybase';
4
+ import {createStore} from 'tinybase';
5
+
6
+ const enumStore = createStore().setValuesSchema({
7
+ status: {enum: ['available', 'adopted'], default: 'available'},
8
+ rating: {enum: ['good', 5, true], allowNull: true},
9
+ });
10
+
11
+ enumStore.setValues({status: 'adopted', rating: true});
12
+ enumStore.setValue('status', 'missing');
13
+ console.log(enumStore.getValues());
14
+ // -> {status: 'available', rating: true}
15
+ ```
16
+
17
+ <p>Each schema entry must use exactly one of <code>type</code> or <code>enum</code>. Defaults are used only when they are enum members, or are <code>null</code> when null is allowed. The schema-aware <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> APIs infer exact unions from enum members, and the Zod, Valibot, ArkType, Effect Schema, TypeBox, and Yup schematizers now preserve supported primitive enum and literal constraints in the schemas they produce.</p><h2 id="schema-type-unions">Schema Type Unions</h2><p><a href="https://tinybase.org/api/store/type-aliases/schema/cellschema/"><code>CellSchema</code></a> and <a href="https://tinybase.org/api/store/type-aliases/schema/valueschema/"><code>ValueSchema</code></a> can now accept a non-empty array in the <code>type</code> property to list one or more allowed broad types (as requested in issue <a href="https://github.com/tinyplex/tinybase/issues/223">#223</a>):</p>
18
+
19
+ ```js
20
+ const unionStore = createStore().setValuesSchema({
21
+ reference: {type: ['string', 'number'], default: 'unknown'},
22
+ response: {type: ['boolean', 'object'], allowNull: true},
23
+ });
24
+
25
+ unionStore.setValues({reference: 42, response: {accepted: true}});
26
+ unionStore.setValue('reference', false);
27
+ console.log(unionStore.getValues());
28
+ // -> {reference: 'unknown', response: {accepted: true}}
29
+ ```
30
+
31
+ <p>A type array can contain <code>string</code>, <code>number</code>, <code>boolean</code>, <code>object</code>, and <code>array</code>. Multiple type names form a union, and repeated names have no additional effect. <code>null</code> continues to be represented by <code>allowNull: true</code>, and defaults are used only when they match one of the listed types. Each schema entry still uses exactly one of <code>type</code> or <code>enum</code>: a type array allows every value of its listed types, while an enum allows only its listed values.</p><p>The schema-aware <a href="https://tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> APIs infer the corresponding TypeScript unions. The ArkType, Effect Schema, TypeBox, Valibot, and Zod schematizers also preserve supported broad type unions, while continuing to preserve literal-only unions as exact enums.</p><h2 id="schema-aware-type-fixes">Schema-Aware Type Fixes</h2><p>This release also corrects a number of declarations on the <code>/with-schemas</code> type surface. These are type-level fixes only, and require no changes to your runtime code:</p><ul><li>The six schematizer factory functions were previously exported from their <code>/with-schemas</code> entry points as types rather than as values, so they could not actually be called from those entry points. <code>createArkTypeSchematizer</code>, <code>createEffectSchematizer</code>, <code>createTypeBoxSchematizer</code>, <code>createValibotSchematizer</code>, <code>createYupSchematizer</code>, and <code>createZodSchematizer</code> are now exported correctly, both individually and from the <code>tinybase/schematizers/with-schemas</code> module.</li><li>The <code>extraCellsBefore</code> and <code>extraCellsAfter</code> props were missing from the schema-aware declarations of the DOM table components, and are now available in the React, Solid, and Svelte packages.</li><li><code>[</code>ResultCell<code>](/api/queries/type-aliases/result/resultcell/)</code> was declared as <code>string | number | boolean | null</code>, and so did not admit the object and array Cells introduced in v8.0. It is now simply <code>[</code>Cell<code>](/api/store/type-aliases/store/cell/)</code>, and the <code>[</code>Aggregate<code>](/api/queries/type-aliases/aggregators/aggregate/)</code>, <code>[</code>AggregateAdd<code>](/api/queries/type-aliases/aggregators/aggregateadd/)</code>, <code>[</code>AggregateRemove<code>](/api/queries/type-aliases/aggregators/aggregateremove/)</code>, <code>[</code>AggregateReplace<code>](/api/queries/type-aliases/aggregators/aggregatereplace/)</code>, and <code>[</code>Having<code>](/api/queries/type-aliases/definition/having/)</code> types have been aligned to match.</li><li>The <code>requestId</code> parameter of the <a href="https://tinybase.org/api/synchronizers/type-aliases/synchronization/send/"><code>Send</code></a> and <a href="https://tinybase.org/api/synchronizers/type-aliases/synchronization/receive/"><code>Receive</code></a> types is now correctly <code>[</code>IdOrNull<code>](/api/common/type-aliases/identity/idornull/)</code> rather than <code>[</code>Id<code>](/api/common/type-aliases/identity/id/)</code>, matching what synchronizer implementations are actually passed.</li></ul><hr><h1 id="v9-4">v9.4</h1><h2 id="selectall"><code>selectAll</code></h2><p><a href="https://tinybase.org/api/queries/interfaces/queries/queries/"><code>Queries</code></a> can now select every <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> present in a root or joined <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> with the <code>selectAll</code> keyword (as requested in issue <a href="https://github.com/tinyplex/tinybase/issues/40">#40</a>). Heterogeneous Rows are supported directly: each result <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a> contains only its source <a href="https://tinybase.org/api/store/type-aliases/store/row/"><code>Row</code></a>&#x27;s Cells, while the result <a href="https://tinybase.org/api/store/type-aliases/store/table/"><code>Table</code></a>&#x27;s <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> are their reactive union.</p><p>Joined selections retain their <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> by default, or can take a <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a> prefix or mapping callback. Selection clauses are applied in declaration order, and source <a href="https://tinybase.org/api/store/type-aliases/store/cell/"><code>Cell</code></a> <a href="https://tinybase.org/api/common/type-aliases/identity/ids/"><code>Ids</code></a> within a <code>selectAll</code> function call are processed lexically, so collision behavior is deterministic.</p>
32
+
33
+ ```js
34
+ import {createQueries} from 'tinybase';
5
35
 
6
36
  const selectAllStore = createStore().setTable('pets', {
7
37
  fido: {species: 'dog', color: 'brown'},
@@ -6,21 +6,31 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const REQUIRED = 'required';
14
+ const UNDEFINED = '\uFFFC';
15
+ const JSON_PREFIX = '\uFFFD';
12
16
 
13
17
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
14
18
  predicate(value)
15
19
  ? /* istanbul ignore next */
16
20
  otherwise?.()
17
21
  : then(value);
22
+ const isFiniteNumber = isFinite;
18
23
  const isNullish = (thing) => thing == null;
19
24
  const isUndefined = (thing) => thing === void 0;
25
+ const isNull = (thing) => thing === null;
20
26
  const ifNotNullish = getIfNotFunction(isNullish);
21
27
  const ifNotUndefined = getIfNotFunction(isUndefined);
28
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
29
+ const isString = (thing) => getTypeOf(thing) == STRING;
30
+ const isArray = (thing) => Array.isArray(thing);
22
31
  const size = (thing) => thing.length;
23
32
 
33
+ const arrayEvery = (array, cb) => array.every(cb);
24
34
  const arrayForEach = (array, cb) => array.forEach(cb);
25
35
 
26
36
  const object = Object;
@@ -57,6 +67,33 @@ const objForEach = (obj, cb) =>
57
67
  const objSize = (obj) => size(objIds(obj));
58
68
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
59
69
 
70
+ const getCellOrValueType = (cellOrValue) => {
71
+ if (isNull(cellOrValue)) {
72
+ return NULL;
73
+ }
74
+ if (isArray(cellOrValue)) {
75
+ return ARRAY;
76
+ }
77
+ if (isObject(cellOrValue)) {
78
+ return OBJECT;
79
+ }
80
+ const type = getTypeOf(cellOrValue);
81
+ return isTypeStringOrBoolean(type) ||
82
+ (type == NUMBER && isFiniteNumber(cellOrValue))
83
+ ? type
84
+ : void 0;
85
+ };
86
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
87
+ const isCellOrValueSchemaType = (type) =>
88
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
89
+ const isCellOrValueSchemaTypes = (types) =>
90
+ isArray(types)
91
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
92
+ : isCellOrValueSchemaType(types);
93
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
94
+ const isReservedString = (value, encoded = 0) =>
95
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
96
+
60
97
  const createCustomSchematizer = (
61
98
  unwrapSchema,
62
99
  getProperties,
@@ -66,16 +103,27 @@ const createCustomSchematizer = (
66
103
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
67
104
  unwrapSchema(schema, void 0, void 0, required);
68
105
  const type = unwrapped?.type;
106
+ const enumValues = unwrapped?.[ENUM];
107
+ const isEnum =
108
+ isUndefined(type) &&
109
+ isArray(enumValues) &&
110
+ !isUndefined(enumValues[0]) &&
111
+ arrayEvery(enumValues, (enumValue) => {
112
+ const enumType = getCellOrValueType(enumValue);
113
+ return (
114
+ !isNull(enumValue) &&
115
+ !isUndefined(enumType) &&
116
+ !isJsonType(enumType) &&
117
+ !isReservedString(enumValue)
118
+ );
119
+ });
69
120
  if (
70
- type !== STRING &&
71
- type !== NUMBER &&
72
- type !== BOOLEAN &&
73
- type !== OBJECT &&
74
- type !== ARRAY
121
+ !isEnum &&
122
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
75
123
  ) {
76
124
  return void 0;
77
125
  }
78
- const cellOrValueSchema = {[TYPE]: type};
126
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
79
127
  ifNotUndefined(defaultValue, (defaultValue2) => {
80
128
  cellOrValueSchema[DEFAULT] = defaultValue2;
81
129
  });
@@ -6,8 +6,10 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const _VALUE = 'value';
12
14
  const DOMAIN = 'domain';
13
15
  const KEY = 'key';
@@ -15,12 +17,15 @@ const OPTIONAL = 'optional';
15
17
  const REQUIRED = 'required';
16
18
  const UNIT = 'unit';
17
19
  const SEQUENCE = 'sequence';
20
+ const UNDEFINED = '\uFFFC';
21
+ const JSON_PREFIX = '\uFFFD';
18
22
 
19
23
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
20
24
  predicate(value)
21
25
  ? /* istanbul ignore next */
22
26
  otherwise?.()
23
27
  : then(value);
28
+ const isFiniteNumber = isFinite;
24
29
  const isNullish = (thing) => thing == null;
25
30
  const isUndefined = (thing) => thing === void 0;
26
31
  const isNull = (thing) => thing === null;
@@ -28,12 +33,16 @@ const isTrue = (thing) => thing === true;
28
33
  const isFalse = (thing) => thing === false;
29
34
  const ifNotNullish = getIfNotFunction(isNullish);
30
35
  const ifNotUndefined = getIfNotFunction(isUndefined);
36
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
31
37
  const isString = (thing) => getTypeOf(thing) == STRING;
32
38
  const isArray = (thing) => Array.isArray(thing);
33
39
  const size = (thing) => thing.length;
34
40
 
41
+ const arrayIndexOf = (array, value) => array.indexOf(value);
35
42
  const arrayEvery = (array, cb) => array.every(cb);
36
43
  const arrayForEach = (array, cb) => array.forEach(cb);
44
+ const arrayMap = (array, cb) => array.map(cb);
45
+ const arrayFilter = (array, cb) => array.filter(cb);
37
46
  const arrayFind = (array, cb) => array.find(cb);
38
47
 
39
48
  const object = Object;
@@ -70,6 +79,44 @@ const objForEach = (obj, cb) =>
70
79
  const objSize = (obj) => size(objIds(obj));
71
80
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
72
81
 
82
+ const getCellOrValueType = (cellOrValue) => {
83
+ if (isNull(cellOrValue)) {
84
+ return NULL;
85
+ }
86
+ if (isArray(cellOrValue)) {
87
+ return ARRAY;
88
+ }
89
+ if (isObject(cellOrValue)) {
90
+ return OBJECT;
91
+ }
92
+ const type = getTypeOf(cellOrValue);
93
+ return isTypeStringOrBoolean(type) ||
94
+ (type == NUMBER && isFiniteNumber(cellOrValue))
95
+ ? type
96
+ : void 0;
97
+ };
98
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
99
+ const isCellOrValueSchemaType = (type) =>
100
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
101
+ const isCellOrValueSchemaTypes = (types) =>
102
+ isArray(types)
103
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
104
+ : isCellOrValueSchemaType(types);
105
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
106
+ const isReservedString = (value, encoded = 0) =>
107
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
108
+
109
+ const getTypeOrTypeUnion = (types) => {
110
+ if (!arrayEvery(types, isCellOrValueSchemaType)) {
111
+ return;
112
+ }
113
+ const uniqueTypes = arrayFilter(
114
+ types,
115
+ (type, index) => arrayIndexOf(types, type) == index,
116
+ );
117
+ return uniqueTypes[1] ? uniqueTypes : uniqueTypes[0];
118
+ };
119
+
73
120
  const createCustomSchematizer = (
74
121
  unwrapSchema,
75
122
  getProperties,
@@ -79,16 +126,27 @@ const createCustomSchematizer = (
79
126
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
80
127
  unwrapSchema(schema, void 0, void 0, required);
81
128
  const type = unwrapped?.type;
129
+ const enumValues = unwrapped?.[ENUM];
130
+ const isEnum =
131
+ isUndefined(type) &&
132
+ isArray(enumValues) &&
133
+ !isUndefined(enumValues[0]) &&
134
+ arrayEvery(enumValues, (enumValue) => {
135
+ const enumType = getCellOrValueType(enumValue);
136
+ return (
137
+ !isNull(enumValue) &&
138
+ !isUndefined(enumType) &&
139
+ !isJsonType(enumType) &&
140
+ !isReservedString(enumValue)
141
+ );
142
+ });
82
143
  if (
83
- type !== STRING &&
84
- type !== NUMBER &&
85
- type !== BOOLEAN &&
86
- type !== OBJECT &&
87
- type !== ARRAY
144
+ !isEnum &&
145
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
88
146
  ) {
89
147
  return void 0;
90
148
  }
91
- const cellOrValueSchema = {[TYPE]: type};
149
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
92
150
  ifNotUndefined(defaultValue, (defaultValue2) => {
93
151
  cellOrValueSchema[DEFAULT] = defaultValue2;
94
152
  });
@@ -138,6 +196,12 @@ const createCustomSchematizer = (
138
196
  });
139
197
  };
140
198
 
199
+ const getSimpleType = (schema) =>
200
+ !isUndefined(schema?.[UNIT])
201
+ ? getCellOrValueType(schema[UNIT])
202
+ : !isUndefined(schema?.[SEQUENCE])
203
+ ? ARRAY
204
+ : schema?.[DOMAIN] || schema;
141
205
  const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
142
206
  const schemaData = schema?.json ?? schema;
143
207
  if (isArray(schemaData)) {
@@ -152,24 +216,40 @@ const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
152
216
  ) {
153
217
  return [{[TYPE]: BOOLEAN}, defaultValue, allowNull ?? false, required];
154
218
  }
155
- if (arrayEvery(schemaData, (item) => isString(item?.[UNIT] ?? item))) {
156
- return [{[TYPE]: STRING}, defaultValue, allowNull ?? false, required];
157
- }
158
- if (hasNull) {
159
- const nonNullItem = arrayFind(
160
- schemaData,
161
- (item) => !isNull(item?.[UNIT]) && !isNull(item) && item !== '=',
162
- );
163
- if (nonNullItem) {
164
- return unwrapSchema(nonNullItem, defaultValue, true, required);
165
- }
219
+ const enumItems = arrayFilter(
220
+ schemaData,
221
+ (item) => !isNull(item?.[UNIT]) && !isNull(item) && item !== '=',
222
+ );
223
+ if (
224
+ size(enumItems) > 0 &&
225
+ arrayEvery(enumItems, (item) => !isUndefined(item?.[UNIT]))
226
+ ) {
227
+ return [
228
+ {[ENUM]: arrayMap(enumItems, (item) => item[UNIT])},
229
+ defaultValue,
230
+ hasNull || allowNull || false,
231
+ required,
232
+ ];
166
233
  }
234
+ return [
235
+ {
236
+ [TYPE]: getTypeOrTypeUnion(arrayMap(enumItems, getSimpleType)),
237
+ },
238
+ defaultValue,
239
+ hasNull || allowNull || false,
240
+ required,
241
+ ];
167
242
  }
168
243
  if (!isArray(schemaData) && !isUndefined(schemaData?.[SEQUENCE])) {
169
244
  return [{[TYPE]: ARRAY}, defaultValue, allowNull ?? false, required];
170
245
  }
171
- if (!isArray(schemaData) && isString(schemaData?.[UNIT])) {
172
- return [{[TYPE]: STRING}, defaultValue, allowNull ?? false, required];
246
+ if (!isArray(schemaData) && !isUndefined(schemaData?.[UNIT])) {
247
+ return [
248
+ {[ENUM]: [schemaData[UNIT]]},
249
+ defaultValue,
250
+ allowNull ?? false,
251
+ required,
252
+ ];
173
253
  }
174
254
  return [
175
255
  {[TYPE]: schemaData?.[DOMAIN] || schemaData},