@livestore/livestore 0.4.0-dev.21 → 0.4.0-dev.23

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 (216) hide show
  1. package/README.md +0 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/QueryCache.js +1 -1
  4. package/dist/QueryCache.js.map +1 -1
  5. package/dist/SqliteDbWrapper.d.ts +5 -5
  6. package/dist/SqliteDbWrapper.d.ts.map +1 -1
  7. package/dist/SqliteDbWrapper.js +8 -8
  8. package/dist/SqliteDbWrapper.js.map +1 -1
  9. package/dist/SqliteDbWrapper.test.js +2 -2
  10. package/dist/SqliteDbWrapper.test.js.map +1 -1
  11. package/dist/effect/LiveStore.d.ts +130 -2
  12. package/dist/effect/LiveStore.d.ts.map +1 -1
  13. package/dist/effect/LiveStore.js +185 -6
  14. package/dist/effect/LiveStore.js.map +1 -1
  15. package/dist/effect/LiveStore.test.d.ts +2 -0
  16. package/dist/effect/LiveStore.test.d.ts.map +1 -0
  17. package/dist/effect/LiveStore.test.js +42 -0
  18. package/dist/effect/LiveStore.test.js.map +1 -0
  19. package/dist/effect/mod.d.ts +1 -1
  20. package/dist/effect/mod.d.ts.map +1 -1
  21. package/dist/effect/mod.js +3 -1
  22. package/dist/effect/mod.js.map +1 -1
  23. package/dist/live-queries/base-class.d.ts +3 -3
  24. package/dist/live-queries/base-class.d.ts.map +1 -1
  25. package/dist/live-queries/base-class.js +2 -2
  26. package/dist/live-queries/base-class.js.map +1 -1
  27. package/dist/live-queries/client-document-get-query.d.ts +1 -1
  28. package/dist/live-queries/client-document-get-query.d.ts.map +1 -1
  29. package/dist/live-queries/client-document-get-query.js +1 -1
  30. package/dist/live-queries/client-document-get-query.js.map +1 -1
  31. package/dist/live-queries/computed.d.ts.map +1 -1
  32. package/dist/live-queries/computed.js +2 -2
  33. package/dist/live-queries/computed.js.map +1 -1
  34. package/dist/live-queries/db-query.js +14 -14
  35. package/dist/live-queries/db-query.js.map +1 -1
  36. package/dist/live-queries/db-query.test.js +2 -2
  37. package/dist/live-queries/db-query.test.js.map +1 -1
  38. package/dist/live-queries/signal.test.js +2 -2
  39. package/dist/live-queries/signal.test.js.map +1 -1
  40. package/dist/mod.d.ts +2 -1
  41. package/dist/mod.d.ts.map +1 -1
  42. package/dist/mod.js +1 -0
  43. package/dist/mod.js.map +1 -1
  44. package/dist/reactive.d.ts +9 -9
  45. package/dist/reactive.d.ts.map +1 -1
  46. package/dist/reactive.js +9 -26
  47. package/dist/reactive.js.map +1 -1
  48. package/dist/reactive.test.js +2 -2
  49. package/dist/reactive.test.js.map +1 -1
  50. package/dist/store/StoreRegistry.d.ts +215 -0
  51. package/dist/store/StoreRegistry.d.ts.map +1 -0
  52. package/dist/store/StoreRegistry.js +267 -0
  53. package/dist/store/StoreRegistry.js.map +1 -0
  54. package/dist/store/StoreRegistry.test.d.ts +2 -0
  55. package/dist/store/StoreRegistry.test.d.ts.map +1 -0
  56. package/dist/store/StoreRegistry.test.js +381 -0
  57. package/dist/store/StoreRegistry.test.js.map +1 -0
  58. package/dist/store/create-store.d.ts +56 -6
  59. package/dist/store/create-store.d.ts.map +1 -1
  60. package/dist/store/create-store.js +32 -7
  61. package/dist/store/create-store.js.map +1 -1
  62. package/dist/store/devtools.d.ts +1 -1
  63. package/dist/store/devtools.d.ts.map +1 -1
  64. package/dist/store/devtools.js +16 -3
  65. package/dist/store/devtools.js.map +1 -1
  66. package/dist/store/store-eventstream.test.js +2 -2
  67. package/dist/store/store-eventstream.test.js.map +1 -1
  68. package/dist/store/store-types.d.ts +59 -9
  69. package/dist/store/store-types.d.ts.map +1 -1
  70. package/dist/store/store-types.js.map +1 -1
  71. package/dist/store/store-types.test.js +1 -1
  72. package/dist/store/store-types.test.js.map +1 -1
  73. package/dist/store/store.d.ts +102 -6
  74. package/dist/store/store.d.ts.map +1 -1
  75. package/dist/store/store.js +148 -47
  76. package/dist/store/store.js.map +1 -1
  77. package/dist/utils/dev.js.map +1 -1
  78. package/dist/utils/stack-info.js +2 -2
  79. package/dist/utils/stack-info.js.map +1 -1
  80. package/dist/utils/tests/fixture.d.ts +1 -1
  81. package/dist/utils/tests/fixture.d.ts.map +1 -1
  82. package/dist/utils/tests/fixture.js.map +1 -1
  83. package/dist/utils/tests/otel.d.ts.map +1 -1
  84. package/dist/utils/tests/otel.js +5 -5
  85. package/dist/utils/tests/otel.js.map +1 -1
  86. package/package.json +59 -18
  87. package/src/QueryCache.ts +1 -1
  88. package/src/SqliteDbWrapper.test.ts +4 -2
  89. package/src/SqliteDbWrapper.ts +12 -11
  90. package/src/ambient.d.ts +0 -7
  91. package/src/effect/LiveStore.test.ts +61 -0
  92. package/src/effect/LiveStore.ts +381 -8
  93. package/src/effect/mod.ts +13 -1
  94. package/src/live-queries/__snapshots__/db-query.test.ts.snap +336 -231
  95. package/src/live-queries/base-class.ts +7 -6
  96. package/src/live-queries/client-document-get-query.ts +4 -2
  97. package/src/live-queries/computed.ts +3 -2
  98. package/src/live-queries/db-query.test.ts +3 -2
  99. package/src/live-queries/db-query.ts +15 -15
  100. package/src/live-queries/signal.test.ts +3 -2
  101. package/src/mod.ts +2 -0
  102. package/src/reactive.test.ts +3 -2
  103. package/src/reactive.ts +22 -23
  104. package/src/store/StoreRegistry.test.ts +540 -0
  105. package/src/store/StoreRegistry.ts +418 -0
  106. package/src/store/create-store.ts +76 -15
  107. package/src/store/devtools.ts +20 -6
  108. package/src/store/store-eventstream.test.ts +4 -2
  109. package/src/store/store-types.test.ts +3 -1
  110. package/src/store/store-types.ts +64 -13
  111. package/src/store/store.ts +197 -60
  112. package/src/utils/dev.ts +2 -2
  113. package/src/utils/stack-info.ts +2 -2
  114. package/src/utils/tests/fixture.ts +2 -1
  115. package/src/utils/tests/otel.ts +8 -7
  116. package/docs/api/index.md +0 -3
  117. package/docs/building-with-livestore/complex-ui-state/index.md +0 -5
  118. package/docs/building-with-livestore/crud/index.md +0 -5
  119. package/docs/building-with-livestore/data-modeling/index.md +0 -1
  120. package/docs/building-with-livestore/debugging/index.md +0 -17
  121. package/docs/building-with-livestore/devtools/index.md +0 -79
  122. package/docs/building-with-livestore/events/index.md +0 -355
  123. package/docs/building-with-livestore/examples/ai-agent/index.md +0 -5
  124. package/docs/building-with-livestore/examples/index.md +0 -30
  125. package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -891
  126. package/docs/building-with-livestore/examples/turnbased-game/index.md +0 -7
  127. package/docs/building-with-livestore/opentelemetry/index.md +0 -208
  128. package/docs/building-with-livestore/production-checklist/index.md +0 -5
  129. package/docs/building-with-livestore/reactivity-system/index.md +0 -202
  130. package/docs/building-with-livestore/rules-for-ai-agents/index.md +0 -9
  131. package/docs/building-with-livestore/state/materializers/index.md +0 -300
  132. package/docs/building-with-livestore/state/sql-queries/index.md +0 -72
  133. package/docs/building-with-livestore/state/sqlite/index.md +0 -45
  134. package/docs/building-with-livestore/state/sqlite-schema/index.md +0 -306
  135. package/docs/building-with-livestore/state/sqlite-schema-effect/index.md +0 -300
  136. package/docs/building-with-livestore/store/index.md +0 -281
  137. package/docs/building-with-livestore/syncing/index.md +0 -136
  138. package/docs/building-with-livestore/tools/cli/index.md +0 -177
  139. package/docs/building-with-livestore/tools/mcp/index.md +0 -187
  140. package/docs/examples/cloudflare-adapter/index.md +0 -44
  141. package/docs/examples/expo-adapter/index.md +0 -44
  142. package/docs/examples/index.md +0 -55
  143. package/docs/examples/node-adapter/index.md +0 -44
  144. package/docs/examples/web-adapter/index.md +0 -52
  145. package/docs/framework-integrations/custom-elements/index.md +0 -142
  146. package/docs/framework-integrations/react-integration/index.md +0 -918
  147. package/docs/framework-integrations/solid-integration/index.md +0 -293
  148. package/docs/framework-integrations/svelte-integration/index.md +0 -42
  149. package/docs/framework-integrations/vue-integration/index.md +0 -294
  150. package/docs/getting-started/expo/index.md +0 -736
  151. package/docs/getting-started/node/index.md +0 -115
  152. package/docs/getting-started/react-web/index.md +0 -573
  153. package/docs/getting-started/solid/index.md +0 -3
  154. package/docs/getting-started/vue/index.md +0 -471
  155. package/docs/index.md +0 -209
  156. package/docs/llms.txt +0 -147
  157. package/docs/misc/CODE_OF_CONDUCT/index.md +0 -133
  158. package/docs/misc/FAQ/index.md +0 -37
  159. package/docs/misc/community/index.md +0 -88
  160. package/docs/misc/credits/index.md +0 -14
  161. package/docs/misc/design-partners/index.md +0 -13
  162. package/docs/misc/package-management/index.md +0 -21
  163. package/docs/misc/performance/index.md +0 -25
  164. package/docs/misc/resources/index.md +0 -46
  165. package/docs/misc/state-of-the-project/index.md +0 -37
  166. package/docs/misc/troubleshooting/index.md +0 -82
  167. package/docs/overview/concepts/index.md +0 -78
  168. package/docs/overview/how-livestore-works/index.md +0 -56
  169. package/docs/overview/introduction/index.md +0 -5
  170. package/docs/overview/technology-comparison/index.md +0 -40
  171. package/docs/overview/when-livestore/index.md +0 -81
  172. package/docs/overview/why-livestore/index.md +0 -5
  173. package/docs/patterns/ai/index.md +0 -15
  174. package/docs/patterns/anonymous-user-transition/index.md +0 -10
  175. package/docs/patterns/app-evolution/index.md +0 -72
  176. package/docs/patterns/auth/index.md +0 -226
  177. package/docs/patterns/effect/index.md +0 -1495
  178. package/docs/patterns/encryption/index.md +0 -6
  179. package/docs/patterns/external-data/index.md +0 -5
  180. package/docs/patterns/file-management/index.md +0 -11
  181. package/docs/patterns/file-structure/index.md +0 -14
  182. package/docs/patterns/list-ordering/index.md +0 -369
  183. package/docs/patterns/offline/index.md +0 -32
  184. package/docs/patterns/orm/index.md +0 -18
  185. package/docs/patterns/presence/index.md +0 -11
  186. package/docs/patterns/rich-text-editing/index.md +0 -11
  187. package/docs/patterns/server-side-clients/index.md +0 -97
  188. package/docs/patterns/side-effects/index.md +0 -11
  189. package/docs/patterns/state-machines/index.md +0 -11
  190. package/docs/patterns/storybook/index.md +0 -192
  191. package/docs/patterns/undo-redo/index.md +0 -9
  192. package/docs/patterns/version-control/index.md +0 -8
  193. package/docs/platform-adapters/cloudflare-durable-object-adapter/index.md +0 -453
  194. package/docs/platform-adapters/electron-adapter/index.md +0 -15
  195. package/docs/platform-adapters/expo-adapter/index.md +0 -245
  196. package/docs/platform-adapters/node-adapter/index.md +0 -160
  197. package/docs/platform-adapters/tauri-adapter/index.md +0 -15
  198. package/docs/platform-adapters/web-adapter/index.md +0 -218
  199. package/docs/sustainable-open-source/contributing/docs/index.md +0 -94
  200. package/docs/sustainable-open-source/contributing/info/index.md +0 -63
  201. package/docs/sustainable-open-source/contributing/monorepo/index.md +0 -195
  202. package/docs/sustainable-open-source/sponsoring/index.md +0 -104
  203. package/docs/sync-providers/cloudflare/index.md +0 -773
  204. package/docs/sync-providers/custom/index.md +0 -65
  205. package/docs/sync-providers/electricsql/index.md +0 -159
  206. package/docs/sync-providers/s2/index.md +0 -230
  207. package/docs/tutorial/0-welcome/index.md +0 -48
  208. package/docs/tutorial/1-setup-starter-project/index.md +0 -105
  209. package/docs/tutorial/2-deploy-to-cloudflare/index.md +0 -195
  210. package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +0 -511
  211. package/docs/tutorial/4-sync-data-via-cloudflare/index.md +0 -210
  212. package/docs/tutorial/5-expand-business-logic/index.md +0 -174
  213. package/docs/tutorial/6-persist-ui-state/index.md +0 -453
  214. package/docs/tutorial/7-next-steps/index.md +0 -22
  215. package/docs/understanding-livestore/design-decisions/index.md +0 -33
  216. package/docs/understanding-livestore/event-sourcing/index.md +0 -40
@@ -1,245 +0,0 @@
1
- # Expo Adapter
2
-
3
- The Expo adapter enables LiveStore in React Native applications built with [Expo](https://expo.dev). It uses native SQLite via `expo-sqlite` for high-performance local persistence on iOS and Android devices.
4
-
5
- ## Key Features
6
-
7
- - **Signals-based reactivity** — High-performance state management with fine-grained updates
8
- - **iOS and Android support** — Works seamlessly on both platforms with native performance
9
- - **Native SQLite storage** — Uses `expo-sqlite` for fast, reliable persistence directly on the device
10
- - **Offline-first** — Full functionality without network connectivity; syncs when connected
11
- - **Real-time sync** — Optional sync backend integration for multi-device data synchronization
12
- - **Integrated devtools** — Debug and inspect your store via the [LiveStore Devtools](/building-with-livestore/devtools)
13
-
14
- ## Requirements
15
-
16
- - [Expo New Architecture](https://docs.expo.dev/guides/new-architecture/) (Fabric) must be enabled
17
- - `expo-sqlite` ^16.0.0
18
- - `expo-application` ^7.0.0
19
-
20
- :::note
21
- Expo Web is not currently supported. See [#130](https://github.com/livestorejs/livestore/issues/130) for progress.
22
- :::
23
-
24
- ## Installation
25
-
26
- ```bash
27
- npm install @livestore/adapter-expo @livestore/livestore @livestore/react expo-sqlite expo-application
28
- ```
29
-
30
- For a complete setup including sync and devtools, see the [Expo getting started guide](/getting-started/expo).
31
-
32
- ## Basic Usage
33
-
34
- Create an adapter and wrap your app with the `LiveStoreProvider`:
35
-
36
- ## `reference/platform-adapters/expo-adapter/usage.tsx`
37
-
38
- ```tsx filename="reference/platform-adapters/expo-adapter/usage.tsx"
39
-
40
- const adapter = makePersistedAdapter()
41
-
42
- export const App = () => (
43
- <SafeAreaView style={{ flex: 1 }}>
44
- <LiveStoreProvider
45
- schema={schema}
46
- adapter={adapter}
47
- storeId="my-app"
48
- batchUpdates={batchUpdates}
49
- renderLoading={(status) => <Text>Loading ({status.stage})...</Text>}
50
- renderError={(error) => <Text>Error: {String(error)}</Text>}
51
- >
52
- {/* Your app content */}
53
- </LiveStoreProvider>
54
- </SafeAreaView>
55
- )
56
- ```
57
-
58
- ### `reference/platform-adapters/expo-adapter/schema.ts`
59
-
60
- ```ts filename="reference/platform-adapters/expo-adapter/schema.ts"
61
-
62
- const tables = {
63
- todos: State.SQLite.table({
64
- name: 'todos',
65
- columns: {
66
- id: State.SQLite.text({ primaryKey: true }),
67
- text: State.SQLite.text(),
68
- completed: State.SQLite.boolean({ default: false }),
69
- },
70
- }),
71
- } as const
72
-
73
- const events = {
74
- todoCreated: Events.synced({
75
- name: 'v1.TodoCreated',
76
- schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
77
- }),
78
- } as const
79
-
80
- const materializers = State.SQLite.materializers(events, {
81
- [events.todoCreated.name]: defineMaterializer(events.todoCreated, ({ id, text }) =>
82
- tables.todos.insert({ id, text, completed: false }),
83
- ),
84
- })
85
-
86
- const state = State.SQLite.makeState({ tables, materializers })
87
-
88
- export const schema = makeSchema({ events, state })
89
- ```
90
-
91
- The adapter requires minimal configuration. For more details on the provider props, see the [React integration guide](/framework-integrations/react-integration).
92
-
93
- ## Configuration Options
94
-
95
- ## `reference/platform-adapters/expo-adapter/adapter.ts`
96
-
97
- ```ts filename="reference/platform-adapters/expo-adapter/adapter.ts"
98
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
99
- // ---cut---
100
-
101
- const adapter = makePersistedAdapter({
102
- storage: { subDirectory: 'my-app' },
103
- })
104
- ```
105
-
106
- ### Available Options
107
-
108
- | Option | Type | Description |
109
- |--------|------|-------------|
110
- | `storage.subDirectory` | `string` | Subdirectory within the default SQLite location for organizing databases |
111
- | `sync` | `SyncOptions` | Sync backend configuration (see [Syncing](/building-with-livestore/syncing)) |
112
- | `clientId` | `string` | Custom client identifier (defaults to device ID) |
113
- | `sessionId` | `string` | Session identifier (defaults to `'static'`) |
114
- | `resetPersistence` | `boolean` | Clear local databases on startup (development only) |
115
-
116
- ## Adding a Sync Backend
117
-
118
- Connect to a sync backend for multi-device synchronization:
119
-
120
- ## `reference/platform-adapters/expo-adapter/sync-backend.ts`
121
-
122
- ```ts filename="reference/platform-adapters/expo-adapter/sync-backend.ts"
123
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
124
- // ---cut---
125
-
126
- const adapter = makePersistedAdapter({
127
- sync: { backend: makeWsSync({ url: 'wss://your-sync-backend.com' }) },
128
- })
129
- ```
130
-
131
- See the [Syncing documentation](/building-with-livestore/syncing) for available sync providers and configuration options.
132
-
133
- ## Platform Notes
134
-
135
- ### Android
136
-
137
- Android requires HTTPS for network connections by default. During development with a local sync backend using `http://` or `ws://`, add `expo-build-properties` to allow cleartext traffic:
138
-
139
- ```bash
140
- npx expo install expo-build-properties
141
- ```
142
-
143
- Then configure `app.json`:
144
-
145
- ```json
146
- {
147
- "expo": {
148
- "plugins": [
149
- [
150
- "expo-build-properties",
151
- {
152
- "android": {
153
- "usesCleartextTraffic": true
154
- }
155
- }
156
- ]
157
- ]
158
- }
159
- }
160
- ```
161
-
162
- See [Expo build properties documentation](https://docs.expo.dev/versions/latest/sdk/build-properties/#pluginconfigtypeandroid) for more details.
163
-
164
- ### iOS
165
-
166
- No special configuration required. The adapter automatically retrieves the iOS vendor ID for client identification.
167
-
168
- ## Devtools
169
-
170
- LiveStore provides integrated devtools for debugging your store. In development, press `shift + m` in the Expo CLI terminal, then select "LiveStore Devtools" to open the browser-based inspector.
171
-
172
- See the [Devtools reference](/building-with-livestore/devtools) for full documentation.
173
-
174
- ## Storage & Persistence
175
-
176
- ### Database Location
177
-
178
- Databases are stored in the device's SQLite directory. The exact path depends on your setup:
179
-
180
- **Expo Go:**
181
- ```bash
182
- open $(find $(xcrun simctl get_app_container booted host.exp.Exponent data) -path "*/Documents/ExponentExperienceData/*livestore*" -print -quit)/SQLite
183
- ```
184
-
185
- **Development builds:**
186
- ```bash
187
- open $(xcrun simctl get_app_container booted [APP_BUNDLE_ID] data)/Documents/SQLite
188
- ```
189
-
190
- Replace `[APP_BUNDLE_ID]` with your app's bundle identifier (e.g., `dev.livestore.myapp`).
191
-
192
- ### Resetting Local Persistence
193
-
194
- During development, you can clear local databases on startup:
195
-
196
- ## `reference/platform-adapters/expo-adapter/reset-persistence.ts`
197
-
198
- ```ts filename="reference/platform-adapters/expo-adapter/reset-persistence.ts"
199
-
200
- const resetPersistence = process.env.EXPO_PUBLIC_LIVESTORE_RESET === 'true'
201
-
202
- const _adapter = makePersistedAdapter({
203
- storage: { subDirectory: 'dev' },
204
- resetPersistence,
205
- })
206
- ```
207
-
208
- :::caution
209
- This deletes all local LiveStore data for the configured store. It only clears on-device data and does not affect any connected sync backend. Ensure this flag is disabled in production builds.
210
- :::
211
-
212
- ## Architecture
213
-
214
- The Expo adapter runs LiveStore directly in the main JavaScript thread, using native SQLite bindings provided by `expo-sqlite`. This differs from the [web adapter](/platform-adapters/web-adapter), which uses web workers and WASM-based SQLite.
215
-
216
- ```
217
- ┌─────────────────────────────────────────┐
218
- │ React Native App │
219
- │ ┌───────────────────────────────────┐ │
220
- │ │ LiveStore Client │ │
221
- │ │ ┌─────────────┐ ┌─────────────┐ │ │
222
- │ │ │ State DB │ │ Eventlog DB │ │ │
223
- │ │ │(expo-sqlite)│ │(expo-sqlite)│ │ │
224
- │ │ └─────────────┘ └─────────────┘ │ │
225
- │ └───────────────────────────────────┘ │
226
- └─────────────────────────────────────────┘
227
-
228
- ▼ WebSocket
229
- ┌───────────────┐
230
- │ Sync Backend │
231
- │ (optional) │
232
- └───────────────┘
233
- ```
234
-
235
- ## Future Improvements
236
-
237
- We're exploring moving database operations to a background thread to further improve UI responsiveness during intensive writes. Follow [livestore/livestore](https://github.com/livestorejs/livestore) for updates.
238
-
239
- ## See Also
240
-
241
- - [Expo Getting Started Guide](/getting-started/expo) — Complete setup tutorial
242
- - [Expo Adapter Examples](/examples/expo-adapter) — Example applications
243
- - [React Integration](/framework-integrations/react-integration) — Provider and hooks documentation
244
- - [Syncing](/building-with-livestore/syncing) — Multi-device synchronization
245
- - [Devtools](/building-with-livestore/devtools) — Debugging and inspection tools
@@ -1,160 +0,0 @@
1
- # Node adapter
2
-
3
- Works with Node.js, Bun and Deno.
4
-
5
- ## Example
6
-
7
- ## `reference/platform-adapters/node-adapter/adapter.ts`
8
-
9
- ```ts filename="reference/platform-adapters/node-adapter/adapter.ts"
10
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
11
- // ---cut---
12
-
13
- const adapter = makeAdapter({
14
- storage: { type: 'fs' },
15
- // or in-memory:
16
- // storage: { type: 'in-memory' },
17
- sync: { backend: makeWsSync({ url: 'ws://localhost:8787' }) },
18
- // To enable devtools:
19
- // devtools: { schemaPath: new URL('./schema.ts', import.meta.url) },
20
- })
21
- ```
22
-
23
- ## Resetting local persistence
24
-
25
- During development you can instruct the adapter to wipe the locally persisted state and eventlog databases on startup:
26
-
27
- ## `reference/platform-adapters/node-adapter/reset-persistence.ts`
28
-
29
- ```ts filename="reference/platform-adapters/node-adapter/reset-persistence.ts"
30
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
31
- // ---cut---
32
-
33
- const resetPersistence = process.env.NODE_ENV !== 'production' && Boolean(process.env.RESET_LIVESTORE)
34
-
35
- const adapter = makeAdapter({
36
- storage: { type: 'fs' },
37
- resetPersistence,
38
- })
39
- ```
40
-
41
- :::caution
42
- This will delete all local data for the given `storeId` and `clientId`. It only clears local persistence and does not reset any connected sync backend. Only enable it for debugging scenarios.
43
- :::
44
-
45
- ### Worker adapter
46
-
47
- The worker adapter can be used for more advanced scenarios where it's preferable to reduce the load of the main thread and run persistence/syncing in a worker thread.
48
-
49
- ## `reference/platform-adapters/node-adapter/worker-main.ts`
50
-
51
- ```ts filename="reference/platform-adapters/node-adapter/worker-main.ts"
52
- /** biome-ignore-all lint/correctness/noUnusedVariables: snippet keeps adapter inline for docs */
53
- // ---cut---
54
-
55
- const adapter = makeWorkerAdapter({
56
- storage: { type: 'fs' },
57
- workerUrl: new URL('./livestore.worker.js', import.meta.url),
58
- })
59
- ```
60
-
61
- ## `reference/platform-adapters/node-adapter/worker-worker.ts`
62
-
63
- ```ts filename="reference/platform-adapters/node-adapter/worker-worker.ts"
64
-
65
- makeWorker({
66
- schema,
67
- sync: { backend: makeWsSync({ url: 'ws://localhost:8787' }) },
68
- })
69
- ```
70
-
71
- ### `reference/platform-adapters/node-adapter/schema.ts`
72
-
73
- ```ts filename="reference/platform-adapters/node-adapter/schema.ts"
74
-
75
- const tables = {
76
- todos: State.SQLite.table({
77
- name: 'todos',
78
- columns: {
79
- id: State.SQLite.text({ primaryKey: true }),
80
- text: State.SQLite.text(),
81
- completed: State.SQLite.boolean({ default: false }),
82
- },
83
- }),
84
- } as const
85
-
86
- const events = {
87
- todoCreated: Events.synced({
88
- name: 'v1.TodoCreated',
89
- schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
90
- }),
91
- } as const
92
-
93
- const materializers = State.SQLite.materializers(events, {
94
- [events.todoCreated.name]: defineMaterializer(events.todoCreated, ({ id, text }) =>
95
- tables.todos.insert({ id, text, completed: false }),
96
- ),
97
- })
98
-
99
- const state = State.SQLite.makeState({ tables, materializers })
100
-
101
- export const schema = makeSchema({ events, state })
102
- ```
103
-
104
- #### Logging
105
-
106
- You can control what the Node worker logs and how it's formatted.
107
- Pass two optional options to `makeWorker`:
108
-
109
- - `logger` — where/format of logs (e.g. pretty console output)
110
- - `logLevel` — how verbose logs are (`LogLevel.None` silences logs)
111
-
112
- ## `reference/platform-adapters/node-adapter/worker-logging.ts`
113
-
114
- ```ts filename="reference/platform-adapters/node-adapter/worker-logging.ts"
115
-
116
- makeWorker({
117
- schema,
118
- // readable console output by thread name
119
- logger: Logger.prettyWithThread('livestore-node-leader-thread'),
120
- // choose verbosity: None | Error | Warning | Info | Debug
121
- logLevel: LogLevel.Info,
122
- })
123
- ```
124
-
125
- ### `reference/platform-adapters/node-adapter/schema.ts`
126
-
127
- ```ts filename="reference/platform-adapters/node-adapter/schema.ts"
128
-
129
- const tables = {
130
- todos: State.SQLite.table({
131
- name: 'todos',
132
- columns: {
133
- id: State.SQLite.text({ primaryKey: true }),
134
- text: State.SQLite.text(),
135
- completed: State.SQLite.boolean({ default: false }),
136
- },
137
- }),
138
- } as const
139
-
140
- const events = {
141
- todoCreated: Events.synced({
142
- name: 'v1.TodoCreated',
143
- schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
144
- }),
145
- } as const
146
-
147
- const materializers = State.SQLite.materializers(events, {
148
- [events.todoCreated.name]: defineMaterializer(events.todoCreated, ({ id, text }) =>
149
- tables.todos.insert({ id, text, completed: false }),
150
- ),
151
- })
152
-
153
- const state = State.SQLite.makeState({ tables, materializers })
154
-
155
- export const schema = makeSchema({ events, state })
156
- ```
157
-
158
- Tips:
159
- - Use `LogLevel.None` to keep test output quiet.
160
- - Keep the default (Debug) when diagnosing issues.
@@ -1,15 +0,0 @@
1
- # Tauri adapter
2
-
3
- ## Native Tauri adapter
4
-
5
- While LiveStore doesn't yet support a native Tauri adapter (see [this issue](https://github.com/livestorejs/livestore/issues/125) for more details), you can already use the [web adapter](./web-adapter.md) with Tauri.
6
-
7
- The goal of the native Tauri adapter is for LiveStore to leverage native platform APIs and capabilities including:
8
-
9
- - Native file system access (instead of going through the browser abstraction layer)
10
- - Background sync capabilities
11
- - ...
12
-
13
- ## Example using the web adapter
14
-
15
- See this example of a Tauri app using the web adapter: [tauri-todomvc-sync-cf](https://github.com/bohdanbirdie/tauri-todomvc-sync-cf)
@@ -1,218 +0,0 @@
1
- # Web adapter
2
-
3
- ## Installation
4
-
5
- ```bash
6
- npm install @livestore/adapter-web @livestore/wa-sqlite
7
- ```
8
-
9
- ## Example
10
-
11
- ## `reference/platform-adapters/web-adapter/main.ts`
12
-
13
- ```ts filename="reference/platform-adapters/web-adapter/main.ts"
14
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
15
- // ---cut---
16
-
17
- const adapter = makePersistedAdapter({
18
- storage: { type: 'opfs' },
19
- worker: LiveStoreWorker,
20
- sharedWorker: LiveStoreSharedWorker,
21
- })
22
- ```
23
-
24
- ## `reference/platform-adapters/web-adapter/livestore.worker.ts`
25
-
26
- ```ts filename="reference/platform-adapters/web-adapter/livestore.worker.ts"
27
-
28
- makeWorker({ schema })
29
- ```
30
-
31
- ### `reference/platform-adapters/web-adapter/schema/index.ts`
32
-
33
- ```ts filename="reference/platform-adapters/web-adapter/schema/index.ts"
34
-
35
- const tables = {
36
- todos: State.SQLite.table({
37
- name: 'todos',
38
- columns: {
39
- id: State.SQLite.text({ primaryKey: true }),
40
- text: State.SQLite.text(),
41
- completed: State.SQLite.boolean({ default: false }),
42
- },
43
- }),
44
- } as const
45
-
46
- const events = {
47
- todoCreated: Events.synced({
48
- name: 'v1.TodoCreated',
49
- schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
50
- }),
51
- } as const
52
-
53
- const materializers = State.SQLite.materializers(events, {
54
- [events.todoCreated.name]: defineMaterializer(events.todoCreated, ({ id, text }) =>
55
- tables.todos.insert({ id, text, completed: false }),
56
- ),
57
- })
58
-
59
- const state = State.SQLite.makeState({ tables, materializers })
60
-
61
- export const schema = makeSchema({ events, state })
62
- ```
63
-
64
- ## Adding a sync backend
65
-
66
- ## `reference/platform-adapters/web-adapter/sync-backend.ts`
67
-
68
- ```ts filename="reference/platform-adapters/web-adapter/sync-backend.ts"
69
-
70
- makeWorker({ schema, sync: { backend: makeWsSync({ url: 'ws://localhost:8787' }) } })
71
- ```
72
-
73
- ### `reference/platform-adapters/web-adapter/schema/index.ts`
74
-
75
- ```ts filename="reference/platform-adapters/web-adapter/schema/index.ts"
76
-
77
- const tables = {
78
- todos: State.SQLite.table({
79
- name: 'todos',
80
- columns: {
81
- id: State.SQLite.text({ primaryKey: true }),
82
- text: State.SQLite.text(),
83
- completed: State.SQLite.boolean({ default: false }),
84
- },
85
- }),
86
- } as const
87
-
88
- const events = {
89
- todoCreated: Events.synced({
90
- name: 'v1.TodoCreated',
91
- schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
92
- }),
93
- } as const
94
-
95
- const materializers = State.SQLite.materializers(events, {
96
- [events.todoCreated.name]: defineMaterializer(events.todoCreated, ({ id, text }) =>
97
- tables.todos.insert({ id, text, completed: false }),
98
- ),
99
- })
100
-
101
- const state = State.SQLite.makeState({ tables, materializers })
102
-
103
- export const schema = makeSchema({ events, state })
104
- ```
105
-
106
- ## In-memory adapter
107
-
108
- You can also use the in-memory adapter which can be useful in certain scenarios (e.g. testing).
109
-
110
- ## `reference/platform-adapters/web-adapter/in-memory.ts`
111
-
112
- ```ts filename="reference/platform-adapters/web-adapter/in-memory.ts"
113
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
114
- // ---cut---
115
-
116
- const adapter = makeInMemoryAdapter()
117
- ```
118
-
119
- ## Web worker
120
-
121
- - Make sure your schema doesn't depend on any code which needs to run in the main thread (e.g. avoid importing from files using React)
122
- - Unfortunately this constraints you from co-locating your table definitions in component files.
123
- - You might be able to still work around this by using the following import in your worker:
124
- ```ts
125
-
126
- ```
127
-
128
- ### Why is there a dedicated web worker and a shared worker?
129
-
130
- - Shared worker:
131
- - Needed to allow tabs to communicate with each other using a binary message channel.
132
- - The shared worker mostly acts as a proxy to the dedicated web worker.
133
- - Dedicated web worker (also called "leader worker" via leader election mechanism using web locks):
134
- - Acts as the leader/single writer for the storage.
135
- - Also handles connection to sync backend.
136
- - Currently needed for synchronous OPFS API which isn't supported in a shared worker. (Hopefully won't be needed in the future anymore.)
137
-
138
- ### Why not use a service worker?
139
-
140
- - While service workers seem similar to shared workers (i.e. only a single instance across all tabs), they serve different purposes and have different trade-offs.
141
- - Service workers are meant to be used to intercept network requests and tend to "shut down" when there are no requests for some period of time making them unsuitable for our use case.
142
- - Also note that service workers don't support some needed APIs such as OPFS.
143
-
144
- ## Storage
145
-
146
- LiveStore currently only support OPFS to locally persist its data. In the future we might add support for other storage types (e.g. IndexedDB).
147
-
148
- During development (`NODE_ENV !== 'production'`), LiveStore automatically copies older state database files into `archive/` inside the OPFS directory for the store (e.g. `livestore-<storeId>@<version>/archive/`). The three most recent copies are retained so you can inspect pre-migration data; older archives are pruned. In production, we delete outdated state databases immediately.
149
-
150
- LiveStore also uses `window.sessionStorage` to retain the identity of a client session (e.g. tab/window) across reloads.
151
-
152
- ### Resetting local persistence
153
-
154
- Resetting local persistence only clears data stored in the browser and does not affect any connected sync backend.
155
-
156
- In case you want to reset the local persistence of a client, you can provide the `resetPersistence` option to the adapter.
157
-
158
- ## `reference/platform-adapters/web-adapter/reset-persistence.ts`
159
-
160
- ```ts filename="reference/platform-adapters/web-adapter/reset-persistence.ts"
161
- /** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
162
- // ---cut---
163
-
164
- const resetPersistence = import.meta.env.DEV && new URLSearchParams(window.location.search).get('reset') !== null
165
-
166
- if (resetPersistence) {
167
- const searchParams = new URLSearchParams(window.location.search)
168
- searchParams.delete('reset')
169
- window.history.replaceState(null, '', `${window.location.pathname}?${searchParams.toString()}`)
170
- }
171
-
172
- const adapter = makePersistedAdapter({
173
- storage: { type: 'opfs' },
174
- worker: LiveStoreWorker,
175
- sharedWorker: LiveStoreSharedWorker,
176
- resetPersistence,
177
- })
178
- ```
179
-
180
- If you want to reset persistence manually, you can:
181
-
182
- 1. **Clear site data** in Chrome DevTools (Application tab > Storage > Clear site data)
183
- 2. **Use console command** if the above doesn't work due to a Chrome OPFS bug:
184
-
185
- ```javascript
186
- const opfsRoot = await navigator.storage.getDirectory();
187
- await opfsRoot.remove();
188
- ```
189
-
190
- Note: Only use this during development while the app is running.
191
-
192
- ## Architecture diagram
193
-
194
- Assuming the web adapter in a multi-client, multi-tab browser application, a diagram looks like this:
195
-
196
- ![](https://i.imgur.com/NCKbfub.png)
197
-
198
- ## Other notes
199
-
200
- - The web adapter is using some browser APIs that might require a HTTPS connection (e.g. `navigator.locks`). It's recommended to even use HTTPS during local development (e.g. via [Caddy](https://caddyserver.com/docs/automatic-https)).
201
-
202
- ## Browser support
203
-
204
- - Notable required browser APIs: OPFS, SharedWorker, `navigator.locks`, WASM
205
- - The web adapter of LiveStore currently doesn't work on Android browsers as they don't support the `SharedWorker` API (see [Chromium bug](https://issues.chromium.org/issues/40290702)).
206
-
207
- ## Best practices
208
-
209
- - It's recommended to develop in an incognito window to avoid issues with persistent storage (e.g. OPFS).
210
-
211
- ## FAQ
212
-
213
- ### What's the bundle size of the web adapter?
214
-
215
- LiveStore with the web adapter adds two parts to your application bundle:
216
-
217
- - The LiveStore JavaScript bundle (~180KB gzipped)
218
- - SQLite WASM (~300KB gzipped)