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

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 (75) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/effect/LiveStore.d.ts +123 -2
  3. package/dist/effect/LiveStore.d.ts.map +1 -1
  4. package/dist/effect/LiveStore.js +195 -1
  5. package/dist/effect/LiveStore.js.map +1 -1
  6. package/dist/effect/mod.d.ts +1 -1
  7. package/dist/effect/mod.d.ts.map +1 -1
  8. package/dist/effect/mod.js +3 -1
  9. package/dist/effect/mod.js.map +1 -1
  10. package/dist/mod.d.ts +1 -0
  11. package/dist/mod.d.ts.map +1 -1
  12. package/dist/mod.js +1 -0
  13. package/dist/mod.js.map +1 -1
  14. package/dist/store/StoreRegistry.d.ts +190 -0
  15. package/dist/store/StoreRegistry.d.ts.map +1 -0
  16. package/dist/store/StoreRegistry.js +244 -0
  17. package/dist/store/StoreRegistry.js.map +1 -0
  18. package/dist/store/StoreRegistry.test.d.ts +2 -0
  19. package/dist/store/StoreRegistry.test.d.ts.map +1 -0
  20. package/dist/store/StoreRegistry.test.js +380 -0
  21. package/dist/store/StoreRegistry.test.js.map +1 -0
  22. package/dist/store/create-store.d.ts +50 -4
  23. package/dist/store/create-store.d.ts.map +1 -1
  24. package/dist/store/create-store.js +19 -0
  25. package/dist/store/create-store.js.map +1 -1
  26. package/dist/store/devtools.d.ts.map +1 -1
  27. package/dist/store/devtools.js +13 -0
  28. package/dist/store/devtools.js.map +1 -1
  29. package/dist/store/store-types.d.ts +10 -25
  30. package/dist/store/store-types.d.ts.map +1 -1
  31. package/dist/store/store-types.js.map +1 -1
  32. package/dist/store/store.d.ts +23 -6
  33. package/dist/store/store.d.ts.map +1 -1
  34. package/dist/store/store.js +20 -2
  35. package/dist/store/store.js.map +1 -1
  36. package/docs/building-with-livestore/complex-ui-state/index.md +0 -2
  37. package/docs/building-with-livestore/crud/index.md +0 -2
  38. package/docs/building-with-livestore/data-modeling/index.md +29 -0
  39. package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -6
  40. package/docs/building-with-livestore/opentelemetry/index.md +25 -6
  41. package/docs/building-with-livestore/rules-for-ai-agents/index.md +2 -2
  42. package/docs/building-with-livestore/state/sql-queries/index.md +22 -0
  43. package/docs/building-with-livestore/state/sqlite-schema/index.md +2 -2
  44. package/docs/building-with-livestore/store/index.md +344 -0
  45. package/docs/framework-integrations/react-integration/index.md +380 -361
  46. package/docs/framework-integrations/vue-integration/index.md +2 -2
  47. package/docs/getting-started/expo/index.md +189 -43
  48. package/docs/getting-started/react-web/index.md +77 -24
  49. package/docs/getting-started/vue/index.md +3 -3
  50. package/docs/index.md +1 -2
  51. package/docs/llms.txt +0 -1
  52. package/docs/misc/troubleshooting/index.md +3 -3
  53. package/docs/overview/how-livestore-works/index.md +1 -1
  54. package/docs/overview/introduction/index.md +409 -1
  55. package/docs/overview/why-livestore/index.md +108 -2
  56. package/docs/patterns/auth/index.md +185 -34
  57. package/docs/patterns/effect/index.md +11 -1
  58. package/docs/patterns/storybook/index.md +43 -26
  59. package/docs/platform-adapters/expo-adapter/index.md +36 -19
  60. package/docs/platform-adapters/web-adapter/index.md +71 -2
  61. package/docs/tutorial/1-setup-starter-project/index.md +5 -5
  62. package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +54 -35
  63. package/docs/tutorial/5-expand-business-logic/index.md +1 -1
  64. package/docs/tutorial/6-persist-ui-state/index.md +12 -12
  65. package/package.json +6 -6
  66. package/src/effect/LiveStore.ts +385 -3
  67. package/src/effect/mod.ts +13 -1
  68. package/src/mod.ts +1 -0
  69. package/src/store/StoreRegistry.test.ts +516 -0
  70. package/src/store/StoreRegistry.ts +393 -0
  71. package/src/store/create-store.ts +50 -4
  72. package/src/store/devtools.ts +15 -0
  73. package/src/store/store-types.ts +17 -5
  74. package/src/store/store.ts +25 -5
  75. package/docs/building-with-livestore/examples/index.md +0 -30
@@ -110,7 +110,7 @@ Here's a quick summary of the code:
110
110
  The `tables`, `events` and `materializers` are packaged up into a `schema` object that's needed in the parts of your app where you interact with LiveStore.
111
111
 
112
112
  :::note[Versioning events and materializers]
113
- You may have noticed that event and materializer names are prefixed with `v1`.
113
+ You may have noticed that event and materializer names are prefixed with `v1`.
114
114
 
115
115
  It's good practice in LiveStore to version your events and materializers to ensure future compatibility between them as your app evolves.
116
116
  :::
@@ -120,9 +120,10 @@ It's good practice in LiveStore to version your events and materializers to ensu
120
120
  To now "connect" LiveStore with your React app, you need to:
121
121
 
122
122
  1. Create the [LiveStore web worker](/platform-adapters/web-adapter#web-worker) that is responsible for the logic of persisting data on your file system.
123
- 2. Create a LiveStore [adapter](/platform-adapters/web-adapter) that enables persistences with local SQLite via [OPFS](https://web.dev/articles/origin-private-file-system).
124
- 3. Wrap your root component in `main.tsx` with the LiveStore [provider](https://dev.docs.livestore.dev/reference/framework-integrations/react-integration/#livestoreprovider) (which will receive both the web worker and adapter from above as arguments).
125
- 4. Update your Vite Config to work with LiveStore.
123
+ 2. Create a LiveStore [adapter](/platform-adapters/web-adapter) that enables persistence with local SQLite via [OPFS](https://web.dev/articles/origin-private-file-system).
124
+ 3. Create a store configuration file that exports a custom hook wrapping [`useStore()`](/framework-integrations/react-integration#1-configure-the-store).
125
+ 4. Create and provide a `StoreRegistry` with [`<StoreRegistryProvider>`](/framework-integrations/react-integration#2-set-up-the-registry) in `main.tsx`.
126
+ 5. Update your Vite Config to work with LiveStore.
126
127
 
127
128
  Let's get started!
128
129
 
@@ -145,9 +146,13 @@ This is boilerplate code that you'll almost never need to touch. (In this tutori
145
146
  When importing this file, make sure to add the `?worker` extension to the import path to ensure that [Vite treats it as a worker file](https://vite.dev/guide/features.html#web-workers).
146
147
  :::
147
148
 
148
- Next, update `main.tsx` to create an adapter and wrap your `App` component inside the `LiveStoreProvider`:
149
+ Next, create a `store.ts` file that defines your store configuration and a `useAppStore()` hook:
149
150
 
150
- ```tsx title="src/main.tsx"
151
+ ```bash
152
+ touch src/livestore/store.ts
153
+ ```
154
+
155
+ ```ts title="src/livestore/store.ts"
151
156
 
152
157
  const adapter = makePersistedAdapter({
153
158
  storage: { type: 'opfs' },
@@ -155,23 +160,37 @@ const adapter = makePersistedAdapter({
155
160
  sharedWorker: LiveStoreSharedWorker,
156
161
  })
157
162
 
158
- createRoot(document.getElementById('root')!).render(
159
- <LiveStoreProvider
160
- schema={schema}
161
- adapter={adapter}
162
- renderLoading={(_) => <div>Loading LiveStore ({_.stage})...</div>}
163
- storeId="todo-db-tutorial"
164
- batchUpdates={batchUpdates}
165
- >
166
- <App />
167
- </LiveStoreProvider>
168
- )
163
+ export const useAppStore = () =>
164
+ useStore({
165
+ storeId: 'todo-db-tutorial',
166
+ schema,
167
+ adapter,
168
+ batchUpdates,
169
+ })
170
+ ```
171
+
172
+ Then, update `main.tsx` to wrap your `<App>` component inside the `<StoreRegistryProvider>`:
173
+
174
+ ```tsx title="src/main.tsx"
175
+
176
+ const Root = () => {
177
+ const [storeRegistry] = useState(() => new StoreRegistry())
178
+ return (
179
+ <Suspense fallback={<div>Loading LiveStore...</div>}>
180
+ <StoreRegistryProvider storeRegistry={storeRegistry}>
181
+ <App />
182
+ </StoreRegistryProvider>
183
+ </Suspense>
184
+ )
185
+ }
186
+
187
+ createRoot(document.getElementById('root')!).render(<Root />)
169
188
  ```
170
189
 
171
190
  :::note[So many "workers" ...]
172
191
  There's some ambiguity with the "worker" terminology in this tutorial. In general, there are three different kinds of Workers at play.
173
192
  - The **LiveStore web worker** (`LiveStoreWorker`); this is the Worker you defined in `livestore.worker.ts`. Technically, this is a _browser_ web worker, i.e. a separate JavaScript thread that runs in the browser, isolated from the main UI thread.
174
- - The **LiveStore shared web worker** (`LiveStoreSharedWorker`); you just imported it from `@livestore/adapter-web/shared-worker`, also a _browser_ web worker. It's actually more of an _implementation detail_ but currently required to be exposed, so that the setup works with Vite.
193
+ - The **LiveStore shared web worker** (`LiveStoreSharedWorker`); you just imported it from `@livestore/adapter-web/shared-worker`, also a _browser_ web worker. It's actually more of an _implementation detail_ but currently required to be exposed, so that the setup works with Vite.
175
194
  - The **Cloudflare Worker** that will automatically sync the data in the background; you'll set this up in the next step.
176
195
 
177
196
  Note that both the LiveStore web worker and the LiveStore Shared web worker are regular [web workers,](https://www.dhiwise.com/post/web-workers-vs-service-workers-in-javascript#what-are-web-workers-) not [service workers](https://www.dhiwise.com/post/web-workers-vs-service-workers-in-javascript#what-are-service-workers-)!
@@ -181,7 +200,7 @@ Here's how to think about the workers in the context of browser tabs (or windows
181
200
  ```
182
201
  Tab 1 ──┐
183
202
  Tab 2 ──┼──→ Shared Worker (tab coordination) ──→ Web Worker (persistence)
184
- Tab 3 ──┘
203
+ Tab 3 ──┘
185
204
  ```
186
205
 
187
206
  :::
@@ -202,7 +221,7 @@ export default defineConfig({
202
221
  })
203
222
  ```
204
223
 
205
- Now, your app is set up to start reading and writing data in a local SQLite database via LiveStore. If you run the app via `pnpm dev`, you'll briefly see a loading screen (implemented via the `renderLoading` prop on the `LiveStoreProvider`) before the todo list UI from the previous steps will appear again:
224
+ Now, your app is set up to start reading and writing data in a local SQLite database via LiveStore. If you run the app via `pnpm dev`, you'll briefly see a loading screen (the Suspense fallback) before the todo list UI from the previous steps will appear again:
206
225
 
207
226
  ![](../../../assets/tutorial/chapter-3/0-livestore-loading.gif)
208
227
 
@@ -210,16 +229,16 @@ The todos themselves are not yet persisted because you haven't modified the logi
210
229
 
211
230
  ## Read and write todos from local SQLite via LiveStore
212
231
 
213
- The current version of the app still stores the todos _in-memory_ via the [state](https://react.dev/learn/state-a-components-memory) of your `App` component. However, with the basic LiveStore setup in place, you can now move to persisting your todos inside SQLite via LiveStore!
232
+ The current version of the app still stores the todos _in-memory_ via the [state](https://react.dev/learn/state-a-components-memory) of your `<App>` component. However, with the basic LiveStore setup in place, you can now move to persisting your todos inside SQLite via LiveStore!
214
233
 
215
234
  In order to read todos, you need to define a LiveStore [query](/building-with-livestore/state/sql-queries). LiveStore queries are _live_ or _reactive_, meaning they will automatically update your UI components when the underlying data changes.
216
235
 
217
- Here's how you can define and use a query to fetch all todos from the local SQLite database using LiveStore inside the `App` component (you don't need to update your code yet, you'll get the full snippet at the end of this section):
236
+ Here's how you can define and use a query to fetch all todos from the local SQLite database using LiveStore inside the `<App>` component (you don't need to update your code yet, you'll get the full snippet at the end of this section):
218
237
 
219
238
  ```diff title="src/App.tsx" lang="ts"
220
239
  function App() {
221
240
 
222
- + const { store } = useStore()
241
+ + const store = useAppStore()
223
242
 
224
243
  // The trailing `$` is a convention to indicate that this
225
244
  // variable is a "live query".
@@ -231,7 +250,7 @@ function App() {
231
250
  + const todos = store.useQuery(todos$)
232
251
  - const [todos, setTodos] = useState<Todo[]>([])
233
252
 
234
- // ... remaining code for the `App` component
253
+ // ... remaining code for the `<App>` component
235
254
  }
236
255
  ```
237
256
 
@@ -242,13 +261,13 @@ This was only half of the job though: Right now your code would throw a type err
242
261
  ```diff title="src/App.tsx" lang="ts"
243
262
  function App() {
244
263
 
245
- const { store } = useStore()
264
+ const store = useAppStore()
246
265
 
247
266
  const todos$ = queryDb(() => tables.todos.select())
248
267
 
249
268
  const todos = store.useQuery(todos$)
250
269
 
251
- // Commit an event to the `store` instead of
270
+ // Commit an event to the `store` instead of
252
271
  // updating local React state.
253
272
  const addTodo = () => {
254
273
  + store.commit(
@@ -257,7 +276,7 @@ function App() {
257
276
  setInput('')
258
277
  }
259
278
 
260
- // Commit an event to the `store` instead of
279
+ // Commit an event to the `store` instead of
261
280
  // updating local React state.
262
281
  const deleteTodo = (id: number) => {
263
282
  + store.commit(
@@ -265,7 +284,7 @@ function App() {
265
284
  + )
266
285
  }
267
286
 
268
- // ... remaining code for the `App` component
287
+ // ... remaining code for the `<App>` component
269
288
 
270
289
  }
271
290
  ```
@@ -274,13 +293,13 @@ See how the data now will flow through the app _unidirectionally_ with this setu
274
293
 
275
294
  Let's follow it from the first time the app is started:
276
295
 
277
- 1. The `App` component registers the `todos$` "live query" with the store.
296
+ 1. The `<App>` component registers the `todos$` "live query" with the store.
278
297
  1. The query fires initially; the returned `todos` array is empty.
279
- 1. The `App` component renders an empty list.
298
+ 1. The `<App>` component renders an empty list.
280
299
  1. A user adds a `todo`; the `todoCreated` event is triggered and committed to the DB.
281
300
  1. The `v1.TodoCreated` materializer is invoked and writes the data into the DB.
282
301
  1. The `todos$` query fires again because the state of the DB changed; the returned `todos` array now contains the newly created todo.
283
- 1. The `App` component renders a single todo.
302
+ 1. The `<App>` component renders a single todo.
284
303
 
285
304
  Now try it out! Here's the full code for `App.tsx` that you can copy and paste:
286
305
 
@@ -288,7 +307,7 @@ Now try it out! Here's the full code for `App.tsx` that you can copy and paste:
288
307
 
289
308
  function App() {
290
309
 
291
- const { store } = useStore()
310
+ const store = useAppStore()
292
311
 
293
312
  const todos$ = queryDb(() => tables.todos.select())
294
313
  const todos = store.useQuery(todos$)
@@ -435,7 +454,7 @@ Here's a little GIF demonstrating the current state of the live updates via brow
435
454
 
436
455
  ![](../../../assets/tutorial/chapter-3/3-livestore-sync-local-480.gif)
437
456
 
438
- - When a change is made in one Chrome window, it is automatically reflected in the other Chrome window.
457
+ - When a change is made in one Chrome window, it is automatically reflected in the other Chrome window.
439
458
  - Similarly, when a change is made in one Safari window, it is automatically reflected in the other Safari window.
440
459
 
441
460
  To recap, here's a visualization of the data flow in the app at this point:
@@ -444,7 +463,7 @@ To recap, here's a visualization of the data flow in the app at this point:
444
463
 
445
464
  ## Set up LiveStore DevTools
446
465
 
447
- You may have wondered: "If the data is persisted, _where_ is it?". If the data is somewhere on your file system, you _should_ be able to spin up a database viewer of your choice and inspect the local SQLite DB file.
466
+ You may have wondered: "If the data is persisted, _where_ is it?". If the data is somewhere on your file system, you _should_ be able to spin up a database viewer of your choice and inspect the local SQLite DB file.
448
467
 
449
468
  Unfortunately, that's not how OPFS works. While the SQLite files do exist _somewhere_ on your file system, they are hidden in the browser's internals and not easily accessible.
450
469
 
@@ -452,7 +471,7 @@ That being said, there is a convenient way how you can actually see the data on
452
471
 
453
472
  :::note[LiveStore DevTools are a sponsor-only feature]
454
473
 
455
- Our goal is to grow the project in a [sustainable](/sustainable-open-source/sponsoring#goal-sustainable-open-source) way (e.g. not rely on VC funding), that's why DevTools are currently a [sponsor-only](/sustainable-open-source/sponsoring) feature.
474
+ Our goal is to grow the project in a [sustainable](/sustainable-open-source/sponsoring#goal-sustainable-open-source) way (e.g. not rely on VC funding), that's why DevTools are currently a [sponsor-only](/sustainable-open-source/sponsoring) feature.
456
475
 
457
476
  That being said, we still include them in this tutorial since you'll be able to use them without sponsorship for one week.
458
477
 
@@ -66,7 +66,7 @@ Next, add a `toggleTodo` function in `App.tsx` in which you're emitting the even
66
66
 
67
67
  function App() {
68
68
 
69
- const { store } = useStore()
69
+ const store = useAppStore()
70
70
 
71
71
  const todos$ = queryDb(() => tables.todos.select())
72
72
 
@@ -5,9 +5,9 @@ As you saw in the beginning of the tutorial, the state of an application is typi
5
5
  - **App state**: State that represents the _application data_ a user needs to achieve their goals with your app. In your current case, that's the list of todos. App state _typically_ lives in the Cloud somewhere (in traditional apps, the Cloud is the source of truth for it; in local-first apps, the data is stored locally and backed up in the Cloud).
6
6
  - **UI state**: UI state that is only relevant for a particular browser session.
7
7
 
8
- Many websites have the problem of "losing UI state" on browser refreshes. This can be incredibly frustrating for users, especially when they've already invested a lot of time getting to a certain point in an app (e.g. filling out a form). Then, the site reloads for some reason and they have to start over!
8
+ Many websites have the problem of "losing UI state" on browser refreshes. This can be incredibly frustrating for users, especially when they've already invested a lot of time getting to a certain point in an app (e.g. filling out a form). Then, the site reloads for some reason and they have to start over!
9
9
 
10
- With LiveStore, this problem is easily solved: It allows you to persist _UI state_ (e.g. form inputs, active tabs, custom UI elements, and pretty much anything you'd otherwise manage via `React.useState`). This means users can always pick up exactly where they left off.
10
+ With LiveStore, this problem is easily solved: It allows you to persist _UI state_ (e.g. form inputs, active tabs, custom UI elements, and pretty much anything you'd otherwise manage via `React.useState()`). This means users can always pick up exactly where they left off.
11
11
 
12
12
  ## Add another UI element
13
13
 
@@ -17,7 +17,7 @@ First, update `App.tsx` to look as follows:
17
17
 
18
18
  function App() {
19
19
 
20
- const { store } = useStore()
20
+ const store = useAppStore()
21
21
 
22
22
  const todos$ = queryDb(() => tables.todos.select())
23
23
  const todos = store.useQuery(todos$)
@@ -175,7 +175,7 @@ export const tables = {
175
175
  On this table, you define:
176
176
 
177
177
  - A name for this client document.
178
- - The structure of the client document via `schema`; in your case:
178
+ - The structure of the client document via `schema`; in your case:
179
179
  - The current state of the `input` text field for adding a new todo.
180
180
  - The `filter` that'll be used to filter the todos according to their `completed` status.
181
181
  - Default values for this client document.
@@ -209,9 +209,9 @@ Here, both the event definition and materializer are automatically derived from
209
209
 
210
210
  ## Implement local state with LiveStore
211
211
 
212
- In this step, you need to add the local state for the tabbed UI element to the `App` component. Additionally, you're going to replace the `useState` hook that you currently use for the `input` state with LiveStore's approach as well.
212
+ In this step, you need to add the local state for the tabbed UI element to the `<App>` component. Additionally, you're going to replace the `useState()` hook that you currently use for the `input` state with LiveStore's approach as well.
213
213
 
214
- Replace the `useState` usage for `input` and `filter` with LiveStore's [`useClientDocument`](/framework-integrations/react-integration#useclientdocument):
214
+ Replace the `useState()` usage for `input` and `filter` with LiveStore's [`useClientDocument()`](/framework-integrations/react-integration#storeuseclientdocumenttable-id-options):
215
215
 
216
216
  ```diff title="src/App.tsx" lang="tsx"
217
217
  +const [{ input, filter }, setUiState, , uiState$] = store.useClientDocument(tables.uiState)
@@ -224,16 +224,16 @@ Replace the `useState` usage for `input` and `filter` with LiveStore's [`useClie
224
224
  -const updatedFilter = (filter: Filter) => store.commit(events.uiStateSet({ filter }))
225
225
  ```
226
226
 
227
- Don't forget to update the imports to include the `Filter` type and drop `useState`:
227
+ Don't forget to update the imports to include the `Filter` type and drop `useState()`:
228
228
 
229
229
  ```diff title="src/App.tsx" lang="tsx"
230
230
  -import { useState } from 'react'
231
231
 
232
232
  ```
233
233
 
234
- `useClientDocument` persists the UI state inside LiveStore while giving you a React-friendly setter function similar to `useState`.
234
+ `useClientDocument()` persists the UI state inside LiveStore while giving you a React-friendly setter function similar to `useState()`.
235
235
 
236
- Since you've renamed the functions to update the values of `input` and `filter` you need to adjust the parts of the `App` component where they are used:
236
+ Since you've renamed the functions to update the values of `input` and `filter` you need to adjust the parts of the `<App>` component where they are used:
237
237
 
238
238
  - `setInput` → `updatedInput`
239
239
  - `setFilter` → `updatedFilter`
@@ -276,15 +276,15 @@ const todos$ = queryDb((
276
276
  const todos = store.useQuery(todos$)
277
277
  ```
278
278
 
279
- Here, `uiState$` comes from `useClientDocument`, ensuring that the todos query automatically reacts whenever the persisted UI state changes.
279
+ Here, `uiState$` comes from `useClientDocument()`, ensuring that the todos query automatically reacts whenever the persisted UI state changes.
280
280
 
281
- This is the final code for the `App` component:
281
+ This is the final code for the `<App>` component:
282
282
 
283
283
  ```tsx title="src/App.tsx"
284
284
 
285
285
  function App() {
286
286
 
287
- const { store } = useStore()
287
+ const store = useAppStore()
288
288
 
289
289
  const [{ input, filter }, setUiState, , uiState$] = store.useClientDocument(tables.uiState)
290
290
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/livestore",
3
- "version": "0.4.0-dev.21",
3
+ "version": "0.4.0-dev.22",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -11,17 +11,17 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@opentelemetry/api": "1.9.0",
14
- "@livestore/common": "0.4.0-dev.21",
15
- "@livestore/utils": "0.4.0-dev.21"
14
+ "@livestore/common": "0.4.0-dev.22",
15
+ "@livestore/utils": "0.4.0-dev.22"
16
16
  },
17
17
  "devDependencies": {
18
- "@opentelemetry/sdk-trace-base": "2.0.1",
18
+ "@opentelemetry/sdk-trace-base": "2.2.0",
19
19
  "jsdom": "^26.1.0",
20
20
  "typescript": "5.9.2",
21
21
  "vite": "7.2.4",
22
22
  "vitest": "3.2.4",
23
- "@livestore/adapter-web": "0.4.0-dev.21",
24
- "@livestore/utils-dev": "0.4.0-dev.21"
23
+ "@livestore/utils-dev": "0.4.0-dev.22",
24
+ "@livestore/adapter-web": "0.4.0-dev.22"
25
25
  },
26
26
  "files": [
27
27
  "package.json",