@livestore/adapter-web 0.4.0-dev.13 → 0.4.0-dev.15

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 (26) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/in-memory/in-memory-adapter.d.ts +13 -3
  3. package/dist/in-memory/in-memory-adapter.d.ts.map +1 -1
  4. package/dist/in-memory/in-memory-adapter.js +19 -5
  5. package/dist/in-memory/in-memory-adapter.js.map +1 -1
  6. package/dist/web-worker/client-session/persisted-adapter.d.ts.map +1 -1
  7. package/dist/web-worker/client-session/persisted-adapter.js +10 -2
  8. package/dist/web-worker/client-session/persisted-adapter.js.map +1 -1
  9. package/dist/web-worker/client-session/sqlite-loader.js +1 -1
  10. package/dist/web-worker/client-session/sqlite-loader.js.map +1 -1
  11. package/dist/web-worker/common/worker-schema.d.ts +5 -5
  12. package/dist/web-worker/common/worker-schema.js +1 -1
  13. package/dist/web-worker/common/worker-schema.js.map +1 -1
  14. package/dist/web-worker/leader-worker/make-leader-worker.d.ts +2 -1
  15. package/dist/web-worker/leader-worker/make-leader-worker.d.ts.map +1 -1
  16. package/dist/web-worker/leader-worker/make-leader-worker.js +4 -3
  17. package/dist/web-worker/leader-worker/make-leader-worker.js.map +1 -1
  18. package/dist/web-worker/shared-worker/make-shared-worker.js +3 -3
  19. package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -1
  20. package/package.json +6 -6
  21. package/src/in-memory/in-memory-adapter.ts +32 -7
  22. package/src/web-worker/client-session/persisted-adapter.ts +20 -2
  23. package/src/web-worker/client-session/sqlite-loader.ts +1 -1
  24. package/src/web-worker/common/worker-schema.ts +1 -1
  25. package/src/web-worker/leader-worker/make-leader-worker.ts +6 -3
  26. package/src/web-worker/shared-worker/make-shared-worker.ts +3 -3
@@ -17,8 +17,17 @@ import type * as WebmeshWorker from '@livestore/devtools-web-common/worker'
17
17
  import type { MakeWebSqliteDb } from '@livestore/sqlite-wasm/browser'
18
18
  import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
19
19
  import { tryAsFunctionAndNew } from '@livestore/utils'
20
- import type { Schema, Scope } from '@livestore/utils/effect'
21
- import { BrowserWorker, Effect, FetchHttpClient, Fiber, Layer, SubscriptionRef, Worker } from '@livestore/utils/effect'
20
+ import type { Scope } from '@livestore/utils/effect'
21
+ import {
22
+ BrowserWorker,
23
+ Effect,
24
+ FetchHttpClient,
25
+ Fiber,
26
+ Layer,
27
+ type Schema,
28
+ SubscriptionRef,
29
+ Worker,
30
+ } from '@livestore/utils/effect'
22
31
  import { nanoid } from '@livestore/utils/nanoid'
23
32
  import * as Webmesh from '@livestore/webmesh'
24
33
 
@@ -52,11 +61,21 @@ export interface InMemoryAdapterOptions {
52
61
  }
53
62
  }
54
63
 
64
+ /**
65
+ * Create a web-only in-memory LiveStore adapter.
66
+ *
67
+ * - Runs entirely in memory: fast, zero I/O, great for tests, sandboxes, or ephemeral sessions.
68
+ * - Works across browser execution contexts: Window, WebWorker, SharedWorker, and ServiceWorker.
69
+ * - DevTools: to inspect this adapter from the browser DevTools, provide a `sharedWorker` in `options.devtools`.
70
+ * (The shared worker is used to bridge the DevTools UI to the running session.)
71
+ * - No persistence support: nothing is written to OPFS/IndexedDB/localStorage. `importSnapshot`
72
+ * can bootstrap initial state only; subsequent changes are not persisted anywhere.
73
+ */
55
74
  export const makeInMemoryAdapter =
56
75
  (options: InMemoryAdapterOptions = {}): Adapter =>
57
76
  (adapterArgs) =>
58
77
  Effect.gen(function* () {
59
- const { schema, shutdown, syncPayload, storeId, devtoolsEnabled } = adapterArgs
78
+ const { schema, shutdown, syncPayloadEncoded, syncPayloadSchema, storeId, devtoolsEnabled } = adapterArgs
60
79
  const sqlite3 = yield* Effect.promise(() => loadSqlite3())
61
80
 
62
81
  const sqliteDb = yield* sqliteDbFactory({ sqlite3 })({ _tag: 'in-memory' })
@@ -88,7 +107,8 @@ export const makeInMemoryAdapter =
88
107
  clientId,
89
108
  makeSqliteDb: sqliteDbFactory({ sqlite3 }),
90
109
  syncOptions: options.sync,
91
- syncPayload,
110
+ syncPayloadEncoded,
111
+ syncPayloadSchema,
92
112
  importSnapshot: options.importSnapshot,
93
113
  devtoolsEnabled,
94
114
  sharedWorkerFiber,
@@ -108,6 +128,8 @@ export const makeInMemoryAdapter =
108
128
  lockStatus,
109
129
  shutdown,
110
130
  webmeshMode: 'direct',
131
+ // Can be undefined in Node.js
132
+ origin: globalThis.location?.origin,
111
133
  connectWebmeshNode: ({ sessionInfo, webmeshNode }) =>
112
134
  Effect.gen(function* () {
113
135
  if (sharedWorkerFiber === undefined || devtoolsEnabled === false) {
@@ -137,7 +159,8 @@ export interface MakeLeaderThreadArgs {
137
159
  clientId: string
138
160
  makeSqliteDb: MakeWebSqliteDb
139
161
  syncOptions: SyncOptions | undefined
140
- syncPayload: Schema.JsonValue | undefined
162
+ syncPayloadEncoded: Schema.JsonValue | undefined
163
+ syncPayloadSchema: Schema.Schema<any> | undefined
141
164
  importSnapshot: Uint8Array<ArrayBuffer> | undefined
142
165
  devtoolsEnabled: boolean
143
166
  sharedWorkerFiber: SharedWorkerFiber | undefined
@@ -149,7 +172,8 @@ const makeLeaderThread = ({
149
172
  clientId,
150
173
  makeSqliteDb,
151
174
  syncOptions,
152
- syncPayload,
175
+ syncPayloadEncoded,
176
+ syncPayloadSchema,
153
177
  importSnapshot,
154
178
  devtoolsEnabled,
155
179
  sharedWorkerFiber,
@@ -196,7 +220,8 @@ const makeLeaderThread = ({
196
220
  dbEventlog,
197
221
  devtoolsOptions,
198
222
  shutdownChannel,
199
- syncPayload,
223
+ syncPayloadEncoded,
224
+ syncPayloadSchema,
200
225
  }),
201
226
  )
202
227
 
@@ -138,7 +138,23 @@ export const makePersistedAdapter =
138
138
  (options: WebAdapterOptions): Adapter =>
139
139
  (adapterArgs) =>
140
140
  Effect.gen(function* () {
141
- const { schema, storeId, devtoolsEnabled, debugInstanceId, bootStatusQueue, shutdown, syncPayload } = adapterArgs
141
+ const {
142
+ schema,
143
+ storeId,
144
+ devtoolsEnabled,
145
+ debugInstanceId,
146
+ bootStatusQueue,
147
+ shutdown,
148
+ syncPayloadSchema: _syncPayloadSchema,
149
+ syncPayloadEncoded,
150
+ } = adapterArgs
151
+
152
+ // NOTE: The schema travels with the worker bundle (developers call
153
+ // `makeWorker({ schema, syncPayloadSchema })`). We only keep the
154
+ // destructured value here to document availability on the client session
155
+ // side—structured cloning the Effect schema into the worker is not
156
+ // possible, so we intentionally do not forward it.
157
+ void _syncPayloadSchema
142
158
 
143
159
  yield* ensureBrowserRequirements
144
160
 
@@ -266,7 +282,7 @@ export const makePersistedAdapter =
266
282
  clientId,
267
283
  devtoolsEnabled,
268
284
  debugInstanceId,
269
- syncPayload,
285
+ syncPayloadEncoded,
270
286
  }),
271
287
  }),
272
288
  )
@@ -490,6 +506,8 @@ export const makePersistedAdapter =
490
506
  isLeader: gotLocky,
491
507
  leaderThread,
492
508
  webmeshMode: 'direct',
509
+ // Can be undefined in Node.js
510
+ origin: globalThis.location?.origin,
493
511
  connectWebmeshNode: ({ sessionInfo, webmeshNode }) =>
494
512
  connectWebmeshNodeClientSession({ webmeshNode, sessionInfo, sharedWorker, devtoolsEnabled, schema }),
495
513
  registerBeforeUnload: (onBeforeUnload) => {
@@ -8,7 +8,7 @@ import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
8
8
  * The Cloudflare / Workerd runtime has stricter rules: async fetches during module
9
9
  * evaluation are blocked, so we defer loading until the worker asks for it.
10
10
  */
11
- const isServerRuntime = String(import.meta.env.SSR) === 'true'
11
+ const isServerRuntime = String(import.meta.env?.SSR) === 'true' || typeof window === 'undefined'
12
12
 
13
13
  let sqlite3Promise: ReturnType<typeof loadSqlite3Wasm> | undefined
14
14
 
@@ -65,7 +65,7 @@ export class LeaderWorkerInnerInitialMessage extends Schema.TaggedRequest<Leader
65
65
  storeId: Schema.String,
66
66
  clientId: Schema.String,
67
67
  debugInstanceId: Schema.String,
68
- syncPayload: Schema.UndefinedOr(Schema.JsonValue),
68
+ syncPayloadEncoded: Schema.UndefinedOr(Schema.JsonValue),
69
69
  },
70
70
  success: Schema.Void,
71
71
  failure: UnexpectedError,
@@ -19,6 +19,7 @@ import {
19
19
  LogLevel,
20
20
  OtelTracer,
21
21
  Scheduler,
22
+ type Schema,
22
23
  Stream,
23
24
  TaskTracing,
24
25
  WorkerRunner,
@@ -33,6 +34,7 @@ import * as WorkerSchema from '../common/worker-schema.ts'
33
34
  export type WorkerOptions = {
34
35
  schema: LiveStoreSchema
35
36
  sync?: SyncOptions
37
+ syncPayloadSchema?: Schema.Schema<any>
36
38
  otelOptions?: {
37
39
  tracer?: otel.Tracer
38
40
  }
@@ -102,9 +104,9 @@ const makeWorkerRunnerOuter = (
102
104
  }).pipe(Effect.withSpan('@livestore/adapter-web:worker:wrapper:InitialMessage'), Layer.unwrapScoped),
103
105
  })
104
106
 
105
- const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
107
+ const makeWorkerRunnerInner = ({ schema, sync: syncOptions, syncPayloadSchema }: WorkerOptions) =>
106
108
  WorkerRunner.layerSerialized(WorkerSchema.LeaderWorkerInnerRequest, {
107
- InitialMessage: ({ storageOptions, storeId, clientId, devtoolsEnabled, debugInstanceId, syncPayload }) =>
109
+ InitialMessage: ({ storageOptions, storeId, clientId, devtoolsEnabled, debugInstanceId, syncPayloadEncoded }) =>
108
110
  Effect.gen(function* () {
109
111
  const sqlite3 = yield* Effect.promise(() => loadSqlite3Wasm())
110
112
  const makeSqliteDb = sqliteDbFactory({ sqlite3 })
@@ -154,7 +156,8 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
154
156
  dbEventlog,
155
157
  devtoolsOptions,
156
158
  shutdownChannel,
157
- syncPayload,
159
+ syncPayloadEncoded,
160
+ syncPayloadSchema,
158
161
  })
159
162
  }).pipe(
160
163
  Effect.tapCauseLogPretty,
@@ -163,7 +163,7 @@ const makeWorkerRunner = Effect.gen(function* () {
163
163
  const InvariantsSchema = Schema.Struct({
164
164
  storeId: Schema.String,
165
165
  storageOptions: WorkerSchema.StorageType,
166
- syncPayload: Schema.UndefinedOr(Schema.JsonValue),
166
+ syncPayloadEncoded: Schema.UndefinedOr(Schema.JsonValue),
167
167
  liveStoreVersion: Schema.Literal(liveStoreVersion),
168
168
  devtoolsEnabled: Schema.Boolean,
169
169
  })
@@ -176,11 +176,11 @@ const makeWorkerRunner = Effect.gen(function* () {
176
176
  // sends a new MessagePort to the shared worker which proxies messages to the new leader thread.
177
177
  UpdateMessagePort: ({ port, initial, liveStoreVersion: clientLiveStoreVersion }) =>
178
178
  Effect.gen(function* () {
179
- // Enforce invariants: storeId, storageOptions, syncPayload, liveStoreVersion must remain stable
179
+ // Enforce invariants: storeId, storageOptions, syncPayloadEncoded, liveStoreVersion must remain stable
180
180
  const invariants: Invariants = {
181
181
  storeId: initial.storeId,
182
182
  storageOptions: initial.storageOptions,
183
- syncPayload: initial.syncPayload,
183
+ syncPayloadEncoded: initial.syncPayloadEncoded,
184
184
  liveStoreVersion: clientLiveStoreVersion,
185
185
  devtoolsEnabled: initial.devtoolsEnabled,
186
186
  }