@livestore/livestore 0.4.0-dev.22 → 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.
- package/README.md +0 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/QueryCache.js +1 -1
- package/dist/QueryCache.js.map +1 -1
- package/dist/SqliteDbWrapper.d.ts +5 -5
- package/dist/SqliteDbWrapper.d.ts.map +1 -1
- package/dist/SqliteDbWrapper.js +8 -8
- package/dist/SqliteDbWrapper.js.map +1 -1
- package/dist/SqliteDbWrapper.test.js +2 -2
- package/dist/SqliteDbWrapper.test.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +14 -7
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +0 -15
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/LiveStore.test.d.ts +2 -0
- package/dist/effect/LiveStore.test.d.ts.map +1 -0
- package/dist/effect/LiveStore.test.js +42 -0
- package/dist/effect/LiveStore.test.js.map +1 -0
- package/dist/live-queries/base-class.d.ts +3 -3
- package/dist/live-queries/base-class.d.ts.map +1 -1
- package/dist/live-queries/base-class.js +2 -2
- package/dist/live-queries/base-class.js.map +1 -1
- package/dist/live-queries/client-document-get-query.d.ts +1 -1
- package/dist/live-queries/client-document-get-query.d.ts.map +1 -1
- package/dist/live-queries/client-document-get-query.js +1 -1
- package/dist/live-queries/client-document-get-query.js.map +1 -1
- package/dist/live-queries/computed.d.ts.map +1 -1
- package/dist/live-queries/computed.js +2 -2
- package/dist/live-queries/computed.js.map +1 -1
- package/dist/live-queries/db-query.js +14 -14
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +2 -2
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/live-queries/signal.test.js +2 -2
- package/dist/live-queries/signal.test.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js.map +1 -1
- package/dist/reactive.d.ts +9 -9
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +9 -26
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +2 -2
- package/dist/reactive.test.js.map +1 -1
- package/dist/store/StoreRegistry.d.ts +30 -5
- package/dist/store/StoreRegistry.d.ts.map +1 -1
- package/dist/store/StoreRegistry.js +54 -31
- package/dist/store/StoreRegistry.js.map +1 -1
- package/dist/store/StoreRegistry.test.js +251 -250
- package/dist/store/StoreRegistry.test.js.map +1 -1
- package/dist/store/create-store.d.ts +6 -2
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +13 -7
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/devtools.d.ts +1 -1
- package/dist/store/devtools.d.ts.map +1 -1
- package/dist/store/devtools.js +3 -3
- package/dist/store/devtools.js.map +1 -1
- package/dist/store/store-eventstream.test.js +2 -2
- package/dist/store/store-eventstream.test.js.map +1 -1
- package/dist/store/store-types.d.ts +70 -5
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store-types.test.js +1 -1
- package/dist/store/store-types.test.js.map +1 -1
- package/dist/store/store.d.ts +81 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +128 -45
- package/dist/store/store.js.map +1 -1
- package/dist/utils/dev.js.map +1 -1
- package/dist/utils/stack-info.js +2 -2
- package/dist/utils/stack-info.js.map +1 -1
- package/dist/utils/tests/fixture.d.ts +1 -1
- package/dist/utils/tests/fixture.d.ts.map +1 -1
- package/dist/utils/tests/fixture.js.map +1 -1
- package/dist/utils/tests/otel.d.ts.map +1 -1
- package/dist/utils/tests/otel.js +5 -5
- package/dist/utils/tests/otel.js.map +1 -1
- package/package.json +58 -17
- package/src/QueryCache.ts +1 -1
- package/src/SqliteDbWrapper.test.ts +4 -2
- package/src/SqliteDbWrapper.ts +12 -11
- package/src/ambient.d.ts +0 -7
- package/src/effect/LiveStore.test.ts +61 -0
- package/src/effect/LiveStore.ts +17 -26
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +336 -231
- package/src/live-queries/base-class.ts +7 -6
- package/src/live-queries/client-document-get-query.ts +4 -2
- package/src/live-queries/computed.ts +3 -2
- package/src/live-queries/db-query.test.ts +3 -2
- package/src/live-queries/db-query.ts +15 -15
- package/src/live-queries/signal.test.ts +3 -2
- package/src/mod.ts +1 -0
- package/src/reactive.test.ts +3 -2
- package/src/reactive.ts +22 -23
- package/src/store/StoreRegistry.test.ts +317 -293
- package/src/store/StoreRegistry.ts +63 -38
- package/src/store/create-store.ts +26 -11
- package/src/store/devtools.ts +5 -6
- package/src/store/store-eventstream.test.ts +4 -2
- package/src/store/store-types.test.ts +3 -1
- package/src/store/store-types.ts +47 -8
- package/src/store/store.ts +172 -55
- package/src/utils/dev.ts +2 -2
- package/src/utils/stack-info.ts +2 -2
- package/src/utils/tests/fixture.ts +2 -1
- package/src/utils/tests/otel.ts +8 -7
- package/docs/api/index.md +0 -3
- package/docs/building-with-livestore/complex-ui-state/index.md +0 -3
- package/docs/building-with-livestore/crud/index.md +0 -3
- package/docs/building-with-livestore/data-modeling/index.md +0 -30
- package/docs/building-with-livestore/debugging/index.md +0 -17
- package/docs/building-with-livestore/devtools/index.md +0 -79
- package/docs/building-with-livestore/events/index.md +0 -355
- package/docs/building-with-livestore/examples/ai-agent/index.md +0 -5
- package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -885
- package/docs/building-with-livestore/examples/turnbased-game/index.md +0 -7
- package/docs/building-with-livestore/opentelemetry/index.md +0 -227
- package/docs/building-with-livestore/production-checklist/index.md +0 -5
- package/docs/building-with-livestore/reactivity-system/index.md +0 -202
- package/docs/building-with-livestore/rules-for-ai-agents/index.md +0 -9
- package/docs/building-with-livestore/state/materializers/index.md +0 -300
- package/docs/building-with-livestore/state/sql-queries/index.md +0 -94
- package/docs/building-with-livestore/state/sqlite/index.md +0 -45
- package/docs/building-with-livestore/state/sqlite-schema/index.md +0 -306
- package/docs/building-with-livestore/state/sqlite-schema-effect/index.md +0 -300
- package/docs/building-with-livestore/store/index.md +0 -625
- package/docs/building-with-livestore/syncing/index.md +0 -136
- package/docs/building-with-livestore/tools/cli/index.md +0 -177
- package/docs/building-with-livestore/tools/mcp/index.md +0 -187
- package/docs/examples/cloudflare-adapter/index.md +0 -44
- package/docs/examples/expo-adapter/index.md +0 -44
- package/docs/examples/index.md +0 -55
- package/docs/examples/node-adapter/index.md +0 -44
- package/docs/examples/web-adapter/index.md +0 -52
- package/docs/framework-integrations/custom-elements/index.md +0 -142
- package/docs/framework-integrations/react-integration/index.md +0 -937
- package/docs/framework-integrations/solid-integration/index.md +0 -293
- package/docs/framework-integrations/svelte-integration/index.md +0 -42
- package/docs/framework-integrations/vue-integration/index.md +0 -294
- package/docs/getting-started/expo/index.md +0 -882
- package/docs/getting-started/node/index.md +0 -115
- package/docs/getting-started/react-web/index.md +0 -626
- package/docs/getting-started/solid/index.md +0 -3
- package/docs/getting-started/vue/index.md +0 -471
- package/docs/index.md +0 -208
- package/docs/llms.txt +0 -146
- package/docs/misc/CODE_OF_CONDUCT/index.md +0 -133
- package/docs/misc/FAQ/index.md +0 -37
- package/docs/misc/community/index.md +0 -88
- package/docs/misc/credits/index.md +0 -14
- package/docs/misc/design-partners/index.md +0 -13
- package/docs/misc/package-management/index.md +0 -21
- package/docs/misc/performance/index.md +0 -25
- package/docs/misc/resources/index.md +0 -46
- package/docs/misc/state-of-the-project/index.md +0 -37
- package/docs/misc/troubleshooting/index.md +0 -82
- package/docs/overview/concepts/index.md +0 -78
- package/docs/overview/how-livestore-works/index.md +0 -56
- package/docs/overview/introduction/index.md +0 -413
- package/docs/overview/technology-comparison/index.md +0 -40
- package/docs/overview/when-livestore/index.md +0 -81
- package/docs/overview/why-livestore/index.md +0 -111
- package/docs/patterns/ai/index.md +0 -15
- package/docs/patterns/anonymous-user-transition/index.md +0 -10
- package/docs/patterns/app-evolution/index.md +0 -72
- package/docs/patterns/auth/index.md +0 -377
- package/docs/patterns/effect/index.md +0 -1505
- package/docs/patterns/encryption/index.md +0 -6
- package/docs/patterns/external-data/index.md +0 -5
- package/docs/patterns/file-management/index.md +0 -11
- package/docs/patterns/file-structure/index.md +0 -14
- package/docs/patterns/list-ordering/index.md +0 -369
- package/docs/patterns/offline/index.md +0 -32
- package/docs/patterns/orm/index.md +0 -18
- package/docs/patterns/presence/index.md +0 -11
- package/docs/patterns/rich-text-editing/index.md +0 -11
- package/docs/patterns/server-side-clients/index.md +0 -97
- package/docs/patterns/side-effects/index.md +0 -11
- package/docs/patterns/state-machines/index.md +0 -11
- package/docs/patterns/storybook/index.md +0 -209
- package/docs/patterns/undo-redo/index.md +0 -9
- package/docs/patterns/version-control/index.md +0 -8
- package/docs/platform-adapters/cloudflare-durable-object-adapter/index.md +0 -453
- package/docs/platform-adapters/electron-adapter/index.md +0 -15
- package/docs/platform-adapters/expo-adapter/index.md +0 -262
- package/docs/platform-adapters/node-adapter/index.md +0 -160
- package/docs/platform-adapters/tauri-adapter/index.md +0 -15
- package/docs/platform-adapters/web-adapter/index.md +0 -287
- package/docs/sustainable-open-source/contributing/docs/index.md +0 -94
- package/docs/sustainable-open-source/contributing/info/index.md +0 -63
- package/docs/sustainable-open-source/contributing/monorepo/index.md +0 -195
- package/docs/sustainable-open-source/sponsoring/index.md +0 -104
- package/docs/sync-providers/cloudflare/index.md +0 -773
- package/docs/sync-providers/custom/index.md +0 -65
- package/docs/sync-providers/electricsql/index.md +0 -159
- package/docs/sync-providers/s2/index.md +0 -230
- package/docs/tutorial/0-welcome/index.md +0 -48
- package/docs/tutorial/1-setup-starter-project/index.md +0 -105
- package/docs/tutorial/2-deploy-to-cloudflare/index.md +0 -195
- package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +0 -530
- package/docs/tutorial/4-sync-data-via-cloudflare/index.md +0 -210
- package/docs/tutorial/5-expand-business-logic/index.md +0 -174
- package/docs/tutorial/6-persist-ui-state/index.md +0 -453
- package/docs/tutorial/7-next-steps/index.md +0 -22
- package/docs/understanding-livestore/design-decisions/index.md +0 -33
- package/docs/understanding-livestore/event-sourcing/index.md +0 -40
|
@@ -1,287 +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
|
-
### Private browsing mode
|
|
153
|
-
|
|
154
|
-
In Safari and Firefox private browsing mode, OPFS is not available due to browser restrictions. When this happens, LiveStore automatically falls back to in-memory storage. This means:
|
|
155
|
-
|
|
156
|
-
- The app will continue to work normally during the session
|
|
157
|
-
- Data will not persist across page reloads or tab closures
|
|
158
|
-
- Sync functionality (if configured) will still work
|
|
159
|
-
|
|
160
|
-
You can detect when the store is running in-memory mode using `store.storageMode`:
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
if (store.storageMode === 'in-memory') {
|
|
164
|
-
// Show a warning to the user
|
|
165
|
-
showToast('Data will not be saved in private browsing mode')
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
The `storageMode` property returns:
|
|
170
|
-
- `'persisted'`: Data is being persisted to disk (e.g., via OPFS)
|
|
171
|
-
- `'in-memory'`: Data is only stored in memory and will be lost on page refresh
|
|
172
|
-
|
|
173
|
-
You can also listen for boot status events including warnings using the `onBootStatus` callback in your store options:
|
|
174
|
-
|
|
175
|
-
```ts
|
|
176
|
-
const useAppStore = () => useStore({
|
|
177
|
-
storeId: 'app',
|
|
178
|
-
schema,
|
|
179
|
-
adapter,
|
|
180
|
-
batchUpdates: ReactDOM.unstable_batchedUpdates,
|
|
181
|
-
onBootStatus: (status) => {
|
|
182
|
-
if (status.stage === 'warning') {
|
|
183
|
-
console.warn(`Storage warning (${status.reason}): ${status.message}`)
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
})
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Resetting local persistence
|
|
190
|
-
|
|
191
|
-
Resetting local persistence only clears data stored in the browser and does not affect any connected sync backend.
|
|
192
|
-
|
|
193
|
-
In case you want to reset the local persistence of a client, you can provide the `resetPersistence` option to the adapter.
|
|
194
|
-
|
|
195
|
-
## `reference/platform-adapters/web-adapter/reset-persistence.ts`
|
|
196
|
-
|
|
197
|
-
```ts filename="reference/platform-adapters/web-adapter/reset-persistence.ts"
|
|
198
|
-
/** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
|
|
199
|
-
// ---cut---
|
|
200
|
-
|
|
201
|
-
const resetPersistence = import.meta.env.DEV && new URLSearchParams(window.location.search).get('reset') !== null
|
|
202
|
-
|
|
203
|
-
if (resetPersistence) {
|
|
204
|
-
const searchParams = new URLSearchParams(window.location.search)
|
|
205
|
-
searchParams.delete('reset')
|
|
206
|
-
window.history.replaceState(null, '', `${window.location.pathname}?${searchParams.toString()}`)
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const adapter = makePersistedAdapter({
|
|
210
|
-
storage: { type: 'opfs' },
|
|
211
|
-
worker: LiveStoreWorker,
|
|
212
|
-
sharedWorker: LiveStoreSharedWorker,
|
|
213
|
-
resetPersistence,
|
|
214
|
-
})
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
If you want to reset persistence manually, you can:
|
|
218
|
-
|
|
219
|
-
1. **Clear site data** in Chrome DevTools (Application tab > Storage > Clear site data)
|
|
220
|
-
2. **Use console command** if the above doesn't work due to a Chrome OPFS bug:
|
|
221
|
-
|
|
222
|
-
```javascript
|
|
223
|
-
const opfsRoot = await navigator.storage.getDirectory();
|
|
224
|
-
await opfsRoot.remove();
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Note: Only use this during development while the app is running.
|
|
228
|
-
|
|
229
|
-
## Architecture diagram
|
|
230
|
-
|
|
231
|
-
Assuming the web adapter in a multi-client, multi-tab browser application, a diagram looks like this:
|
|
232
|
-
|
|
233
|
-

|
|
234
|
-
|
|
235
|
-
## Other notes
|
|
236
|
-
|
|
237
|
-
- 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)).
|
|
238
|
-
|
|
239
|
-
## Browser support
|
|
240
|
-
|
|
241
|
-
- Notable required browser APIs: OPFS, `navigator.locks`, WASM
|
|
242
|
-
- SharedWorker is used for multi-tab synchronization but is not strictly required
|
|
243
|
-
|
|
244
|
-
### Android Chrome (Single-tab mode)
|
|
245
|
-
|
|
246
|
-
Android Chrome does not support the `SharedWorker` API ([Chromium bug #40290702](https://issues.chromium.org/issues/40290702)). When running on Android Chrome, LiveStore automatically falls back to **single-tab mode**:
|
|
247
|
-
|
|
248
|
-
- Each browser tab runs independently with its own leader worker
|
|
249
|
-
- Data is still persisted to OPFS (same as full mode)
|
|
250
|
-
- Multi-tab synchronization is not available
|
|
251
|
-
- Devtools are not supported in single-tab mode
|
|
252
|
-
- A warning is logged to the console when this fallback occurs
|
|
253
|
-
|
|
254
|
-
You can also explicitly use single-tab mode if you don't need multi-tab support:
|
|
255
|
-
|
|
256
|
-
## `reference/platform-adapters/web-adapter/single-tab.ts`
|
|
257
|
-
|
|
258
|
-
```ts filename="reference/platform-adapters/web-adapter/single-tab.ts"
|
|
259
|
-
/** biome-ignore-all lint/correctness/noUnusedVariables: docs snippet keeps inline adapter */
|
|
260
|
-
// ---cut---
|
|
261
|
-
|
|
262
|
-
// Use this only if you specifically need single-tab mode.
|
|
263
|
-
// Prefer makePersistedAdapter which auto-detects SharedWorker support.
|
|
264
|
-
const adapter = makeSingleTabAdapter({
|
|
265
|
-
worker: LiveStoreWorker,
|
|
266
|
-
storage: { type: 'opfs' },
|
|
267
|
-
})
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
:::note
|
|
271
|
-
The single-tab adapter is intended as a fallback for browsers without SharedWorker support.
|
|
272
|
-
We plan to remove it once SharedWorker is supported in Android Chrome.
|
|
273
|
-
Track progress: [LiveStore #321](https://github.com/livestorejs/livestore/issues/321)
|
|
274
|
-
:::
|
|
275
|
-
|
|
276
|
-
## Best practices
|
|
277
|
-
|
|
278
|
-
- It's recommended to develop in an incognito window to avoid issues with persistent storage (e.g. OPFS).
|
|
279
|
-
|
|
280
|
-
## FAQ
|
|
281
|
-
|
|
282
|
-
### What's the bundle size of the web adapter?
|
|
283
|
-
|
|
284
|
-
LiveStore with the web adapter adds two parts to your application bundle:
|
|
285
|
-
|
|
286
|
-
- The LiveStore JavaScript bundle (~180KB gzipped)
|
|
287
|
-
- SQLite WASM (~300KB gzipped)
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Docs
|
|
2
|
-
|
|
3
|
-
Please follow LiveStore's [guiding principles](/sustainable-open-source/contributing/info#guiding-principles) when writing docs.
|
|
4
|
-
|
|
5
|
-
## Writing style
|
|
6
|
-
|
|
7
|
-
This project broadly tries to follow the [Prisma docs style guide](https://www.prisma.io/docs/about/style-guide/writing-style).
|
|
8
|
-
|
|
9
|
-
## Use regular sentence casing for titles of navigation item, pages and sections
|
|
10
|
-
|
|
11
|
-
All titles for navigation items, pages and sections are using regular sentence casing. This means that only the first word and proper nouns (e.g. "Cloudflare Workers" or "Cloudflare Durable Objects") are capitalized.
|
|
12
|
-
|
|
13
|
-
### Example 1
|
|
14
|
-
|
|
15
|
-
Good:
|
|
16
|
-
|
|
17
|
-
```md
|
|
18
|
-
## This is the title of this section
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Bad:
|
|
22
|
-
|
|
23
|
-
```md
|
|
24
|
-
## This is the Title of this Section
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Example 2
|
|
28
|
-
|
|
29
|
-
Good:
|
|
30
|
-
|
|
31
|
-
```md
|
|
32
|
-
## This pages is about Cloudflare Workers
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Bad:
|
|
36
|
-
|
|
37
|
-
```md
|
|
38
|
-
## This pages is about cloudflare workers
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Create proper frontmatter for every page
|
|
42
|
-
|
|
43
|
-
Frontmatter is YAML metadata at the start of MD/MDX files (between `---` markers) that controls page rendering, navigation, and SEO.
|
|
44
|
-
|
|
45
|
-
### Required fields
|
|
46
|
-
|
|
47
|
-
- **`title`**: Page title used for the browser tab, search results, and page heading. Always required.
|
|
48
|
-
- **`description`**: Brief summary (150-160 characters) used for search snippets and social previews. Highly recommended for SEO.
|
|
49
|
-
|
|
50
|
-
### Optional fields
|
|
51
|
-
|
|
52
|
-
- **`sidebar`**: Controls sidebar navigation
|
|
53
|
-
- `label`: Custom sidebar label (defaults to `title`)
|
|
54
|
-
- `order`: Numeric sort order (lower numbers appear first)
|
|
55
|
-
|
|
56
|
-
### SEO impact
|
|
57
|
-
|
|
58
|
-
The `title` and `description` fields directly impact SEO:
|
|
59
|
-
- `title` becomes the `<title>` tag and search result headline
|
|
60
|
-
- `description` becomes the `<meta name="description">` tag and search snippet
|
|
61
|
-
- Both are used for Open Graph and Twitter Card previews
|
|
62
|
-
- OG images are auto-generated at `/og/{slug}.png` using these fields
|
|
63
|
-
|
|
64
|
-
### Examples
|
|
65
|
-
|
|
66
|
-
Minimal (title only):
|
|
67
|
-
```yaml
|
|
68
|
-
---
|
|
69
|
-
title: Getting started with LiveStore + React
|
|
70
|
-
---
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
With description and sidebar:
|
|
74
|
-
```yaml
|
|
75
|
-
---
|
|
76
|
-
title: Getting started with LiveStore + React
|
|
77
|
-
description: How to use LiveStore with React on the web.
|
|
78
|
-
sidebar:
|
|
79
|
-
label: React web
|
|
80
|
-
order: 1
|
|
81
|
-
---
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Snippets
|
|
85
|
-
|
|
86
|
-
For snippet guidelines, see: `/contributor-docs/docs/snippets.md`
|
|
87
|
-
|
|
88
|
-
## Deploying the docs
|
|
89
|
-
|
|
90
|
-
- Run `direnv exec . mono docs deploy` to build and deploy the documentation to the dev domain (`https://dev.docs.livestore.dev`).
|
|
91
|
-
- Passing `--prod` targets the production domain (`https://docs.livestore.dev`) when you are on `main` (otherwise the command deploys using a branch alias).
|
|
92
|
-
- Use `--site=<slug>` if you need to override the default Netlify site name.
|
|
93
|
-
- Add `--purge-cdn` when you need to invalidate Netlify's CDN cache after deploying; this ensures new edge handlers or content-negotiation changes take effect immediately.
|
|
94
|
-
- CI automatically builds and deploys the docs: `main` updates `https://docs.livestore.dev`, `dev` updates `https://dev.docs.livestore.dev`, and feature branches publish to the dev domain behind a branch alias.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# Info
|
|
2
|
-
|
|
3
|
-
## Before contributing
|
|
4
|
-
|
|
5
|
-
First of all, thank you for your interest in contributing to LiveStore! Building LiveStore has been an incredible amount of work, so everyone interested in contributing is very much appreciated. 🧡
|
|
6
|
-
|
|
7
|
-
Please note that LiveStore is still in active development with many things yet subject to change (e.g. APIs, examples, docs, etc).
|
|
8
|
-
|
|
9
|
-
Before you start contributing, please check with the maintainers if the changes you'd like to make are likely to be accepted. Please get in touch via the `#contrib` channel on [Discord](https://discord.gg/RbMcjUAPd7).
|
|
10
|
-
|
|
11
|
-
## Areas for contribution
|
|
12
|
-
|
|
13
|
-
There are many ways to contribute to LiveStore.
|
|
14
|
-
|
|
15
|
-
### Help wanted for ...
|
|
16
|
-
|
|
17
|
-
- You can look at ["help wanted" issues](https://github.com/livestorejs/livestore/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) on GitHub for ideas.
|
|
18
|
-
- [SQLite WASM build](https://github.com/livestorejs/wa-sqlite) maintainer (e.g. keeping it up to date with upstream SQLite and wa-sqlite versions)
|
|
19
|
-
- Examples maintainer (e.g. keeping dependencies & best practices up to date)
|
|
20
|
-
- Solid integration maintainer (e.g. keeping it up to date with upstream Solid versions)
|
|
21
|
-
|
|
22
|
-
### In scope and encouraged
|
|
23
|
-
|
|
24
|
-
- Documentation improvements
|
|
25
|
-
- Improving examples
|
|
26
|
-
- Test cases
|
|
27
|
-
- Bug fixes
|
|
28
|
-
- Benchmarking
|
|
29
|
-
|
|
30
|
-
### Potentially in scope
|
|
31
|
-
|
|
32
|
-
- New features
|
|
33
|
-
- Larger architectural changes in the core library
|
|
34
|
-
- Adding new examples
|
|
35
|
-
- Adding new integrations (e.g. for technologies such as Svelte, Vue, ...)
|
|
36
|
-
- Monorepo setup changes
|
|
37
|
-
- Changes to the docs site/setup
|
|
38
|
-
|
|
39
|
-
**Note:** For significant changes to public APIs or core architecture, consider writing an [RFC (Request for Comments)](https://github.com/livestorejs/livestore/tree/dev/contributor-docs/rfcs) first to gather feedback before implementation.
|
|
40
|
-
|
|
41
|
-
### Out of scope (for now)
|
|
42
|
-
|
|
43
|
-
- Changes to the landing page
|
|
44
|
-
- Changes to the devtools
|
|
45
|
-
- Rewriting the core library in a different language
|
|
46
|
-
|
|
47
|
-
### Open research questions
|
|
48
|
-
|
|
49
|
-
- Safer event schema evolution
|
|
50
|
-
- Incremental view maintenance for complex SQLite database views
|
|
51
|
-
|
|
52
|
-
Please get in touch if you'd like to discuss any of these topics!
|
|
53
|
-
|
|
54
|
-
## Bug reports
|
|
55
|
-
|
|
56
|
-
- Please include a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) for how to reproduce the bug.
|
|
57
|
-
|
|
58
|
-
## Guiding principles {#guiding-principles}
|
|
59
|
-
|
|
60
|
-
- Keep it as simple as possible
|
|
61
|
-
- Reduce surface area
|
|
62
|
-
- Make the right thing easy
|
|
63
|
-
- Document the "why"
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
# Monorepo
|
|
2
|
-
|
|
3
|
-
## Prerequisites
|
|
4
|
-
|
|
5
|
-
### Personal experience
|
|
6
|
-
|
|
7
|
-
Depending on the kind of contribution you're interested in, the following
|
|
8
|
-
experience is recommended:
|
|
9
|
-
|
|
10
|
-
- Deep experience with TypeScript (incl. type-level programming)
|
|
11
|
-
- Experience with TypeScript monorepo setups
|
|
12
|
-
- Experience with distributed systems
|
|
13
|
-
- Experience with [Effect](https://effect.website) (or willingness to learn)
|
|
14
|
-
|
|
15
|
-
### Recommended tooling: Use devenv + direnv for a consistent setup
|
|
16
|
-
|
|
17
|
-
To make development easy and consistent across systems and platforms, this
|
|
18
|
-
project uses [Nix](https://zero-to-nix.com/) with [devenv](https://devenv.sh)
|
|
19
|
-
to manage "system dependencies" such as Node.js, Bun, etc.
|
|
20
|
-
Use [direnv](https://direnv.net) (recommended) to automatically load the
|
|
21
|
-
environment, or run commands explicitly with devenv, for example:
|
|
22
|
-
`devenv shell pnpm install`.
|
|
23
|
-
|
|
24
|
-
### Manual setup
|
|
25
|
-
|
|
26
|
-
You'll need to have a recent version the following tools installed:
|
|
27
|
-
|
|
28
|
-
- Node.js
|
|
29
|
-
- Bun
|
|
30
|
-
- pnpm
|
|
31
|
-
|
|
32
|
-
## Initial setup
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
git clone git@github.com:livestorejs/livestore.git
|
|
36
|
-
cd livestore
|
|
37
|
-
# Loads env vars, installs deps and builds the project
|
|
38
|
-
./bootstrap.sh
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## General notes
|
|
42
|
-
|
|
43
|
-
- TypeScript
|
|
44
|
-
- LiveStore tries to follow the strictest TypeScript rules possible to ensure
|
|
45
|
-
type safety and avoid subtle bugs.
|
|
46
|
-
- LiveStore also makes heavy use of
|
|
47
|
-
[TypeScript project references](https://www.typescriptlang.org/docs/handbook/project-references.html).
|
|
48
|
-
- Package management
|
|
49
|
-
- This project uses [pnpm](https://pnpm.io/) to manage the workspace.
|
|
50
|
-
- LiveStore is primarily developed in VSCode/Cursor.
|
|
51
|
-
- Testing
|
|
52
|
-
- LiveStore uses Vitest for most tests and Playwright for browser tests.
|
|
53
|
-
|
|
54
|
-
### Notable used tools / technologies
|
|
55
|
-
|
|
56
|
-
- [TypeScript](https://www.typescriptlang.org/)
|
|
57
|
-
- [Effect](https://effect.website)
|
|
58
|
-
- [pnpm](https://pnpm.io/)
|
|
59
|
-
- [Bun](https://bun.sh/)
|
|
60
|
-
- [Vitest](https://vitest.dev/)
|
|
61
|
-
- [Playwright](https://playwright.dev/)
|
|
62
|
-
- [OpenTelemetry](https://opentelemetry.io/)
|
|
63
|
-
- [wa-sqlite](https://github.com/rhashimoto/wa-sqlite) (included as git subtree) - see [wa-sqlite management](../../../../../../contributor-docs/wa-sqlite-management.md)
|
|
64
|
-
- [Nix](https://zero-to-nix.com/)
|
|
65
|
-
- [Direnv](https://direnv.net/)
|
|
66
|
-
- [devenv](https://devenv.sh)
|
|
67
|
-
|
|
68
|
-
### Environment variables
|
|
69
|
-
|
|
70
|
-
The `.envrc` file contains all necessary environment variables for the project.
|
|
71
|
-
You can create a `.envrc.local` file to override or add variables for your local
|
|
72
|
-
setup. You'll need to run `direnv allow` to load the environment variables.
|
|
73
|
-
|
|
74
|
-
### VSCode tasks
|
|
75
|
-
|
|
76
|
-
- This project is primarily developed in VSCode and makes use of
|
|
77
|
-
[tasks](https://code.visualstudio.com/docs/editor/tasks) to run commands.
|
|
78
|
-
- Common tasks are:
|
|
79
|
-
- `dev:ts:watch` to run the TypeScript compiler in watch mode for the entire
|
|
80
|
-
monorepo
|
|
81
|
-
- `pnpm:install` to install all dependencies (e.g. when changing a
|
|
82
|
-
`package.json`)
|
|
83
|
-
|
|
84
|
-
## Tasks to run before committing
|
|
85
|
-
|
|
86
|
-
Please run the following tasks before committing & pushing:
|
|
87
|
-
|
|
88
|
-
- `mono ts` to build the TypeScript code
|
|
89
|
-
- `mono lint` to run the linting checks
|
|
90
|
-
- `mono test` to run the tests
|
|
91
|
-
|
|
92
|
-
## Examples
|
|
93
|
-
|
|
94
|
-
- Once you've set up the monorepo locally, you'll find all examples in the
|
|
95
|
-
`/examples` directory.
|
|
96
|
-
- All examples are self-contained and can be run independently.
|
|
97
|
-
- Examples use explicit version dependencies (e.g., `0.3.2-dev.0`) for LiveStore packages.
|
|
98
|
-
- Examples are not part of the monorepo TypeScript build system to maintain independence.
|
|
99
|
-
- Each example has its own TypeScript configuration that's independent of the
|
|
100
|
-
monorepo build system.
|
|
101
|
-
|
|
102
|
-
#### Making changes to examples
|
|
103
|
-
|
|
104
|
-
1. Make your desired changes directly in `/examples/<example-name>`.
|
|
105
|
-
2. Test your changes by running the example (e.g., `pnpm dev` in the example
|
|
106
|
-
directory).
|
|
107
|
-
3. Commit your changes.
|
|
108
|
-
|
|
109
|
-
### OpenTelemetry setup
|
|
110
|
-
|
|
111
|
-
As a local OpenTelemetry setup, we recommend the
|
|
112
|
-
[docker-otel-lgtm](https://github.com/grafana/docker-otel-lgtm) setup.
|
|
113
|
-
|
|
114
|
-
Add the following to your `.envrc.local` file:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
export VITE_GRAFANA_ENDPOINT="http://localhost:30003"
|
|
118
|
-
export GRAFANA_ENDPOINT="http://localhost:30003"
|
|
119
|
-
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
120
|
-
export VITE_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### TypeScript
|
|
124
|
-
|
|
125
|
-
- Each package has its own `tsconfig.json` file which extends the root
|
|
126
|
-
`tsconfig.base.json`.
|
|
127
|
-
- This project makes heavy use of TypeScript project references.
|
|
128
|
-
|
|
129
|
-
### Package management
|
|
130
|
-
|
|
131
|
-
- This project uses [pnpm](https://pnpm.io/) to manage the workspace.
|
|
132
|
-
- We're using the `workspace:*` protocol to link packages together.
|
|
133
|
-
- We should try to keep dependencies to an absolute minimum and only add them if
|
|
134
|
-
we absolutely need them.
|
|
135
|
-
- We also need to manually add peer dependencies for each package.
|
|
136
|
-
- We should try to avoid duplicate dependencies across the monorepo as much as
|
|
137
|
-
possible as duplicate dependencies can lead to a lot of issues and pain.
|
|
138
|
-
- We're also using the `resolutions` field in the root `package.json` to force
|
|
139
|
-
some packages to be the same across the monorepo (ideally not needed but for
|
|
140
|
-
some packages it's necessary currently).
|
|
141
|
-
- We're using [syncpack](https://github.com/JamieMason/syncpack) to help
|
|
142
|
-
maintain consistent dependency versions across the monorepo.
|
|
143
|
-
- See `syncpack.config.mjs` for the configuration.
|
|
144
|
-
- Common commands:
|
|
145
|
-
- `bunx syncpack format` to format the `package.json` files
|
|
146
|
-
- `bunx syncpack lint` to check all version ranges
|
|
147
|
-
- `bunx syncpack fix-mismatches` to adjust versions across `package.json`
|
|
148
|
-
files (check before with `lint`)
|
|
149
|
-
- `bunx syncpack update` to update packages across the monorepo to the
|
|
150
|
-
latest versions
|
|
151
|
-
|
|
152
|
-
### Notes on external dependencies
|
|
153
|
-
|
|
154
|
-
LiveStore tries to use as few external dependencies as possible. Given LiveStore
|
|
155
|
-
is built on top of Effect, which can be considered a standard library for
|
|
156
|
-
TypeScript, it should handle most use cases.
|
|
157
|
-
|
|
158
|
-
#### Notes on some packages
|
|
159
|
-
|
|
160
|
-
The following packages need to be updated with extra care:
|
|
161
|
-
|
|
162
|
-
- `react`/`react-dom` as we need to move in lockstep with Expo / React Native
|
|
163
|
-
(currently pinned to {REACT_VERSION})
|
|
164
|
-
- `effect` (currently pinned to {EFFECT_VERSION})
|
|
165
|
-
|
|
166
|
-
#### Effect
|
|
167
|
-
|
|
168
|
-
- LiveStore makes heavy use of the [Effect](https://effect.website) library and
|
|
169
|
-
ecosystem throughout the implementation of the various packages.
|
|
170
|
-
- Effect is not imposed on the app developers using LiveStore but where it makes
|
|
171
|
-
sense, LiveStore is also exposing a Effect-based API (e.g. `createStore`).
|
|
172
|
-
|
|
173
|
-
#### Updating dependencies
|
|
174
|
-
|
|
175
|
-
- Either update the versions manually in each `package.json` file or use
|
|
176
|
-
`bunx syncpack update`.
|
|
177
|
-
|
|
178
|
-
### Notes on monorepo structure
|
|
179
|
-
|
|
180
|
-
- The `@livestore/utils` package re-exports many common modules/functions (e.g.
|
|
181
|
-
from `effect`) in order to
|
|
182
|
-
- Reduce the number of direct dependencies for other packages
|
|
183
|
-
- Allows for convenient extension of modules (e.g. adding methods to
|
|
184
|
-
`Effect.___`, `Schema.___`, ...)
|
|
185
|
-
|
|
186
|
-
## Docs
|
|
187
|
-
|
|
188
|
-
The LiveStore docs are built with
|
|
189
|
-
[Astro Starlight](https://starlight.astro.build/).
|
|
190
|
-
|
|
191
|
-
## Related external repos
|
|
192
|
-
|
|
193
|
-
- [Fork of wa-sqlite](https://github.com/livestorejs/wa-sqlite) with Nix build setup included as git subtree.
|
|
194
|
-
- The source code of the devtools is currently not part of this monorepo but in
|
|
195
|
-
a separate private repo.
|