@livestore/adapter-web 0.3.0-dev.46 → 0.3.0-dev.48
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 +22 -44
- 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 +25 -70
- package/src/web-worker/common/worker-schema.ts +6 -2
|
@@ -96,13 +96,13 @@ export declare namespace LeaderWorkerInner {
|
|
|
96
96
|
batch: Schema.Array$<Schema.Struct<{
|
|
97
97
|
name: typeof Schema.String;
|
|
98
98
|
args: typeof Schema.Any;
|
|
99
|
-
|
|
100
|
-
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
101
|
-
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
99
|
+
seqNum: Schema.Struct<{
|
|
100
|
+
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
|
|
101
|
+
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"ClientEventSequenceNumber">, number, never>;
|
|
102
102
|
}>;
|
|
103
|
-
|
|
104
|
-
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
105
|
-
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
103
|
+
parentSeqNum: Schema.Struct<{
|
|
104
|
+
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
|
|
105
|
+
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"ClientEventSequenceNumber">, number, never>;
|
|
106
106
|
}>;
|
|
107
107
|
clientId: typeof Schema.String;
|
|
108
108
|
sessionId: typeof Schema.String;
|
|
@@ -115,9 +115,9 @@ export declare namespace LeaderWorkerInner {
|
|
|
115
115
|
} & {
|
|
116
116
|
cursor: Schema.Struct<{
|
|
117
117
|
mergeCounter: typeof Schema.Number;
|
|
118
|
-
|
|
119
|
-
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
120
|
-
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
118
|
+
eventNum: Schema.Struct<{
|
|
119
|
+
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
|
|
120
|
+
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"ClientEventSequenceNumber">, number, never>;
|
|
121
121
|
}>;
|
|
122
122
|
}>;
|
|
123
123
|
}, Schema.Struct<{
|
|
@@ -155,8 +155,8 @@ export declare namespace LeaderWorkerInner {
|
|
|
155
155
|
const GetLeaderHead_base: Schema.TaggedRequestClass<GetLeaderHead, "GetLeaderHead", {
|
|
156
156
|
readonly _tag: Schema.tag<"GetLeaderHead">;
|
|
157
157
|
}, Schema.Struct<{
|
|
158
|
-
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
159
|
-
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"
|
|
158
|
+
global: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
|
|
159
|
+
client: Schema.BrandSchema<number & import("effect/Brand").Brand<"ClientEventSequenceNumber">, number, never>;
|
|
160
160
|
}>, typeof UnexpectedError>;
|
|
161
161
|
export class GetLeaderHead extends GetLeaderHead_base {
|
|
162
162
|
}
|
|
@@ -209,6 +209,7 @@ export declare namespace SharedWorker {
|
|
|
209
209
|
readonly _tag: Schema.tag<"InitialMessage">;
|
|
210
210
|
} & {
|
|
211
211
|
payload: Schema.Union<[typeof InitialMessagePayloadFromClientSession, Schema.TaggedStruct<"FromWebBridge", {}>]>;
|
|
212
|
+
liveStoreVersion: Schema.Literal<["0.3.0-dev.48"]>;
|
|
212
213
|
}, typeof Schema.Void, typeof UnexpectedError>;
|
|
213
214
|
export class InitialMessage extends InitialMessage_base_2 {
|
|
214
215
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-schema.d.ts","sourceRoot":"","sources":["../../../src/web-worker/common/worker-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EACR,gBAAgB,
|
|
1
|
+
{"version":3,"file":"worker-schema.d.ts","sourceRoot":"","sources":["../../../src/web-worker/common/worker-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EACR,gBAAgB,EAIhB,SAAS,EACT,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,KAAK,aAAa,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAE,MAAM,EAAgB,MAAM,yBAAyB,CAAA;AAE9D,eAAO,MAAM,eAAe;;IAE1B;;;;;OAKG;;EAEH,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAUzD,eAAO,MAAM,WAAW;;IAnBtB;;;;;OAKG;;EAiBJ,CAAA;AACD,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AACjD,MAAM,MAAM,kBAAkB,GAAG,OAAO,WAAW,CAAC,OAAO,CAAA;AAG3D,eAAO,MAAM,kBAAkB,gGAAiE,CAAA;AAChG,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;AAEjE,yBAAiB,iBAAiB,CAAC;;;;;;;;IACjC,MAAM,OAAO,cAAe,SAAQ,mBAIlC;KAAG;;IAEL,MAAM,OAAO,OAAQ,SAAQ,YAA4B;KAAG;;CAC7D;AAGD,yBAAiB,iBAAiB,CAAC;;;;;;YAzCjC;;;;;eAKG;;;;;;;;;IAqCH,MAAM,OAAO,cAAe,SAAQ,qBAWlC;KAAG;;;;;;;;;;;;;;;;;;;;;;;;;;IAEL,MAAM,OAAO,gBAAiB,SAAQ,qBAIpC;KAAG;;;;;;;;;;;;;;;;;;;IAEL,MAAM,OAAO,YAAa,SAAQ,iBAMhC;KAAG;;;;;;;;;;;;;;;IAEL,MAAM,OAAO,UAAW,SAAQ,eAS9B;KAAG;;;;IAEL,MAAM,OAAO,MAAO,SAAQ,WAI1B;KAAG;;;;IAEL,MAAM,OAAO,cAAe,SAAQ,mBAIlC;KAAG;;;;;;;;;;;;;;;IAEL,MAAM,OAAO,mBAAoB,SAAQ,wBAOvC;KAAG;;;;;;;IAEL,MAAM,OAAO,aAAc,SAAQ,kBAIjC;KAAG;;;;IAEL,MAAM,OAAO,kBAAmB,SAAQ,uBAItC;KAAG;;;;IAEL,MAAM,OAAO,QAAS,SAAQ,aAI5B;KAAG;;;;;;;;;;;;;;;;;;;;;;;;IAEL,MAAM,OAAO,oBAAqB,SAAQ,yBAMxC;KAAG;IAEL,MAAM,CAAC,MAAM,OAAO,uTAanB,CAAA;IACD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;;CAC1C;AAED,yBAAiB,YAAY,CAAC;;;;IAC5B,MAAM,OAAO,sCAAuC,SAAQ,2CAE1D;KAAG;;;;;;;IAEL,MAAM,OAAO,cAAe,SAAQ,qBASlC;KAAG;;;;;;IAEL,MAAM,OAAO,iBAAkB,SAAQ,sBAMrC;KAAG;;IAEL,MAAM,OAAO,OAAQ,SAAQ,cAiB5B;KAAG;;CACL"}
|
|
@@ -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.48",
|
|
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/common": "0.3.0-dev.
|
|
55
|
-
"@livestore/devtools-web-common": "0.3.0-dev.
|
|
56
|
-
"@livestore/
|
|
57
|
-
"@livestore/
|
|
58
|
-
"@livestore/
|
|
54
|
+
"@livestore/common": "0.3.0-dev.48",
|
|
55
|
+
"@livestore/devtools-web-common": "0.3.0-dev.48",
|
|
56
|
+
"@livestore/utils": "0.3.0-dev.48",
|
|
57
|
+
"@livestore/sqlite-wasm": "0.3.0-dev.48",
|
|
58
|
+
"@livestore/webmesh": "0.3.0-dev.48"
|
|
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
|
+
})
|