tinybase 9.4.0-beta.1 → 9.4.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/@types/persisters/index.d.ts +4 -0
  2. package/@types/persisters/persister-durable-object-sql-storage/index.d.ts +9 -2
  3. package/@types/persisters/persister-durable-object-sql-storage/with-schemas/index.d.ts +9 -2
  4. package/@types/persisters/with-schemas/index.d.ts +4 -0
  5. package/@types/queries/index.d.ts +4 -0
  6. package/@types/queries/with-schemas/index.d.ts +4 -0
  7. package/@types/synchronizers/synchronizer-ws-client/index.d.ts +7 -3
  8. package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +7 -3
  9. package/@types/synchronizers/synchronizer-ws-server/index.d.ts +9 -3
  10. package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +9 -3
  11. package/@types/synchronizers/synchronizer-ws-server-simple/index.d.ts +6 -3
  12. package/@types/synchronizers/synchronizer-ws-server-simple/with-schemas/index.d.ts +6 -3
  13. package/index.js +191 -74
  14. package/min/index.js +1 -1
  15. package/min/index.js.gz +0 -0
  16. package/min/omni/index.js +1 -1
  17. package/min/omni/index.js.gz +0 -0
  18. package/min/omni/with-schemas/index.js +1 -1
  19. package/min/omni/with-schemas/index.js.gz +0 -0
  20. package/min/persisters/index.js +1 -1
  21. package/min/persisters/index.js.gz +0 -0
  22. package/min/persisters/persister-automerge/index.js +1 -1
  23. package/min/persisters/persister-automerge/index.js.gz +0 -0
  24. package/min/persisters/persister-automerge/with-schemas/index.js +1 -1
  25. package/min/persisters/persister-automerge/with-schemas/index.js.gz +0 -0
  26. package/min/persisters/persister-browser/index.js +1 -1
  27. package/min/persisters/persister-browser/index.js.gz +0 -0
  28. package/min/persisters/persister-browser/with-schemas/index.js +1 -1
  29. package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
  30. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  31. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  32. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  33. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  34. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  35. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  36. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  37. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  38. package/min/persisters/persister-durable-object-storage/index.js +1 -1
  39. package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
  40. package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
  41. package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
  42. package/min/persisters/persister-electric-sql/index.js +1 -1
  43. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  44. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  45. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  46. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  47. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  48. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  49. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  50. package/min/persisters/persister-file/index.js +1 -1
  51. package/min/persisters/persister-file/index.js.gz +0 -0
  52. package/min/persisters/persister-file/with-schemas/index.js +1 -1
  53. package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
  54. package/min/persisters/persister-indexed-db/index.js +1 -1
  55. package/min/persisters/persister-indexed-db/index.js.gz +0 -0
  56. package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
  57. package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
  58. package/min/persisters/persister-libsql/index.js +1 -1
  59. package/min/persisters/persister-libsql/index.js.gz +0 -0
  60. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  61. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  62. package/min/persisters/persister-partykit-client/index.js +1 -1
  63. package/min/persisters/persister-partykit-client/index.js.gz +0 -0
  64. package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
  65. package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
  66. package/min/persisters/persister-pglite/index.js +1 -1
  67. package/min/persisters/persister-pglite/index.js.gz +0 -0
  68. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  69. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  70. package/min/persisters/persister-postgres/index.js +1 -1
  71. package/min/persisters/persister-postgres/index.js.gz +0 -0
  72. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  73. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  74. package/min/persisters/persister-powersync/index.js +1 -1
  75. package/min/persisters/persister-powersync/index.js.gz +0 -0
  76. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  77. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  78. package/min/persisters/persister-react-native-mmkv/index.js +1 -1
  79. package/min/persisters/persister-react-native-mmkv/index.js.gz +0 -0
  80. package/min/persisters/persister-react-native-mmkv/with-schemas/index.js +1 -1
  81. package/min/persisters/persister-react-native-mmkv/with-schemas/index.js.gz +0 -0
  82. package/min/persisters/persister-react-native-sqlite/index.js +1 -1
  83. package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
  84. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
  85. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
  86. package/min/persisters/persister-remote/index.js +1 -1
  87. package/min/persisters/persister-remote/index.js.gz +0 -0
  88. package/min/persisters/persister-remote/with-schemas/index.js +1 -1
  89. package/min/persisters/persister-remote/with-schemas/index.js.gz +0 -0
  90. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  91. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  92. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  93. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  94. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  95. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  96. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  97. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  98. package/min/persisters/persister-sqlite3/index.js +1 -1
  99. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  100. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  101. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  102. package/min/persisters/persister-yjs/index.js +1 -1
  103. package/min/persisters/persister-yjs/index.js.gz +0 -0
  104. package/min/persisters/persister-yjs/with-schemas/index.js +1 -1
  105. package/min/persisters/persister-yjs/with-schemas/index.js.gz +0 -0
  106. package/min/persisters/with-schemas/index.js +1 -1
  107. package/min/persisters/with-schemas/index.js.gz +0 -0
  108. package/min/queries/index.js +1 -1
  109. package/min/queries/index.js.gz +0 -0
  110. package/min/queries/with-schemas/index.js +1 -1
  111. package/min/queries/with-schemas/index.js.gz +0 -0
  112. package/min/synchronizers/index.js +1 -1
  113. package/min/synchronizers/index.js.gz +0 -0
  114. package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
  115. package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
  116. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
  117. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
  118. package/min/synchronizers/synchronizer-local/index.js +1 -1
  119. package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
  120. package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
  121. package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
  122. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  123. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  124. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  125. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  126. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  127. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  128. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  129. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  130. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  131. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  132. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  133. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  134. package/min/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
  135. package/min/synchronizers/synchronizer-ws-server-simple/index.js.gz +0 -0
  136. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
  137. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js.gz +0 -0
  138. package/min/synchronizers/with-schemas/index.js +1 -1
  139. package/min/synchronizers/with-schemas/index.js.gz +0 -0
  140. package/min/ui-react-inspector/index.js +1 -1
  141. package/min/ui-react-inspector/index.js.gz +0 -0
  142. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  143. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  144. package/min/ui-solid-inspector/index.js +1 -1
  145. package/min/ui-solid-inspector/index.js.gz +0 -0
  146. package/min/ui-solid-inspector/with-schemas/index.js +1 -1
  147. package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
  148. package/min/ui-svelte-inspector/index.js +1 -1
  149. package/min/ui-svelte-inspector/index.js.gz +0 -0
  150. package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
  151. package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
  152. package/min/with-schemas/index.js +1 -1
  153. package/min/with-schemas/index.js.gz +0 -0
  154. package/omni/index.js +606 -179
  155. package/omni/with-schemas/index.js +606 -179
  156. package/package.json +8 -4
  157. package/persisters/index.js +49 -10
  158. package/persisters/persister-automerge/index.js +29 -5
  159. package/persisters/persister-automerge/with-schemas/index.js +29 -5
  160. package/persisters/persister-browser/index.js +29 -5
  161. package/persisters/persister-browser/with-schemas/index.js +29 -5
  162. package/persisters/persister-cr-sqlite-wasm/index.js +29 -5
  163. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +29 -5
  164. package/persisters/persister-durable-object-sql-storage/index.js +44 -8
  165. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +44 -8
  166. package/persisters/persister-durable-object-storage/index.js +31 -5
  167. package/persisters/persister-durable-object-storage/with-schemas/index.js +31 -5
  168. package/persisters/persister-electric-sql/index.js +29 -5
  169. package/persisters/persister-electric-sql/with-schemas/index.js +29 -5
  170. package/persisters/persister-expo-sqlite/index.js +29 -5
  171. package/persisters/persister-expo-sqlite/with-schemas/index.js +29 -5
  172. package/persisters/persister-file/index.js +31 -5
  173. package/persisters/persister-file/with-schemas/index.js +31 -5
  174. package/persisters/persister-indexed-db/index.js +29 -5
  175. package/persisters/persister-indexed-db/with-schemas/index.js +29 -5
  176. package/persisters/persister-libsql/index.js +29 -5
  177. package/persisters/persister-libsql/with-schemas/index.js +29 -5
  178. package/persisters/persister-partykit-client/index.js +31 -5
  179. package/persisters/persister-partykit-client/with-schemas/index.js +31 -5
  180. package/persisters/persister-pglite/index.js +49 -10
  181. package/persisters/persister-pglite/with-schemas/index.js +49 -10
  182. package/persisters/persister-postgres/index.js +49 -10
  183. package/persisters/persister-postgres/with-schemas/index.js +49 -10
  184. package/persisters/persister-powersync/index.js +29 -5
  185. package/persisters/persister-powersync/with-schemas/index.js +29 -5
  186. package/persisters/persister-react-native-mmkv/index.js +31 -5
  187. package/persisters/persister-react-native-mmkv/with-schemas/index.js +31 -5
  188. package/persisters/persister-react-native-sqlite/index.js +29 -5
  189. package/persisters/persister-react-native-sqlite/with-schemas/index.js +29 -5
  190. package/persisters/persister-remote/index.js +31 -5
  191. package/persisters/persister-remote/with-schemas/index.js +31 -5
  192. package/persisters/persister-sqlite-bun/index.js +29 -5
  193. package/persisters/persister-sqlite-bun/with-schemas/index.js +29 -5
  194. package/persisters/persister-sqlite-wasm/index.js +29 -5
  195. package/persisters/persister-sqlite-wasm/with-schemas/index.js +29 -5
  196. package/persisters/persister-sqlite3/index.js +29 -5
  197. package/persisters/persister-sqlite3/with-schemas/index.js +29 -5
  198. package/persisters/persister-yjs/index.js +29 -5
  199. package/persisters/persister-yjs/with-schemas/index.js +29 -5
  200. package/persisters/with-schemas/index.js +49 -10
  201. package/queries/index.js +205 -74
  202. package/queries/with-schemas/index.js +205 -74
  203. package/readme.md +3 -3
  204. package/releases.md +22 -5
  205. package/synchronizers/index.js +31 -5
  206. package/synchronizers/synchronizer-broadcast-channel/index.js +39 -13
  207. package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +39 -13
  208. package/synchronizers/synchronizer-local/index.js +31 -5
  209. package/synchronizers/synchronizer-local/with-schemas/index.js +31 -5
  210. package/synchronizers/synchronizer-ws-client/index.js +220 -61
  211. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +220 -61
  212. package/synchronizers/synchronizer-ws-server/index.js +253 -73
  213. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +253 -73
  214. package/synchronizers/synchronizer-ws-server-durable-object/index.js +88 -40
  215. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +88 -40
  216. package/synchronizers/synchronizer-ws-server-simple/index.js +184 -60
  217. package/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +184 -60
  218. package/synchronizers/with-schemas/index.js +31 -5
  219. package/ui-react-inspector/index.js +29 -5
  220. package/ui-react-inspector/with-schemas/index.js +29 -5
  221. package/ui-solid-inspector/index.js +29 -5
  222. package/ui-solid-inspector/with-schemas/index.js +29 -5
  223. package/ui-svelte-inspector/index.js +29 -5
  224. package/ui-svelte-inspector/with-schemas/index.js +29 -5
  225. package/with-schemas/index.js +191 -74
@@ -1,4 +1,5 @@
1
1
  const getTypeOf = (thing) => typeof thing;
2
+ const TINYBASE = 'tinybase';
2
3
  const EMPTY_STRING = '';
3
4
  const STRING = getTypeOf(EMPTY_STRING);
4
5
  const BOOLEAN = getTypeOf(true);
@@ -251,6 +252,20 @@ const getCellOrValueType = (cellOrValue) => {
251
252
  const encodeIfJson = (value) =>
252
253
  isObject(value) || isArray(value) ? JSON_PREFIX + jsonString(value) : value;
253
254
 
255
+ const ERROR_QUERY_SELECT_ALL_CYCLE = 16;
256
+ const errorNew = (code, details) =>
257
+ new Error(
258
+ TINYBASE +
259
+ ':' +
260
+ code +
261
+ (isUndefined(details)
262
+ ? EMPTY_STRING
263
+ : /* istanbul ignore next */
264
+ ':' + details),
265
+ );
266
+ const errorThrow = (code, details) => {
267
+ throw errorNew(code, details);
268
+ };
254
269
  const tryCatchSync = (action, onError) => {
255
270
  try {
256
271
  return action();
@@ -470,7 +485,50 @@ const createQueries = getCreateFunction((store) => {
470
485
  const preStoreListenerIds = mapNew();
471
486
  const sourceStoreListenerIds = mapNew();
472
487
  const selectAllListenerIds = mapNew();
488
+ const selectAllRetryListenerIds = mapNew();
489
+ const selectAllQuerySources = mapNew();
473
490
  const referencedQueryIds = mapNew();
491
+ const assertNoMappedSelectAllCycle = (queryId, nextQuerySources) => {
492
+ const getQuerySources = (sourceQueryId) =>
493
+ sourceQueryId === queryId
494
+ ? nextQuerySources
495
+ : mapGet(selectAllQuerySources, sourceQueryId);
496
+ const reachesQuery = (
497
+ sourceQueryId,
498
+ targetQueryId,
499
+ visitedQueryIds = setNew(),
500
+ ) => {
501
+ if (sourceQueryId === targetQueryId) {
502
+ return true;
503
+ }
504
+ if (collHas(visitedQueryIds, sourceQueryId)) {
505
+ return false;
506
+ }
507
+ setAdd(visitedQueryIds, sourceQueryId);
508
+ return !collEvery(
509
+ getQuerySources(sourceQueryId),
510
+ (_changesCellId, nextQueryId) =>
511
+ !reachesQuery(nextQueryId, targetQueryId, visitedQueryIds),
512
+ );
513
+ };
514
+ const hasMappedCycle = (sourceQueryId, querySources) =>
515
+ !collEvery(
516
+ querySources,
517
+ (changesCellId, nextQueryId) =>
518
+ !changesCellId || !reachesQuery(nextQueryId, sourceQueryId),
519
+ );
520
+ if (
521
+ hasMappedCycle(queryId, nextQuerySources) ||
522
+ !collEvery(
523
+ selectAllQuerySources,
524
+ (querySources, sourceQueryId) =>
525
+ sourceQueryId === queryId ||
526
+ !hasMappedCycle(sourceQueryId, querySources),
527
+ )
528
+ ) {
529
+ errorThrow(ERROR_QUERY_SELECT_ALL_CYCLE);
530
+ }
531
+ };
474
532
  const {
475
533
  _: [, addListener, callListeners],
476
534
  delListener: delListenerImpl,
@@ -544,6 +602,30 @@ const createQueries = getCreateFunction((store) => {
544
602
  resetStoreListeners(mapGet(sourceStoreListenerIds, queryId));
545
603
  mapSet(sourceStoreListenerIds, queryId);
546
604
  };
605
+ const clearSelectAllRetryListeners = (queryId) =>
606
+ ifNotUndefined(
607
+ mapGet(selectAllRetryListenerIds, queryId),
608
+ (listenerIds) => {
609
+ mapForEach(listenerIds, (sourceStore, listenerIdsByTableId) =>
610
+ mapForEach(listenerIdsByTableId, (_sourceTableId, listenerId) =>
611
+ sourceStore.delListener(listenerId),
612
+ ),
613
+ );
614
+ mapSet(selectAllRetryListenerIds, queryId);
615
+ },
616
+ );
617
+ const addSelectAllRetryListener = (queryId, sourceStore, sourceTableId) => {
618
+ const listenerIdsByTableId = mapEnsure(
619
+ mapEnsure(selectAllRetryListenerIds, queryId, mapNew),
620
+ sourceStore,
621
+ mapNew,
622
+ );
623
+ mapEnsure(listenerIdsByTableId, sourceTableId, () =>
624
+ sourceStore.addTableListener(sourceTableId, () =>
625
+ setQueryDefinitionImpl(queryId),
626
+ ),
627
+ );
628
+ };
547
629
  const syncSelectAllListeners = (queryId, nextSources = mapNew()) => {
548
630
  const listenerIds = mapEnsure(selectAllListenerIds, queryId, mapNew);
549
631
  mapForEach(listenerIds, (sourceStore, listenerIdsByTableId) => {
@@ -562,7 +644,13 @@ const createQueries = getCreateFunction((store) => {
562
644
  collForEach(tableIds, (sourceTableId) =>
563
645
  mapEnsure(listenerIdsByTableId, sourceTableId, () =>
564
646
  sourceStore.addTableCellIdsListener(sourceTableId, () =>
565
- setQueryDefinitionImpl(queryId),
647
+ tryCatchSync(
648
+ () => setQueryDefinitionImpl(queryId),
649
+ (error) => {
650
+ addSelectAllRetryListener(queryId, sourceStore, sourceTableId);
651
+ throw error;
652
+ },
653
+ ),
566
654
  ),
567
655
  ),
568
656
  );
@@ -721,6 +809,10 @@ const createQueries = getCreateFunction((store) => {
721
809
  isFunction(prefixOrMapper)
722
810
  ? prefixOrMapper
723
811
  : (cellId) => (prefixOrMapper ?? EMPTY_STRING) + cellId,
812
+ isFunction(prefixOrMapper) ||
813
+ (!isUndefined(prefixOrMapper) && prefixOrMapper !== EMPTY_STRING)
814
+ ? 1
815
+ : 0,
724
816
  ]);
725
817
  };
726
818
  const join = (arg1, arg2, arg3, arg4) => {
@@ -794,28 +886,49 @@ const createQueries = getCreateFunction((store) => {
794
886
  getSelectedOrGroupedCell(arg1) === arg2,
795
887
  );
796
888
  build({select, selectAll, join, where, group, having, param});
797
- resultStore2.delTable(queryId);
798
- if (isEmpty(selectionEntries)) {
799
- commit?.();
800
- return queries;
801
- }
802
889
  const joins = mapNew(joinEntries);
803
890
  mapForEach(joins, (joinAlias, [, fromJoinAlias]) =>
804
891
  ifNotUndefined(mapGet(joins, fromJoinAlias), ({3: toJoinAliases2}) =>
805
892
  isUndefined(joinAlias) ? 0 : arrayPush(toJoinAliases2, joinAlias),
806
893
  ),
807
894
  );
808
- const groups = mapNew(groupEntries);
809
- const hasGroupsOrHavings = !collIsEmpty(groups) || !isEmpty(havings);
810
- const selectEntries = [];
811
- const selectAllSources = stagedDefinition[3];
895
+ const isRootSelectAll = (joinedTableId) => isUndefined(joinedTableId);
812
896
  const getSelectAllJoin = (joinedTableId) =>
813
897
  mapGet(
814
898
  joins,
815
- isUndefined(joinedTableId) || joinedTableId === tableId
816
- ? void 0
817
- : joinedTableId,
899
+ isRootSelectAll(joinedTableId) ? void 0 : joinedTableId,
818
900
  );
901
+ const nextSelectAllQuerySources = stagedDefinition[5];
902
+ arrayForEach(
903
+ selectionEntries,
904
+ ([selectAll2, selectedOrJoinedTableId, , changesCellId = 0]) =>
905
+ selectAll2
906
+ ? ifNotUndefined(
907
+ getSelectAllJoin(selectedOrJoinedTableId),
908
+ ([sourceQueryId, , , , , sourceStore]) =>
909
+ sourceStore === store
910
+ ? 0
911
+ : mapSet(
912
+ nextSelectAllQuerySources,
913
+ sourceQueryId,
914
+ mapGet(nextSelectAllQuerySources, sourceQueryId) ||
915
+ changesCellId
916
+ ? 1
917
+ : 0,
918
+ ),
919
+ )
920
+ : 0,
921
+ );
922
+ assertNoMappedSelectAllCycle(queryId, nextSelectAllQuerySources);
923
+ resultStore2.delTable(queryId);
924
+ if (isEmpty(selectionEntries)) {
925
+ commit?.();
926
+ return queries;
927
+ }
928
+ const groups = mapNew(groupEntries);
929
+ const hasGroupsOrHavings = !collIsEmpty(groups) || !isEmpty(havings);
930
+ const selectEntries = [];
931
+ const selectAllSources = stagedDefinition[3];
819
932
  arrayForEach(
820
933
  selectionEntries,
821
934
  ([selectAll2, selectedOrJoinedTableId, clauseOrMapper]) => {
@@ -833,11 +946,7 @@ const createQueries = getCreateFunction((store) => {
833
946
  (cellId) =>
834
947
  arrayPush(selectEntries, [
835
948
  clauseOrMapper(cellId),
836
- (getTableCell) =>
837
- isUndefined(selectedOrJoinedTableId) ||
838
- selectedOrJoinedTableId === tableId
839
- ? getTableCell(cellId)
840
- : getTableCell(selectedOrJoinedTableId, cellId),
949
+ getUndefined,
841
950
  ]),
842
951
  );
843
952
  },
@@ -1034,67 +1143,74 @@ const createQueries = getCreateFunction((store) => {
1034
1143
  joinedCellId,
1035
1144
  );
1036
1145
  };
1146
+ const writeSelectAllRow = () => {
1147
+ const resultRow = objNew();
1148
+ arrayForEach(
1149
+ selectionEntries,
1150
+ ([selectAll2, selectedOrJoinedTableId, clauseOrMapper]) => {
1151
+ if (selectAll2) {
1152
+ ifNotUndefined(
1153
+ getSelectAllJoin(selectedOrJoinedTableId),
1154
+ ([realTableId, , , , remoteIdPairs, sourceStore]) => {
1155
+ const sourceRowId = isRootSelectAll(
1156
+ selectedOrJoinedTableId,
1157
+ )
1158
+ ? rootRowId
1159
+ : mapGet(remoteIdPairs, rootRowId)?.[0];
1160
+ ifNotUndefined(sourceRowId, (sourceRowId2) =>
1161
+ arrayForEach(
1162
+ arraySort(
1163
+ sourceStore.getCellIds(realTableId, sourceRowId2),
1164
+ ),
1165
+ (cellId) =>
1166
+ objSet(
1167
+ resultRow,
1168
+ clauseOrMapper(cellId),
1169
+ sourceStore.getCell(
1170
+ realTableId,
1171
+ sourceRowId2,
1172
+ cellId,
1173
+ ),
1174
+ ),
1175
+ ),
1176
+ );
1177
+ },
1178
+ );
1179
+ } else {
1180
+ const selectedCell = clauseOrMapper(getJoinCell, rootRowId);
1181
+ const selectedCellId = selectedOrJoinedTableId;
1182
+ if (isUndefined(selectedCell)) {
1183
+ objDel(resultRow, selectedCellId);
1184
+ } else {
1185
+ objSet(resultRow, selectedCellId, selectedCell);
1186
+ }
1187
+ }
1188
+ },
1189
+ );
1190
+ if (objIsEmpty(resultRow)) {
1191
+ selectJoinWhereStore.delRow(queryId, rootRowId);
1192
+ } else {
1193
+ selectJoinWhereStore.setRow(queryId, rootRowId, resultRow);
1194
+ }
1195
+ };
1037
1196
  selectJoinWhereStore.transaction(() => {
1038
1197
  if (!arrayEvery(wheres, (where2) => where2(getJoinCell))) {
1039
1198
  selectJoinWhereStore.delRow(queryId, rootRowId);
1040
1199
  } else if (hasGroupsOrHavings) {
1041
- mapForEach(selects, (asCellId, tableCellGetter) =>
1042
- selectJoinWhereStore._[5](
1043
- queryId,
1044
- rootRowId,
1045
- asCellId,
1046
- tableCellGetter(getJoinCell, rootRowId),
1047
- ),
1048
- );
1049
- } else if (hasSelectAll) {
1050
- const resultRow = objNew();
1051
- arrayForEach(
1052
- selectionEntries,
1053
- ([selectAll2, selectedOrJoinedTableId, clauseOrMapper]) => {
1054
- if (selectAll2) {
1055
- ifNotUndefined(
1056
- getSelectAllJoin(selectedOrJoinedTableId),
1057
- ([realTableId, , , , remoteIdPairs, sourceStore]) => {
1058
- const sourceRowId =
1059
- isUndefined(selectedOrJoinedTableId) ||
1060
- selectedOrJoinedTableId === tableId
1061
- ? rootRowId
1062
- : mapGet(remoteIdPairs, rootRowId)?.[0];
1063
- ifNotUndefined(sourceRowId, (sourceRowId2) =>
1064
- arrayForEach(
1065
- arraySort(
1066
- sourceStore.getCellIds(realTableId, sourceRowId2),
1067
- ),
1068
- (cellId) =>
1069
- objSet(
1070
- resultRow,
1071
- clauseOrMapper(cellId),
1072
- sourceStore.getCell(
1073
- realTableId,
1074
- sourceRowId2,
1075
- cellId,
1076
- ),
1077
- ),
1078
- ),
1079
- );
1080
- },
1081
- );
1082
- } else {
1083
- const selectedCell = clauseOrMapper(getJoinCell, rootRowId);
1084
- const selectedCellId = selectedOrJoinedTableId;
1085
- if (isUndefined(selectedCell)) {
1086
- objDel(resultRow, selectedCellId);
1087
- } else {
1088
- objSet(resultRow, selectedCellId, selectedCell);
1089
- }
1090
- }
1091
- },
1092
- );
1093
- if (objIsEmpty(resultRow)) {
1094
- selectJoinWhereStore.delRow(queryId, rootRowId);
1200
+ if (hasSelectAll) {
1201
+ writeSelectAllRow();
1095
1202
  } else {
1096
- selectJoinWhereStore.setRow(queryId, rootRowId, resultRow);
1203
+ mapForEach(selects, (asCellId, tableCellGetter) =>
1204
+ selectJoinWhereStore._[5](
1205
+ queryId,
1206
+ rootRowId,
1207
+ asCellId,
1208
+ tableCellGetter(getJoinCell, rootRowId),
1209
+ ),
1210
+ );
1097
1211
  }
1212
+ } else if (hasSelectAll) {
1213
+ writeSelectAllRow();
1098
1214
  } else {
1099
1215
  mapForEach(selects, (asCellId, tableCellGetter) =>
1100
1216
  selectJoinWhereStore._[5](
@@ -1224,7 +1340,14 @@ const createQueries = getCreateFunction((store) => {
1224
1340
  }),
1225
1341
  );
1226
1342
  const setQueryDefinitionImpl = (queryId, definition) => {
1227
- const stagedDefinition = [mapNew(), mapNew(), void 0, mapNew(), setNew()];
1343
+ const stagedDefinition = [
1344
+ mapNew(),
1345
+ mapNew(),
1346
+ void 0,
1347
+ mapNew(),
1348
+ setNew(),
1349
+ mapNew(),
1350
+ ];
1228
1351
  let committed = false;
1229
1352
  tryCatchSync(
1230
1353
  () =>
@@ -1246,11 +1369,17 @@ const createQueries = getCreateFunction((store) => {
1246
1369
  );
1247
1370
  mapSet(preStores, queryId, stagedDefinition[2]);
1248
1371
  syncSelectAllListeners(queryId, stagedDefinition[3]);
1372
+ clearSelectAllRetryListeners(queryId);
1249
1373
  mapSet(
1250
1374
  referencedQueryIds,
1251
1375
  queryId,
1252
1376
  collIsEmpty(stagedDefinition[4]) ? void 0 : stagedDefinition[4],
1253
1377
  );
1378
+ mapSet(
1379
+ selectAllQuerySources,
1380
+ queryId,
1381
+ collIsEmpty(stagedDefinition[5]) ? void 0 : stagedDefinition[5],
1382
+ );
1254
1383
  committed = true;
1255
1384
  }),
1256
1385
  (error) => {
@@ -1301,7 +1430,9 @@ const createQueries = getCreateFunction((store) => {
1301
1430
  resetPreStores(queryId);
1302
1431
  resetSourceStores(queryId);
1303
1432
  syncSelectAllListeners(queryId);
1433
+ clearSelectAllRetryListeners(queryId);
1304
1434
  mapSet(referencedQueryIds, queryId);
1435
+ mapSet(selectAllQuerySources, queryId);
1305
1436
  delDefinition(queryId);
1306
1437
  cleanStores();
1307
1438
  return queries;
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- <link rel="preload" as="image" href="https://beta.tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/solid.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/svelte.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/indexeddb.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/browser.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/cloudflare.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/postgresql.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/pglite.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/sqlite.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/bun.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/expo.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/electric.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/turso.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/powersync.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/partykit.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/yjs.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/crsqlite.png"><link rel="preload" as="image" href="https://beta.tinybase.org/automerge.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/zod.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/typebox.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/valibot.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/arktype.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/yup.svg?asImg"><link rel="preload" as="image" href="https://beta.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://beta.tinybase.org/ui-react-dom.webp"><link rel="preload" as="image" href="https://beta.tinybase.org/shots/styled-chart-react-demo.png"><link rel="preload" as="image" href="https://beta.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://beta.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://beta.tinybase.org/guides/releases/#v9-3"><em>NEW!</em> v9.3 release</a></p><p><span id="one-with">&quot;The one with fewer sockets!&quot;</span></p><p><a class="start" href="https://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.tinybase.org/api/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://beta.tinybase.org/react.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/solid.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/svelte.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/indexeddb.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/browser.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/cloudflare.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/postgresql.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/pglite.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/sqlite.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/bun.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/expo.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/electric.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/turso.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/powersync.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/partykit.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/yjs.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/crsqlite.png"><link rel="preload" as="image" href="https://beta.tinybase.org/automerge.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/zod.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/typebox.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/valibot.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/arktype.svg?asImg"><link rel="preload" as="image" href="https://beta.tinybase.org/yup.svg?asImg"><link rel="preload" as="image" href="https://beta.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://beta.tinybase.org/ui-react-dom.webp"><link rel="preload" as="image" href="https://beta.tinybase.org/shots/styled-chart-react-demo.png"><link rel="preload" as="image" href="https://beta.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://beta.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://beta.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://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.tinybase.org/api/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://beta.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://beta.tinybase.org/api/persister-browser">browser storage</a>, <a href="https://beta.tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://beta.tinybase.org/guides/persistence/database-persistence/">SQLite or PostgreSQL databases</a>, and <a href="https://beta.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 - 15.6kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://beta.tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends.</h2><h3 id="ui-frameworks"><a href="https://beta.tinybase.org/guides/">UI Frameworks</a></h3><div><a href="https://beta.tinybase.org/guides/building-uis-with-react/getting-started-with-ui-react"><img src="https://beta.tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://beta.tinybase.org/guides/building-uis-with-solid/getting-started-with-ui-solid"><img src="https://beta.tinybase.org/solid.svg?asImg" width="48"> Solid</a></div><div><a href="https://beta.tinybase.org/guides/building-uis-with-svelte/getting-started-with-ui-svelte"><img src="https://beta.tinybase.org/svelte.svg?asImg" width="48"> Svelte</a></div><h3 id="storage-sync"><a href="https://beta.tinybase.org/guides/persistence/">Storage &amp; Sync</a></h3><div><a href="https://beta.tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img src="https://beta.tinybase.org/indexeddb.svg?asImg" width="48"> IndexedDB</a></div><div><a href="https://beta.tinybase.org/api/persister-browser"><img src="https://beta.tinybase.org/browser.svg?asImg" width="48"> OPFS</a></div><div><a href="https://beta.tinybase.org/guides/integrations/cloudflare-durable-objects"><img src="https://beta.tinybase.org/cloudflare.svg?asImg" width="48"> Cloudflare</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/postgresql.svg?asImg" width="48"> PostgreSQL</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/pglite.svg?asImg" width="48"> PGlite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/sqlite.svg?asImg" width="48"> SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/bun.svg?asImg" width="48"> Bun SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/expo.svg?asImg" width="48"> Expo SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/electric.svg?asImg" width="48"> ElectricSQL</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/turso.svg?asImg" width="48"> Turso</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/powersync.svg?asImg" width="48"> PowerSync</a></div><div><a href="https://beta.tinybase.org/api/persister-partykit-client"><img src="https://beta.tinybase.org/partykit.svg?asImg" width="48"> PartyKit</a></div><div><a href="https://beta.tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img src="https://beta.tinybase.org/yjs.svg?asImg" width="48"> YJS</a></div><div><a href="https://beta.tinybase.org/api/persister-cr-sqlite-wasm"><img src="https://beta.tinybase.org/crsqlite.png" width="48"> CR-SQLite</a></div><div><a href="https://beta.tinybase.org/api/persister-automerge"><img src="https://beta.tinybase.org/automerge.svg?asImg" width="48"> Automerge</a></div><h3 id="schema-systems"><a href="https://beta.tinybase.org/guides/schemas/using-schematizers/">Schema Systems</a></h3><div><a href="https://beta.tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer"><img src="https://beta.tinybase.org/zod.svg?asImg" width="48"> Zod</a></div><div><a href="https://beta.tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer"><img src="https://beta.tinybase.org/typebox.svg?asImg" width="48"> TypeBox</a></div><div><a href="https://beta.tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer"><img src="https://beta.tinybase.org/valibot.svg?asImg" width="48"> Valibot</a></div><div><a href="https://beta.tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer"><img src="https://beta.tinybase.org/arktype.svg?asImg" width="48"> ArkType</a></div><div><a href="https://beta.tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer"><img src="https://beta.tinybase.org/yup.svg?asImg" width="48"> Yup</a></div><div><a href="https://beta.tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer"><img src="https://beta.tinybase.org/effect.svg?asImg" width="48"> Effect</a></div><p>(Baffled by all these logos? Check out our <a href="https://beta.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-beta.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://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> requires just a simple call to the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://beta.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://beta.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://beta.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://beta.tinybase.org/api/persister-browser">browser storage</a>, <a href="https://beta.tinybase.org/api/persister-indexed-db">IndexedDB</a>, <a href="https://beta.tinybase.org/guides/persistence/database-persistence/">SQLite or PostgreSQL databases</a>, and <a href="https://beta.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.0kB</a> and with no dependencies - yet <a href="#well-tested-and-documented">100% tested</a>, <a href="https://beta.tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</p></section><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">TinyBase works great on its own, but also plays well with friends.</h2><h3 id="ui-frameworks"><a href="https://beta.tinybase.org/guides/">UI Frameworks</a></h3><div><a href="https://beta.tinybase.org/guides/building-uis-with-react/getting-started-with-ui-react"><img src="https://beta.tinybase.org/react.svg?asImg" width="48"> React</a></div><div><a href="https://beta.tinybase.org/guides/building-uis-with-solid/getting-started-with-ui-solid"><img src="https://beta.tinybase.org/solid.svg?asImg" width="48"> Solid</a></div><div><a href="https://beta.tinybase.org/guides/building-uis-with-svelte/getting-started-with-ui-svelte"><img src="https://beta.tinybase.org/svelte.svg?asImg" width="48"> Svelte</a></div><h3 id="storage-sync"><a href="https://beta.tinybase.org/guides/persistence/">Storage &amp; Sync</a></h3><div><a href="https://beta.tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img src="https://beta.tinybase.org/indexeddb.svg?asImg" width="48"> IndexedDB</a></div><div><a href="https://beta.tinybase.org/api/persister-browser"><img src="https://beta.tinybase.org/browser.svg?asImg" width="48"> OPFS</a></div><div><a href="https://beta.tinybase.org/guides/integrations/cloudflare-durable-objects"><img src="https://beta.tinybase.org/cloudflare.svg?asImg" width="48"> Cloudflare</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/postgresql.svg?asImg" width="48"> PostgreSQL</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/pglite.svg?asImg" width="48"> PGlite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/sqlite.svg?asImg" width="48"> SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/bun.svg?asImg" width="48"> Bun SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/expo.svg?asImg" width="48"> Expo SQLite</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/electric.svg?asImg" width="48"> ElectricSQL</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/turso.svg?asImg" width="48"> Turso</a></div><div><a href="https://beta.tinybase.org/guides/schemas-and-persistence/database-persistence"><img src="https://beta.tinybase.org/powersync.svg?asImg" width="48"> PowerSync</a></div><div><a href="https://beta.tinybase.org/api/persister-partykit-client"><img src="https://beta.tinybase.org/partykit.svg?asImg" width="48"> PartyKit</a></div><div><a href="https://beta.tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img src="https://beta.tinybase.org/yjs.svg?asImg" width="48"> YJS</a></div><div><a href="https://beta.tinybase.org/api/persister-cr-sqlite-wasm"><img src="https://beta.tinybase.org/crsqlite.png" width="48"> CR-SQLite</a></div><div><a href="https://beta.tinybase.org/api/persister-automerge"><img src="https://beta.tinybase.org/automerge.svg?asImg" width="48"> Automerge</a></div><h3 id="schema-systems"><a href="https://beta.tinybase.org/guides/schemas/using-schematizers/">Schema Systems</a></h3><div><a href="https://beta.tinybase.org/api/schematizer-zod/functions/creation/createzodschematizer"><img src="https://beta.tinybase.org/zod.svg?asImg" width="48"> Zod</a></div><div><a href="https://beta.tinybase.org/api/schematizer-typebox/functions/creation/createtypeboxschematizer"><img src="https://beta.tinybase.org/typebox.svg?asImg" width="48"> TypeBox</a></div><div><a href="https://beta.tinybase.org/api/schematizer-valibot/functions/creation/createvalibotschematizer"><img src="https://beta.tinybase.org/valibot.svg?asImg" width="48"> Valibot</a></div><div><a href="https://beta.tinybase.org/api/schematizer-arktype/functions/creation/createarktypeschematizer"><img src="https://beta.tinybase.org/arktype.svg?asImg" width="48"> ArkType</a></div><div><a href="https://beta.tinybase.org/api/schematizer-yup/functions/creation/createyupschematizer"><img src="https://beta.tinybase.org/yup.svg?asImg" width="48"> Yup</a></div><div><a href="https://beta.tinybase.org/api/schematizer-effect/functions/creation/createeffectschematizer"><img src="https://beta.tinybase.org/effect.svg?asImg" width="48"> Effect</a></div><p>(Baffled by all these logos? Check out our <a href="https://beta.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-beta.1" 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://beta.tinybase.org/api/the-essentials/creating-stores/store/"><code>Store</code></a> requires just a simple call to the <a href="https://beta.tinybase.org/api/the-essentials/creating-stores/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://beta.tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://beta.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://beta.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://beta.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>15.6kB</em>.</p><p>The optional <a href="https://beta.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://beta.tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://beta.tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>7.2kB</td><td>77.7kB</td></tr><tr><th class="right">tinybase (complete)</th><td>15.6kB</td><td>175.2kB</td></tr><tr><th class="right"><a href="https://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Tested lines</th><td>4,984</td><td>4,984</td><td>100.0%</td></tr><tr><th class="right">Tested statements</th><td>5,403</td><td>5,403</td><td>100.0%</td></tr><tr><th class="right">Tested functions</th><td>2,385</td><td>2,385</td><td>100.0%</td></tr><tr><th class="right">Tested branches</th><td>1,684</td><td>1,684</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">8,942</td></tr><tr><th class="right">Assertions</th><td colspan="3">37,451</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://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.tinybase.org/api/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://beta.tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://beta.tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://beta.tinybase.org/youtube.webp"></a></section>
286
+ <section><h2 id="did-we-say-tiny">Did we say tiny?</h2><p>If you use the basic <a href="https://beta.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.0kB</em>.</p><p>The optional <a href="https://beta.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://beta.tinybase.org/guides/how-tinybase-is-built/architecture/">Architecture</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th> </th><th>Minified .js.gz</th><th>Source .js</th></tr><tr><th class="right"><a href="https://beta.tinybase.org/api/store/">tinybase/store</a> (minimal)</th><td>7.2kB</td><td>77.7kB</td></tr><tr><th class="right">tinybase (complete)</th><td>16.0kB</td><td>182.1kB</td></tr><tr><th class="right"><a href="https://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.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://beta.tinybase.org/guides/how-tinybase-is-built/testing/">Testing</a> guide.</p></section><div class="table"><table class="fixed"><tbody><tr><th width="30%"> </th><th>Total</th><th>Tested</th><th>Coverage</th></tr><tr><th class="right">Tested lines</th><td>5,060</td><td>5,060</td><td>100.0%</td></tr><tr><th class="right">Tested statements</th><td>5,479</td><td>5,479</td><td>100.0%</td></tr><tr><th class="right">Tested functions</th><td>2,405</td><td>2,405</td><td>100.0%</td></tr><tr><th class="right">Tested branches</th><td>1,736</td><td>1,736</td><td>100.0%</td></tr><tr><th class="right">Tests</th><td colspan="3">8,959</td></tr><tr><th class="right">Assertions</th><td colspan="3">37,548</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://beta.tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://beta.tinybase.org/demos/">Try the demos</a></p><p><a href="https://beta.tinybase.org/api/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://beta.tinybase.org/guides/how-tinybase-is-built/credits/#giants">projects</a> and <a href="https://beta.tinybase.org/guides/how-tinybase-is-built/credits/#and-friends">friends</a>, and I hope you enjoy using it as much as I do building it!</p></section><section id="story"><h2 id="the-story">The story</h2><a href="https://youtu.be/hXL7OkW-Prk?t=1232" target="_blank"><img src="https://beta.tinybase.org/youtube.webp"></a></section>