@livestore/adapter-web 0.3.0-dev.47 → 0.3.0-dev.49
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/dist/.tsbuildinfo +1 -1
- package/dist/in-memory/in-memory-adapter.d.ts +45 -3
- package/dist/in-memory/in-memory-adapter.d.ts.map +1 -1
- package/dist/in-memory/in-memory-adapter.js +139 -36
- package/dist/in-memory/in-memory-adapter.js.map +1 -1
- package/dist/web-worker/client-session/client-session-devtools.d.ts +11 -0
- package/dist/web-worker/client-session/client-session-devtools.d.ts.map +1 -1
- package/dist/web-worker/client-session/client-session-devtools.js +34 -1
- package/dist/web-worker/client-session/client-session-devtools.js.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.d.ts.map +1 -1
- package/dist/web-worker/client-session/persisted-adapter.js +13 -39
- package/dist/web-worker/client-session/persisted-adapter.js.map +1 -1
- package/dist/web-worker/common/worker-schema.d.ts +12 -11
- package/dist/web-worker/common/worker-schema.d.ts.map +1 -1
- package/dist/web-worker/common/worker-schema.js +6 -3
- package/dist/web-worker/common/worker-schema.js.map +1 -1
- package/package.json +6 -6
- package/src/in-memory/in-memory-adapter.ts +250 -39
- package/src/web-worker/client-session/client-session-devtools.ts +62 -1
- package/src/web-worker/client-session/persisted-adapter.ts +16 -60
- package/src/web-worker/common/worker-schema.ts +6 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BootStatus, Devtools, LeaderAheadError, LeaderPullCursor, MigrationsReport, SyncState, UnexpectedError, } from '@livestore/common';
|
|
2
|
-
import {
|
|
1
|
+
import { BootStatus, Devtools, LeaderAheadError, LeaderPullCursor, liveStoreVersion, MigrationsReport, SyncState, UnexpectedError, } from '@livestore/common';
|
|
2
|
+
import { EventSequenceNumber, LiveStoreEvent } from '@livestore/common/schema';
|
|
3
3
|
import * as WebmeshWorker from '@livestore/devtools-web-common/worker';
|
|
4
4
|
import { Schema, Transferable } from '@livestore/utils/effect';
|
|
5
5
|
export const StorageTypeOpfs = Schema.Struct({
|
|
@@ -106,7 +106,7 @@ export var LeaderWorkerInner;
|
|
|
106
106
|
LeaderWorkerInner.GetRecreateSnapshot = GetRecreateSnapshot;
|
|
107
107
|
class GetLeaderHead extends Schema.TaggedRequest()('GetLeaderHead', {
|
|
108
108
|
payload: {},
|
|
109
|
-
success:
|
|
109
|
+
success: EventSequenceNumber.EventSequenceNumber,
|
|
110
110
|
failure: UnexpectedError,
|
|
111
111
|
}) {
|
|
112
112
|
}
|
|
@@ -146,6 +146,9 @@ export var SharedWorker;
|
|
|
146
146
|
class InitialMessage extends Schema.TaggedRequest()('InitialMessage', {
|
|
147
147
|
payload: {
|
|
148
148
|
payload: Schema.Union(InitialMessagePayloadFromClientSession, Schema.TaggedStruct('FromWebBridge', {})),
|
|
149
|
+
// To guard against scenarios where a client session is already running a newer version of LiveStore
|
|
150
|
+
// We should probably find a better way to handle those cases once they become more common.
|
|
151
|
+
liveStoreVersion: Schema.Literal(liveStoreVersion),
|
|
149
152
|
},
|
|
150
153
|
success: Schema.Void,
|
|
151
154
|
failure: UnexpectedError,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-schema.js","sourceRoot":"","sources":["../../../src/web-worker/common/worker-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"worker-schema.js","sourceRoot":"","sources":["../../../src/web-worker/common/worker-schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/adapter-web",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.49",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@opentelemetry/api": "1.9.0",
|
|
54
|
-
"@livestore/
|
|
55
|
-
"@livestore/common": "0.3.0-dev.
|
|
56
|
-
"@livestore/sqlite-wasm": "0.3.0-dev.
|
|
57
|
-
"@livestore/utils": "0.3.0-dev.
|
|
58
|
-
"@livestore/webmesh": "0.3.0-dev.
|
|
54
|
+
"@livestore/common": "0.3.0-dev.49",
|
|
55
|
+
"@livestore/devtools-web-common": "0.3.0-dev.49",
|
|
56
|
+
"@livestore/sqlite-wasm": "0.3.0-dev.49",
|
|
57
|
+
"@livestore/utils": "0.3.0-dev.49",
|
|
58
|
+
"@livestore/webmesh": "0.3.0-dev.49"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/chrome": "^0.0.304",
|
|
@@ -1,62 +1,273 @@
|
|
|
1
|
-
import type { Adapter,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import type { Adapter, ClientSessionLeaderThreadProxy, LockStatus, SyncOptions } from '@livestore/common'
|
|
2
|
+
import { Devtools, makeClientSession, UnexpectedError } from '@livestore/common'
|
|
3
|
+
import type { DevtoolsOptions, LeaderSqliteDb } from '@livestore/common/leader-thread'
|
|
4
|
+
import { configureConnection, Eventlog, LeaderThreadCtx, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
|
|
5
|
+
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
6
|
+
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
7
|
+
import * as DevtoolsWeb from '@livestore/devtools-web-common/web-channel'
|
|
8
|
+
import type * as WebmeshWorker from '@livestore/devtools-web-common/worker'
|
|
9
|
+
import type { MakeWebSqliteDb } from '@livestore/sqlite-wasm/browser'
|
|
5
10
|
import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
|
|
6
11
|
import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
|
|
7
|
-
import {
|
|
12
|
+
import { tryAsFunctionAndNew } from '@livestore/utils'
|
|
13
|
+
import type { Schema, Scope } from '@livestore/utils/effect'
|
|
14
|
+
import { BrowserWorker, Effect, FetchHttpClient, Fiber, Layer, SubscriptionRef, Worker } from '@livestore/utils/effect'
|
|
8
15
|
import { nanoid } from '@livestore/utils/nanoid'
|
|
16
|
+
import * as Webmesh from '@livestore/webmesh'
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
import { connectWebmeshNodeClientSession } from '../web-worker/client-session/client-session-devtools.js'
|
|
19
|
+
import { makeShutdownChannel } from '../web-worker/common/shutdown-channel.js'
|
|
11
20
|
|
|
12
21
|
// NOTE we're starting to initialize the sqlite wasm binary here to speed things up
|
|
13
22
|
const sqlite3Promise = loadSqlite3Wasm()
|
|
14
23
|
|
|
15
|
-
|
|
24
|
+
export interface InMemoryAdapterOptions {
|
|
25
|
+
importSnapshot?: Uint8Array
|
|
26
|
+
sync?: SyncOptions
|
|
27
|
+
/**
|
|
28
|
+
* The client ID to use for the adapter.
|
|
29
|
+
*
|
|
30
|
+
* @default a random nanoid
|
|
31
|
+
*/
|
|
32
|
+
clientId?: string
|
|
33
|
+
/**
|
|
34
|
+
* The session ID to use for the adapter.
|
|
35
|
+
*
|
|
36
|
+
* @default a random nanoid
|
|
37
|
+
*/
|
|
38
|
+
sessionId?: string
|
|
39
|
+
// TODO make the in-memory adapter work with the browser extension
|
|
40
|
+
/** In order to use the devtools with the in-memory adapter, you need to provide the shared worker. */
|
|
41
|
+
devtools?: {
|
|
42
|
+
sharedWorker:
|
|
43
|
+
| ((options: { name: string }) => globalThis.SharedWorker)
|
|
44
|
+
| (new (options: { name: string }) => globalThis.SharedWorker)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
16
48
|
export const makeInMemoryAdapter =
|
|
17
|
-
(
|
|
18
|
-
(
|
|
19
|
-
schema,
|
|
20
|
-
shutdown,
|
|
21
|
-
// devtoolsEnabled, bootStatusQueue, shutdown, connectDevtoolsToStore
|
|
22
|
-
}) =>
|
|
49
|
+
(options: InMemoryAdapterOptions = {}): Adapter =>
|
|
50
|
+
(adapterArgs) =>
|
|
23
51
|
Effect.gen(function* () {
|
|
52
|
+
const { schema, shutdown, syncPayload, storeId, devtoolsEnabled } = adapterArgs
|
|
24
53
|
const sqlite3 = yield* Effect.promise(() => sqlite3Promise)
|
|
25
54
|
|
|
26
55
|
const sqliteDb = yield* sqliteDbFactory({ sqlite3 })({ _tag: 'in-memory' })
|
|
27
|
-
let migrationsReport: MigrationsReport = { migrations: [] }
|
|
28
56
|
|
|
29
|
-
|
|
30
|
-
|
|
57
|
+
const clientId = options.clientId ?? nanoid(6)
|
|
58
|
+
const sessionId = options.sessionId ?? nanoid(6)
|
|
59
|
+
|
|
60
|
+
const sharedWebWorker = options.devtools?.sharedWorker
|
|
61
|
+
? tryAsFunctionAndNew(options.devtools.sharedWorker, {
|
|
62
|
+
name: `livestore-shared-worker-${storeId}`,
|
|
63
|
+
})
|
|
64
|
+
: undefined
|
|
31
65
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
66
|
+
const sharedWorkerFiber = sharedWebWorker
|
|
67
|
+
? yield* Worker.makePoolSerialized<typeof WebmeshWorker.Schema.Request.Type>({
|
|
68
|
+
size: 1,
|
|
69
|
+
concurrency: 100,
|
|
70
|
+
}).pipe(
|
|
71
|
+
Effect.provide(BrowserWorker.layer(() => sharedWebWorker)),
|
|
72
|
+
Effect.tapCauseLogPretty,
|
|
73
|
+
UnexpectedError.mapToUnexpectedError,
|
|
74
|
+
Effect.forkScoped,
|
|
75
|
+
)
|
|
76
|
+
: undefined
|
|
35
77
|
|
|
36
|
-
|
|
37
|
-
|
|
78
|
+
const { leaderThread, initialSnapshot } = yield* makeLeaderThread({
|
|
79
|
+
schema,
|
|
80
|
+
storeId,
|
|
81
|
+
clientId,
|
|
82
|
+
makeSqliteDb: sqliteDbFactory({ sqlite3 }),
|
|
83
|
+
syncOptions: options.sync,
|
|
84
|
+
syncPayload,
|
|
85
|
+
importSnapshot: options.importSnapshot,
|
|
86
|
+
devtoolsEnabled,
|
|
87
|
+
sharedWorkerFiber,
|
|
88
|
+
})
|
|
38
89
|
|
|
39
|
-
|
|
90
|
+
sqliteDb.import(initialSnapshot)
|
|
40
91
|
|
|
41
|
-
const
|
|
92
|
+
const lockStatus = yield* SubscriptionRef.make<LockStatus>('has-lock')
|
|
93
|
+
|
|
94
|
+
const clientSession = yield* makeClientSession({
|
|
95
|
+
...adapterArgs,
|
|
42
96
|
sqliteDb,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
leaderThread
|
|
47
|
-
events: {
|
|
48
|
-
pull: () => Stream.never,
|
|
49
|
-
push: () => Effect.void,
|
|
50
|
-
},
|
|
51
|
-
initialState: { leaderHead: EventId.ROOT, migrationsReport },
|
|
52
|
-
export: Effect.sync(() => sqliteDb.export()),
|
|
53
|
-
getEventlogData: Effect.succeed(new Uint8Array()),
|
|
54
|
-
getSyncState: Effect.dieMessage('Not implemented'),
|
|
55
|
-
sendDevtoolsMessage: () => Effect.dieMessage('Not implemented'),
|
|
56
|
-
},
|
|
97
|
+
clientId,
|
|
98
|
+
sessionId,
|
|
99
|
+
isLeader: true,
|
|
100
|
+
leaderThread,
|
|
57
101
|
lockStatus,
|
|
58
102
|
shutdown,
|
|
59
|
-
|
|
103
|
+
webmeshMode: 'direct',
|
|
104
|
+
connectWebmeshNode: ({ sessionInfo, webmeshNode }) =>
|
|
105
|
+
Effect.gen(function* () {
|
|
106
|
+
if (sharedWorkerFiber === undefined || devtoolsEnabled === false) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const sharedWorker = yield* sharedWorkerFiber.pipe(Fiber.join)
|
|
111
|
+
|
|
112
|
+
yield* connectWebmeshNodeClientSession({ webmeshNode, sessionInfo, sharedWorker, devtoolsEnabled, schema })
|
|
113
|
+
}),
|
|
114
|
+
registerBeforeUnload: (onBeforeUnload) => {
|
|
115
|
+
if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
|
|
116
|
+
window.addEventListener('beforeunload', onBeforeUnload)
|
|
117
|
+
return () => window.removeEventListener('beforeunload', onBeforeUnload)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return () => {}
|
|
121
|
+
},
|
|
122
|
+
})
|
|
60
123
|
|
|
61
124
|
return clientSession
|
|
62
|
-
}).pipe(UnexpectedError.mapToUnexpectedError)
|
|
125
|
+
}).pipe(UnexpectedError.mapToUnexpectedError, Effect.provide(FetchHttpClient.layer))
|
|
126
|
+
|
|
127
|
+
export interface MakeLeaderThreadArgs {
|
|
128
|
+
schema: LiveStoreSchema
|
|
129
|
+
storeId: string
|
|
130
|
+
clientId: string
|
|
131
|
+
makeSqliteDb: MakeWebSqliteDb
|
|
132
|
+
syncOptions: SyncOptions | undefined
|
|
133
|
+
syncPayload: Schema.JsonValue | undefined
|
|
134
|
+
importSnapshot: Uint8Array | undefined
|
|
135
|
+
devtoolsEnabled: boolean
|
|
136
|
+
sharedWorkerFiber: SharedWorkerFiber | undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const makeLeaderThread = ({
|
|
140
|
+
schema,
|
|
141
|
+
storeId,
|
|
142
|
+
clientId,
|
|
143
|
+
makeSqliteDb,
|
|
144
|
+
syncOptions,
|
|
145
|
+
syncPayload,
|
|
146
|
+
importSnapshot,
|
|
147
|
+
devtoolsEnabled,
|
|
148
|
+
sharedWorkerFiber,
|
|
149
|
+
}: MakeLeaderThreadArgs) =>
|
|
150
|
+
Effect.gen(function* () {
|
|
151
|
+
const runtime = yield* Effect.runtime<never>()
|
|
152
|
+
|
|
153
|
+
const makeDb = (_kind: 'state' | 'eventlog') => {
|
|
154
|
+
return makeSqliteDb({
|
|
155
|
+
_tag: 'in-memory',
|
|
156
|
+
configureDb: (db) =>
|
|
157
|
+
configureConnection(db, { foreignKeys: true }).pipe(Effect.provide(runtime), Effect.runSync),
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const shutdownChannel = yield* makeShutdownChannel(storeId)
|
|
162
|
+
|
|
163
|
+
// Might involve some async work, so we're running them concurrently
|
|
164
|
+
const [dbState, dbEventlog] = yield* Effect.all([makeDb('state'), makeDb('eventlog')], { concurrency: 2 })
|
|
165
|
+
|
|
166
|
+
if (importSnapshot) {
|
|
167
|
+
dbState.import(importSnapshot)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const devtoolsOptions = yield* makeDevtoolsOptions({
|
|
171
|
+
devtoolsEnabled,
|
|
172
|
+
sharedWorkerFiber,
|
|
173
|
+
dbState,
|
|
174
|
+
dbEventlog,
|
|
175
|
+
storeId,
|
|
176
|
+
clientId,
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const layer = yield* Layer.build(
|
|
180
|
+
makeLeaderThreadLayer({
|
|
181
|
+
schema,
|
|
182
|
+
storeId,
|
|
183
|
+
clientId,
|
|
184
|
+
makeSqliteDb,
|
|
185
|
+
syncOptions,
|
|
186
|
+
dbState,
|
|
187
|
+
dbEventlog,
|
|
188
|
+
devtoolsOptions,
|
|
189
|
+
shutdownChannel,
|
|
190
|
+
syncPayload,
|
|
191
|
+
}),
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return yield* Effect.gen(function* () {
|
|
195
|
+
const { dbState, dbEventlog, syncProcessor, extraIncomingMessagesQueue, initialState } = yield* LeaderThreadCtx
|
|
196
|
+
|
|
197
|
+
const initialLeaderHead = Eventlog.getClientHeadFromDb(dbEventlog)
|
|
198
|
+
|
|
199
|
+
const leaderThread = {
|
|
200
|
+
events: {
|
|
201
|
+
pull: ({ cursor }) => syncProcessor.pull({ cursor }),
|
|
202
|
+
push: (batch) =>
|
|
203
|
+
syncProcessor.push(
|
|
204
|
+
batch.map((item) => new LiveStoreEvent.EncodedWithMeta(item)),
|
|
205
|
+
{ waitForProcessing: true },
|
|
206
|
+
),
|
|
207
|
+
},
|
|
208
|
+
initialState: { leaderHead: initialLeaderHead, migrationsReport: initialState.migrationsReport },
|
|
209
|
+
export: Effect.sync(() => dbState.export()),
|
|
210
|
+
getEventlogData: Effect.sync(() => dbEventlog.export()),
|
|
211
|
+
getSyncState: syncProcessor.syncState,
|
|
212
|
+
sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
|
|
213
|
+
} satisfies ClientSessionLeaderThreadProxy
|
|
214
|
+
|
|
215
|
+
const initialSnapshot = dbState.export()
|
|
216
|
+
|
|
217
|
+
return { leaderThread, initialSnapshot }
|
|
218
|
+
}).pipe(Effect.provide(layer))
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
type SharedWorkerFiber = Fiber.Fiber<
|
|
222
|
+
Worker.SerializedWorkerPool<typeof WebmeshWorker.Schema.Request.Type>,
|
|
223
|
+
UnexpectedError
|
|
224
|
+
>
|
|
225
|
+
|
|
226
|
+
const makeDevtoolsOptions = ({
|
|
227
|
+
devtoolsEnabled,
|
|
228
|
+
sharedWorkerFiber,
|
|
229
|
+
dbState,
|
|
230
|
+
dbEventlog,
|
|
231
|
+
storeId,
|
|
232
|
+
clientId,
|
|
233
|
+
}: {
|
|
234
|
+
devtoolsEnabled: boolean
|
|
235
|
+
sharedWorkerFiber: SharedWorkerFiber | undefined
|
|
236
|
+
dbState: LeaderSqliteDb
|
|
237
|
+
dbEventlog: LeaderSqliteDb
|
|
238
|
+
storeId: string
|
|
239
|
+
clientId: string
|
|
240
|
+
}): Effect.Effect<DevtoolsOptions, UnexpectedError, Scope.Scope> =>
|
|
241
|
+
Effect.gen(function* () {
|
|
242
|
+
if (devtoolsEnabled === false || sharedWorkerFiber === undefined) {
|
|
243
|
+
return { enabled: false }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
enabled: true,
|
|
248
|
+
boot: Effect.gen(function* () {
|
|
249
|
+
const persistenceInfo = {
|
|
250
|
+
state: dbState.metadata.persistenceInfo,
|
|
251
|
+
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const node = yield* Webmesh.makeMeshNode(Devtools.makeNodeName.client.leader({ storeId, clientId }))
|
|
255
|
+
// @ts-expect-error TODO type this
|
|
256
|
+
globalThis.__debugWebmeshNodeLeader = node
|
|
257
|
+
|
|
258
|
+
const sharedWorker = yield* sharedWorkerFiber.pipe(Fiber.join)
|
|
259
|
+
|
|
260
|
+
// TODO also make this work with the browser extension
|
|
261
|
+
// basic idea: instead of also connecting to the shared worker,
|
|
262
|
+
// connect to the client session node above which will already connect to the shared worker + browser extension
|
|
263
|
+
|
|
264
|
+
yield* DevtoolsWeb.connectViaWorker({
|
|
265
|
+
node,
|
|
266
|
+
worker: sharedWorker,
|
|
267
|
+
target: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }),
|
|
268
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
269
|
+
|
|
270
|
+
return { node, persistenceInfo, mode: 'direct' }
|
|
271
|
+
}),
|
|
272
|
+
}
|
|
273
|
+
})
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { Devtools } from '@livestore/common'
|
|
1
2
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
|
+
import * as DevtoolsWeb from '@livestore/devtools-web-common/web-channel'
|
|
2
4
|
import { isDevEnv } from '@livestore/utils'
|
|
3
|
-
import {
|
|
5
|
+
import type { Worker } from '@livestore/utils/effect'
|
|
6
|
+
import { Effect, Stream, WebChannel } from '@livestore/utils/effect'
|
|
7
|
+
import * as Webmesh from '@livestore/webmesh'
|
|
4
8
|
|
|
5
9
|
export const logDevtoolsUrl = ({
|
|
6
10
|
schema,
|
|
@@ -29,3 +33,60 @@ export const logDevtoolsUrl = ({
|
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
}).pipe(Effect.withSpan('@livestore/adapter-web:client-session:devtools:logDevtoolsUrl'))
|
|
36
|
+
|
|
37
|
+
export const connectWebmeshNodeClientSession = Effect.fn(function* ({
|
|
38
|
+
webmeshNode,
|
|
39
|
+
sessionInfo,
|
|
40
|
+
sharedWorker,
|
|
41
|
+
devtoolsEnabled,
|
|
42
|
+
schema,
|
|
43
|
+
}: {
|
|
44
|
+
webmeshNode: Webmesh.MeshNode
|
|
45
|
+
sessionInfo: Devtools.SessionInfo.SessionInfo
|
|
46
|
+
sharedWorker: Worker.SerializedWorkerPool<typeof DevtoolsWeb.WorkerSchema.Request.Type>
|
|
47
|
+
devtoolsEnabled: boolean
|
|
48
|
+
schema: LiveStoreSchema
|
|
49
|
+
}) {
|
|
50
|
+
if (devtoolsEnabled) {
|
|
51
|
+
const { clientId, sessionId, storeId } = sessionInfo
|
|
52
|
+
yield* logDevtoolsUrl({ clientId, sessionId, schema, storeId })
|
|
53
|
+
|
|
54
|
+
// This additional sessioninfo broadcast channel is needed since we can't use the shared worker
|
|
55
|
+
// as it's currently storeId-specific
|
|
56
|
+
yield* Devtools.SessionInfo.provideSessionInfo({
|
|
57
|
+
webChannel: yield* DevtoolsWeb.makeSessionInfoBroadcastChannel,
|
|
58
|
+
sessionInfo,
|
|
59
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
60
|
+
|
|
61
|
+
yield* Effect.gen(function* () {
|
|
62
|
+
const clientSessionStaticChannel = yield* DevtoolsWeb.makeStaticClientSessionChannel.clientSession
|
|
63
|
+
|
|
64
|
+
yield* clientSessionStaticChannel.send(
|
|
65
|
+
DevtoolsWeb.ClientSessionContentscriptMainReq.make({ clientId, sessionId, storeId }),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const { tabId } = yield* clientSessionStaticChannel.listen.pipe(Stream.flatten(), Stream.runHead, Effect.flatten)
|
|
69
|
+
|
|
70
|
+
const contentscriptMainNodeName = DevtoolsWeb.makeNodeName.browserExtension.contentscriptMain(tabId)
|
|
71
|
+
|
|
72
|
+
const contentscriptMainChannel = yield* WebChannel.windowChannel({
|
|
73
|
+
listenWindow: window,
|
|
74
|
+
sendWindow: window,
|
|
75
|
+
schema: Webmesh.WebmeshSchema.Packet,
|
|
76
|
+
ids: { own: webmeshNode.nodeName, other: contentscriptMainNodeName },
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
yield* webmeshNode.addEdge({ target: contentscriptMainNodeName, edgeChannel: contentscriptMainChannel })
|
|
80
|
+
}).pipe(
|
|
81
|
+
Effect.withSpan('@livestore/adapter-web:client-session:devtools:browser-extension'),
|
|
82
|
+
Effect.tapCauseLogPretty,
|
|
83
|
+
Effect.forkScoped,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
yield* DevtoolsWeb.connectViaWorker({
|
|
87
|
+
node: webmeshNode,
|
|
88
|
+
target: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }),
|
|
89
|
+
worker: sharedWorker,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Adapter, ClientSession, LockStatus } from '@livestore/common'
|
|
2
2
|
import {
|
|
3
|
-
Devtools,
|
|
4
3
|
IntentionalShutdownCause,
|
|
4
|
+
liveStoreVersion,
|
|
5
5
|
makeClientSession,
|
|
6
6
|
StoreInterrupted,
|
|
7
7
|
UnexpectedError,
|
|
@@ -9,8 +9,7 @@ import {
|
|
|
9
9
|
// TODO bring back - this currently doesn't work due to https://github.com/vitejs/vite/issues/8427
|
|
10
10
|
// NOTE We're using a non-relative import here for Vite to properly resolve the import during app builds
|
|
11
11
|
// import LiveStoreSharedWorker from '@livestore/adapter-web/internal-shared-worker?sharedworker'
|
|
12
|
-
import {
|
|
13
|
-
import * as DevtoolsWeb from '@livestore/devtools-web-common/web-channel'
|
|
12
|
+
import { EventSequenceNumber, SystemTables } from '@livestore/common/schema'
|
|
14
13
|
import { sqliteDbFactory } from '@livestore/sqlite-wasm/browser'
|
|
15
14
|
import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
|
|
16
15
|
import { isDevEnv, shouldNeverHappen, tryAsFunctionAndNew } from '@livestore/utils'
|
|
@@ -26,20 +25,18 @@ import {
|
|
|
26
25
|
Schema,
|
|
27
26
|
Stream,
|
|
28
27
|
SubscriptionRef,
|
|
29
|
-
WebChannel,
|
|
30
28
|
WebLock,
|
|
31
29
|
Worker,
|
|
32
30
|
WorkerError,
|
|
33
31
|
} from '@livestore/utils/effect'
|
|
34
32
|
import { nanoid } from '@livestore/utils/nanoid'
|
|
35
|
-
import * as Webmesh from '@livestore/webmesh'
|
|
36
33
|
|
|
37
34
|
import * as OpfsUtils from '../../opfs-utils.js'
|
|
38
35
|
import { readPersistedAppDbFromClientSession, resetPersistedDataFromClientSession } from '../common/persisted-sqlite.js'
|
|
39
36
|
import { makeShutdownChannel } from '../common/shutdown-channel.js'
|
|
40
37
|
import { DedicatedWorkerDisconnectBroadcast, makeWorkerDisconnectChannel } from '../common/worker-disconnect-channel.js'
|
|
41
38
|
import * as WorkerSchema from '../common/worker-schema.js'
|
|
42
|
-
import {
|
|
39
|
+
import { connectWebmeshNodeClientSession } from './client-session-devtools.js'
|
|
43
40
|
|
|
44
41
|
// NOTE we're starting to initialize the sqlite wasm binary here to speed things up
|
|
45
42
|
const sqlite3Promise = loadSqlite3Wasm()
|
|
@@ -161,6 +158,7 @@ export const makePersistedAdapter =
|
|
|
161
158
|
concurrency: 100,
|
|
162
159
|
initialMessage: () =>
|
|
163
160
|
new WorkerSchema.SharedWorker.InitialMessage({
|
|
161
|
+
liveStoreVersion,
|
|
164
162
|
payload: {
|
|
165
163
|
_tag: 'FromClientSession',
|
|
166
164
|
initialMessage: new WorkerSchema.LeaderWorkerInner.InitialMessage({
|
|
@@ -352,15 +350,18 @@ export const makePersistedAdapter =
|
|
|
352
350
|
// We're restoring the leader head from the SESSION_CHANGESET_META_TABLE, not from the eventlog db/table
|
|
353
351
|
// in order to avoid exporting/transferring the eventlog db/table, which is important to speed up the fast path.
|
|
354
352
|
const initialLeaderHeadRes = sqliteDb.select<{
|
|
355
|
-
|
|
356
|
-
|
|
353
|
+
seqNumGlobal: EventSequenceNumber.GlobalEventSequenceNumber
|
|
354
|
+
seqNumClient: EventSequenceNumber.ClientEventSequenceNumber
|
|
357
355
|
}>(
|
|
358
|
-
`select
|
|
356
|
+
`select seqNumGlobal, seqNumClient from ${SystemTables.SESSION_CHANGESET_META_TABLE} order by seqNumGlobal desc, seqNumClient desc limit 1`,
|
|
359
357
|
)[0]
|
|
360
358
|
|
|
361
359
|
const initialLeaderHead = initialLeaderHeadRes
|
|
362
|
-
?
|
|
363
|
-
|
|
360
|
+
? EventSequenceNumber.make({
|
|
361
|
+
global: initialLeaderHeadRes.seqNumGlobal,
|
|
362
|
+
client: initialLeaderHeadRes.seqNumClient,
|
|
363
|
+
})
|
|
364
|
+
: EventSequenceNumber.ROOT
|
|
364
365
|
|
|
365
366
|
// console.debug('[@livestore/adapter-web:client-session] initialLeaderHead', initialLeaderHead)
|
|
366
367
|
|
|
@@ -421,6 +422,8 @@ export const makePersistedAdapter =
|
|
|
421
422
|
),
|
|
422
423
|
}
|
|
423
424
|
|
|
425
|
+
const sharedWorker = yield* Fiber.join(sharedWorkerFiber)
|
|
426
|
+
|
|
424
427
|
const clientSession = yield* makeClientSession({
|
|
425
428
|
...adapterArgs,
|
|
426
429
|
sqliteDb,
|
|
@@ -431,55 +434,8 @@ export const makePersistedAdapter =
|
|
|
431
434
|
isLeader: true,
|
|
432
435
|
leaderThread,
|
|
433
436
|
webmeshMode: 'direct',
|
|
434
|
-
connectWebmeshNode:
|
|
435
|
-
|
|
436
|
-
yield* logDevtoolsUrl({ clientId, sessionId, schema, storeId })
|
|
437
|
-
|
|
438
|
-
// This additional sessioninfo broadcast channel is needed since we can't use the shared worker
|
|
439
|
-
// as it's currently storeId-specific
|
|
440
|
-
yield* Devtools.SessionInfo.provideSessionInfo({
|
|
441
|
-
webChannel: yield* DevtoolsWeb.makeSessionInfoBroadcastChannel,
|
|
442
|
-
sessionInfo,
|
|
443
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
|
|
444
|
-
|
|
445
|
-
yield* Effect.gen(function* () {
|
|
446
|
-
const clientSessionStaticChannel = yield* DevtoolsWeb.makeStaticClientSessionChannel.clientSession
|
|
447
|
-
|
|
448
|
-
yield* clientSessionStaticChannel.send(
|
|
449
|
-
DevtoolsWeb.ClientSessionContentscriptMainReq.make({ clientId, sessionId, storeId }),
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
const { tabId } = yield* clientSessionStaticChannel.listen.pipe(
|
|
453
|
-
Stream.flatten(),
|
|
454
|
-
Stream.runHead,
|
|
455
|
-
Effect.flatten,
|
|
456
|
-
)
|
|
457
|
-
|
|
458
|
-
const contentscriptMainNodeName = DevtoolsWeb.makeNodeName.browserExtension.contentscriptMain(tabId)
|
|
459
|
-
|
|
460
|
-
const contentscriptMainChannel = yield* WebChannel.windowChannel({
|
|
461
|
-
listenWindow: window,
|
|
462
|
-
sendWindow: window,
|
|
463
|
-
schema: Webmesh.WebmeshSchema.Packet,
|
|
464
|
-
ids: { own: webmeshNode.nodeName, other: contentscriptMainNodeName },
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
yield* webmeshNode.addEdge({ target: contentscriptMainNodeName, edgeChannel: contentscriptMainChannel })
|
|
468
|
-
}).pipe(
|
|
469
|
-
Effect.withSpan('@livestore/adapter-web:client-session:devtools:browser-extension'),
|
|
470
|
-
Effect.tapCauseLogPretty,
|
|
471
|
-
Effect.forkScoped,
|
|
472
|
-
)
|
|
473
|
-
|
|
474
|
-
const sharedWorker = yield* Fiber.join(sharedWorkerFiber)
|
|
475
|
-
|
|
476
|
-
yield* DevtoolsWeb.connectViaWorker({
|
|
477
|
-
node: webmeshNode,
|
|
478
|
-
target: DevtoolsWeb.makeNodeName.sharedWorker({ storeId }),
|
|
479
|
-
worker: sharedWorker,
|
|
480
|
-
})
|
|
481
|
-
}
|
|
482
|
-
}),
|
|
437
|
+
connectWebmeshNode: ({ sessionInfo, webmeshNode }) =>
|
|
438
|
+
connectWebmeshNodeClientSession({ webmeshNode, sessionInfo, sharedWorker, devtoolsEnabled, schema }),
|
|
483
439
|
registerBeforeUnload: (onBeforeUnload) => {
|
|
484
440
|
if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
|
|
485
441
|
window.addEventListener('beforeunload', onBeforeUnload)
|
|
@@ -3,11 +3,12 @@ import {
|
|
|
3
3
|
Devtools,
|
|
4
4
|
LeaderAheadError,
|
|
5
5
|
LeaderPullCursor,
|
|
6
|
+
liveStoreVersion,
|
|
6
7
|
MigrationsReport,
|
|
7
8
|
SyncState,
|
|
8
9
|
UnexpectedError,
|
|
9
10
|
} from '@livestore/common'
|
|
10
|
-
import {
|
|
11
|
+
import { EventSequenceNumber, LiveStoreEvent } from '@livestore/common/schema'
|
|
11
12
|
import * as WebmeshWorker from '@livestore/devtools-web-common/worker'
|
|
12
13
|
import { Schema, Transferable } from '@livestore/utils/effect'
|
|
13
14
|
|
|
@@ -116,7 +117,7 @@ export namespace LeaderWorkerInner {
|
|
|
116
117
|
|
|
117
118
|
export class GetLeaderHead extends Schema.TaggedRequest<GetLeaderHead>()('GetLeaderHead', {
|
|
118
119
|
payload: {},
|
|
119
|
-
success:
|
|
120
|
+
success: EventSequenceNumber.EventSequenceNumber,
|
|
120
121
|
failure: UnexpectedError,
|
|
121
122
|
}) {}
|
|
122
123
|
|
|
@@ -165,6 +166,9 @@ export namespace SharedWorker {
|
|
|
165
166
|
export class InitialMessage extends Schema.TaggedRequest<InitialMessage>()('InitialMessage', {
|
|
166
167
|
payload: {
|
|
167
168
|
payload: Schema.Union(InitialMessagePayloadFromClientSession, Schema.TaggedStruct('FromWebBridge', {})),
|
|
169
|
+
// To guard against scenarios where a client session is already running a newer version of LiveStore
|
|
170
|
+
// We should probably find a better way to handle those cases once they become more common.
|
|
171
|
+
liveStoreVersion: Schema.Literal(liveStoreVersion),
|
|
168
172
|
},
|
|
169
173
|
success: Schema.Void,
|
|
170
174
|
failure: UnexpectedError,
|