@livestore/adapter-web 0.4.0-dev.10 → 0.4.0-dev.11

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 (28) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/in-memory/in-memory-adapter.d.ts.map +1 -1
  3. package/dist/in-memory/in-memory-adapter.js +3 -5
  4. package/dist/in-memory/in-memory-adapter.js.map +1 -1
  5. package/dist/web-worker/client-session/persisted-adapter.d.ts.map +1 -1
  6. package/dist/web-worker/client-session/persisted-adapter.js +6 -5
  7. package/dist/web-worker/client-session/persisted-adapter.js.map +1 -1
  8. package/dist/web-worker/client-session/sqlite-loader.d.ts +2 -0
  9. package/dist/web-worker/client-session/sqlite-loader.d.ts.map +1 -0
  10. package/dist/web-worker/client-session/sqlite-loader.js +16 -0
  11. package/dist/web-worker/client-session/sqlite-loader.js.map +1 -0
  12. package/dist/web-worker/common/worker-schema.d.ts +11 -6
  13. package/dist/web-worker/common/worker-schema.d.ts.map +1 -1
  14. package/dist/web-worker/common/worker-schema.js +8 -2
  15. package/dist/web-worker/common/worker-schema.js.map +1 -1
  16. package/dist/web-worker/leader-worker/make-leader-worker.js +4 -0
  17. package/dist/web-worker/leader-worker/make-leader-worker.js.map +1 -1
  18. package/dist/web-worker/shared-worker/make-shared-worker.d.ts.map +1 -1
  19. package/dist/web-worker/shared-worker/make-shared-worker.js +6 -2
  20. package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -1
  21. package/package.json +6 -6
  22. package/src/in-memory/in-memory-adapter.ts +3 -6
  23. package/src/web-worker/ambient.d.ts +7 -4
  24. package/src/web-worker/client-session/persisted-adapter.ts +9 -9
  25. package/src/web-worker/client-session/sqlite-loader.ts +19 -0
  26. package/src/web-worker/common/worker-schema.ts +11 -0
  27. package/src/web-worker/leader-worker/make-leader-worker.ts +5 -0
  28. package/src/web-worker/shared-worker/make-shared-worker.ts +31 -13
@@ -12,7 +12,6 @@ import {
12
12
  // import LiveStoreSharedWorker from '@livestore/adapter-web/internal-shared-worker?sharedworker'
13
13
  import { EventSequenceNumber } from '@livestore/common/schema'
14
14
  import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
15
- import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
16
15
  import { isDevEnv, shouldNeverHappen, tryAsFunctionAndNew } from '@livestore/utils'
17
16
  import {
18
17
  BrowserWorker,
@@ -40,9 +39,7 @@ import { makeShutdownChannel } from '../common/shutdown-channel.ts'
40
39
  import { DedicatedWorkerDisconnectBroadcast, makeWorkerDisconnectChannel } from '../common/worker-disconnect-channel.ts'
41
40
  import * as WorkerSchema from '../common/worker-schema.ts'
42
41
  import { connectWebmeshNodeClientSession } from './client-session-devtools.ts'
43
-
44
- // NOTE we're starting to initialize the sqlite wasm binary here to speed things up
45
- const sqlite3Promise = loadSqlite3Wasm()
42
+ import { loadSqlite3 } from './sqlite-loader.ts'
46
43
 
47
44
  if (isDevEnv()) {
48
45
  globalThis.__debugLiveStoreUtils = {
@@ -147,7 +144,7 @@ export const makePersistedAdapter =
147
144
 
148
145
  yield* Queue.offer(bootStatusQueue, { stage: 'loading' })
149
146
 
150
- const sqlite3 = yield* Effect.promise(() => sqlite3Promise)
147
+ const sqlite3 = yield* Effect.promise(() => loadSqlite3())
151
148
 
152
149
  const LIVESTORE_TAB_LOCK = `livestore-tab-lock-${storeId}`
153
150
  const LIVESTORE_SHARED_WORKER_TERMINATION_LOCK = `livestore-shared-worker-termination-lock-${storeId}`
@@ -463,10 +460,13 @@ export const makePersistedAdapter =
463
460
  Effect.withSpan('@livestore/adapter-web:client-session:getEventlogData'),
464
461
  ),
465
462
 
466
- getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInnerGetLeaderSyncState()).pipe(
467
- UnexpectedError.mapToUnexpectedError,
468
- Effect.withSpan('@livestore/adapter-web:client-session:getLeaderSyncState'),
469
- ),
463
+ syncState: Subscribable.make({
464
+ get: runInWorker(new WorkerSchema.LeaderWorkerInnerGetLeaderSyncState()).pipe(
465
+ UnexpectedError.mapToUnexpectedError,
466
+ Effect.withSpan('@livestore/adapter-web:client-session:getLeaderSyncState'),
467
+ ),
468
+ changes: runInWorkerStream(new WorkerSchema.LeaderWorkerInnerSyncStateStream()).pipe(Stream.orDie),
469
+ }),
470
470
 
471
471
  sendDevtoolsMessage: (message) =>
472
472
  runInWorker(new WorkerSchema.LeaderWorkerInnerExtraDevtoolsMessage({ message })).pipe(
@@ -0,0 +1,19 @@
1
+ import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
2
+
3
+ /**
4
+ * Browser sessions benefit from downloading and compiling the wasm binary as soon as
5
+ * possible to hide network and IO latency behind the rest of the boot process. We kick
6
+ * that work off eagerly on the client while still returning the shared promise.
7
+ *
8
+ * The Cloudflare / Workerd runtime has stricter rules: async fetches during module
9
+ * evaluation are blocked, so we defer loading until the worker asks for it.
10
+ */
11
+ const isServerRuntime = String(import.meta.env.SSR) === 'true'
12
+
13
+ let sqlite3Promise: ReturnType<typeof loadSqlite3Wasm> | undefined
14
+
15
+ if (isServerRuntime === false) {
16
+ sqlite3Promise = loadSqlite3Wasm()
17
+ }
18
+
19
+ export const loadSqlite3 = () => (isServerRuntime ? loadSqlite3Wasm() : (sqlite3Promise ?? loadSqlite3Wasm()))
@@ -147,6 +147,15 @@ export class LeaderWorkerInnerGetLeaderSyncState extends Schema.TaggedRequest<Le
147
147
  },
148
148
  ) {}
149
149
 
150
+ export class LeaderWorkerInnerSyncStateStream extends Schema.TaggedRequest<LeaderWorkerInnerSyncStateStream>()(
151
+ 'SyncStateStream',
152
+ {
153
+ payload: {},
154
+ success: SyncState.SyncState,
155
+ failure: UnexpectedError,
156
+ },
157
+ ) {}
158
+
150
159
  export class LeaderWorkerInnerGetNetworkStatus extends Schema.TaggedRequest<LeaderWorkerInnerGetNetworkStatus>()(
151
160
  'GetNetworkStatus',
152
161
  {
@@ -192,6 +201,7 @@ export const LeaderWorkerInnerRequest = Schema.Union(
192
201
  LeaderWorkerInnerGetRecreateSnapshot,
193
202
  LeaderWorkerInnerGetLeaderHead,
194
203
  LeaderWorkerInnerGetLeaderSyncState,
204
+ LeaderWorkerInnerSyncStateStream,
195
205
  LeaderWorkerInnerGetNetworkStatus,
196
206
  LeaderWorkerInnerNetworkStatusStream,
197
207
  LeaderWorkerInnerShutdown,
@@ -239,6 +249,7 @@ export class SharedWorkerRequest extends Schema.Union(
239
249
  LeaderWorkerInnerExportEventlog,
240
250
  LeaderWorkerInnerGetLeaderHead,
241
251
  LeaderWorkerInnerGetLeaderSyncState,
252
+ LeaderWorkerInnerSyncStateStream,
242
253
  LeaderWorkerInnerGetNetworkStatus,
243
254
  LeaderWorkerInnerNetworkStatusStream,
244
255
  LeaderWorkerInnerShutdown,
@@ -222,6 +222,11 @@ const makeWorkerRunnerInner = ({ schema, sync: syncOptions }: WorkerOptions) =>
222
222
  UnexpectedError.mapToUnexpectedError,
223
223
  Effect.withSpan('@livestore/adapter-web:worker:GetLeaderSyncState'),
224
224
  ),
225
+ SyncStateStream: () =>
226
+ Effect.gen(function* () {
227
+ const workerCtx = yield* LeaderThreadCtx
228
+ return workerCtx.syncProcessor.syncState.changes
229
+ }).pipe(Stream.unwrapScoped),
225
230
  GetNetworkStatus: () =>
226
231
  Effect.gen(function* () {
227
232
  const workerCtx = yield* LeaderThreadCtx
@@ -70,12 +70,15 @@ const makeWorkerRunner = Effect.gen(function* () {
70
70
 
71
71
  const forwardRequest = <TReq extends WorkerSchema.LeaderWorkerInnerRequest>(
72
72
  req: TReq,
73
- ): TReq extends Schema.WithResult<infer A, infer _I, infer _E, infer _EI, infer _R>
74
- ? Effect.Effect<A, UnexpectedError, never>
75
- : never =>
73
+ ): Effect.Effect<
74
+ Schema.WithResult.Success<TReq>,
75
+ UnexpectedError | Schema.WithResult.Failure<TReq>,
76
+ Schema.WithResult.Context<TReq>
77
+ > =>
78
+ // Forward the request to the active worker and normalize platform errors into UnexpectedError.
76
79
  waitForWorker.pipe(
77
80
  // Effect.logBefore(`forwardRequest: ${req._tag}`),
78
- Effect.andThen((worker) => worker.executeEffect(req) as Effect.Effect<unknown, unknown, never>),
81
+ Effect.andThen((worker) => worker.executeEffect(req) as Effect.Effect<unknown, unknown, unknown>),
79
82
  // Effect.tap((_) => Effect.log(`forwardRequest: ${req._tag}`, _)),
80
83
  // Effect.tapError((cause) => Effect.logError(`forwardRequest err: ${req._tag}`, cause)),
81
84
  Effect.interruptible,
@@ -92,17 +95,23 @@ const makeWorkerRunner = Effect.gen(function* () {
92
95
  ),
93
96
  Effect.catchAllDefect((cause) => new UnexpectedError({ cause })),
94
97
  Effect.tapCauseLogPretty,
95
- ) as any
98
+ ) as Effect.Effect<
99
+ Schema.WithResult.Success<TReq>,
100
+ UnexpectedError | Schema.WithResult.Failure<TReq>,
101
+ Schema.WithResult.Context<TReq>
102
+ >
96
103
 
97
104
  const forwardRequestStream = <TReq extends WorkerSchema.LeaderWorkerInnerRequest>(
98
105
  req: TReq,
99
- ): TReq extends Schema.WithResult<infer A, infer _I, infer _E, infer _EI, infer _R>
100
- ? Stream.Stream<A, UnexpectedError, never>
101
- : never =>
106
+ ): Stream.Stream<
107
+ Schema.WithResult.Success<TReq>,
108
+ UnexpectedError | Schema.WithResult.Failure<TReq>,
109
+ Schema.WithResult.Context<TReq>
110
+ > =>
102
111
  Effect.gen(function* () {
103
112
  yield* Effect.logDebug(`forwardRequestStream: ${req._tag}`)
104
113
  const { worker, scope } = yield* SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined)
105
- const stream = worker.execute(req) as Stream.Stream<unknown, unknown, never>
114
+ const stream = worker.execute(req) as Stream.Stream<unknown, unknown, unknown>
106
115
 
107
116
  // It seems the request stream is not automatically interrupted when the scope shuts down
108
117
  // so we need to manually interrupt it when the scope shuts down
@@ -123,7 +132,11 @@ const makeWorkerRunner = Effect.gen(function* () {
123
132
  Stream.unwrap,
124
133
  Stream.ensuring(Effect.logDebug(`shutting down stream for ${req._tag}`)),
125
134
  UnexpectedError.mapToUnexpectedErrorStream,
126
- ) as any
135
+ ) as Stream.Stream<
136
+ Schema.WithResult.Success<TReq>,
137
+ UnexpectedError | Schema.WithResult.Failure<TReq>,
138
+ Schema.WithResult.Context<TReq>
139
+ >
127
140
 
128
141
  const resetCurrentWorkerCtx = Effect.gen(function* () {
129
142
  const prevWorker = yield* SubscriptionRef.get(leaderWorkerContextSubRef)
@@ -245,6 +258,7 @@ const makeWorkerRunner = Effect.gen(function* () {
245
258
  ExportEventlog: forwardRequest,
246
259
  Setup: forwardRequest,
247
260
  GetLeaderSyncState: forwardRequest,
261
+ SyncStateStream: forwardRequestStream,
248
262
  GetLeaderHead: forwardRequest,
249
263
  GetNetworkStatus: forwardRequest,
250
264
  NetworkStatusStream: forwardRequestStream,
@@ -257,6 +271,12 @@ const makeWorkerRunner = Effect.gen(function* () {
257
271
  }).pipe(Layer.unwrapScoped)
258
272
 
259
273
  export const makeWorker = () => {
274
+ const layer = Layer.mergeAll(
275
+ Logger.prettyWithThread(self.name),
276
+ FetchHttpClient.layer,
277
+ WebmeshWorker.CacheService.layer({ nodeName: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }) }),
278
+ )
279
+
260
280
  makeWorkerRunner.pipe(
261
281
  Layer.provide(BrowserWorkerRunner.layer),
262
282
  // WorkerRunner.launch,
@@ -264,9 +284,7 @@ export const makeWorker = () => {
264
284
  Effect.scoped,
265
285
  Effect.tapCauseLogPretty,
266
286
  Effect.annotateLogs({ thread: self.name }),
267
- Effect.provide(Logger.prettyWithThread(self.name)),
268
- Effect.provide(FetchHttpClient.layer),
269
- Effect.provide(WebmeshWorker.CacheService.layer({ nodeName: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }) })),
287
+ Effect.provide(layer),
270
288
  LS_DEV ? TaskTracing.withAsyncTaggingTracing((name) => (console as any).createTask(name)) : identity,
271
289
  // TODO remove type-cast (currently needed to silence a tsc bug)
272
290
  (_) => _ as any as Effect.Effect<void, any>,