@livestore/adapter-node 0.3.1 → 0.3.2-dev.1
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/client-session/adapter.d.ts +4 -4
- package/dist/client-session/adapter.d.ts.map +1 -1
- package/dist/client-session/adapter.js +22 -28
- package/dist/client-session/adapter.js.map +1 -1
- package/dist/devtools/devtools-server.d.ts +1 -1
- package/dist/devtools/devtools-server.d.ts.map +1 -1
- package/dist/devtools/devtools-server.js +6 -4
- package/dist/devtools/devtools-server.js.map +1 -1
- package/dist/devtools/mod.d.ts +3 -3
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +2 -2
- package/dist/devtools/mod.js.map +1 -1
- package/dist/devtools/vite-dev-server.d.ts +1 -1
- package/dist/devtools/vite-dev-server.d.ts.map +1 -1
- package/dist/devtools/vite-dev-server.js +4 -1
- package/dist/devtools/vite-dev-server.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/leader-thread-lazy.js +1 -1
- package/dist/leader-thread-shared.d.ts +7 -6
- package/dist/leader-thread-shared.d.ts.map +1 -1
- package/dist/leader-thread-shared.js +6 -4
- package/dist/leader-thread-shared.js.map +1 -1
- package/dist/make-leader-worker.d.ts +2 -2
- package/dist/make-leader-worker.d.ts.map +1 -1
- package/dist/make-leader-worker.js +10 -6
- package/dist/make-leader-worker.js.map +1 -1
- package/dist/shutdown-channel.d.ts +1 -1
- package/dist/shutdown-channel.d.ts.map +1 -1
- package/dist/shutdown-channel.js +1 -1
- package/dist/webchannel.d.ts.map +1 -1
- package/dist/webchannel.js +0 -1
- package/dist/webchannel.js.map +1 -1
- package/dist/worker-schema.d.ts +166 -171
- package/dist/worker-schema.d.ts.map +1 -1
- package/dist/worker-schema.js +100 -120
- package/dist/worker-schema.js.map +1 -1
- package/package.json +8 -7
- package/src/client-session/adapter.ts +75 -85
- package/src/devtools/devtools-server.ts +7 -5
- package/src/devtools/mod.ts +3 -3
- package/src/devtools/vite-dev-server.ts +5 -2
- package/src/index.ts +1 -1
- package/src/leader-thread-lazy.ts +1 -1
- package/src/leader-thread-shared.ts +19 -11
- package/src/make-leader-worker.ts +12 -7
- package/src/shutdown-channel.ts +1 -1
- package/src/webchannel.ts +1 -2
- package/src/worker-schema.ts +86 -72
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-schema.js","sourceRoot":"","sources":["../src/worker-schema.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"worker-schema.js","sourceRoot":"","sources":["../src/worker-schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/adapter-node",
|
|
3
|
-
"version": "0.3.1",
|
|
3
|
+
"version": "0.3.2-dev.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"bun": "./src/index.ts",
|
|
9
10
|
"default": "./dist/index.js"
|
|
10
11
|
},
|
|
11
12
|
"./devtools": {
|
|
@@ -26,13 +27,13 @@
|
|
|
26
27
|
}
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@livestore/devtools-vite": "0.3.1",
|
|
30
|
+
"@livestore/devtools-vite": "0.3.2-dev.1",
|
|
30
31
|
"@opentelemetry/api": "1.9.0",
|
|
31
|
-
"vite": "
|
|
32
|
-
"@livestore/
|
|
33
|
-
"@livestore/
|
|
34
|
-
"@livestore/
|
|
35
|
-
"@livestore/
|
|
32
|
+
"vite": "7.0.0",
|
|
33
|
+
"@livestore/common": "0.3.2-dev.1",
|
|
34
|
+
"@livestore/sqlite-wasm": "0.3.2-dev.1",
|
|
35
|
+
"@livestore/webmesh": "0.3.2-dev.1",
|
|
36
|
+
"@livestore/utils": "0.3.2-dev.1"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@rollup/plugin-commonjs": "^28.0.3",
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { hostname } from 'node:os'
|
|
2
2
|
import * as WT from 'node:worker_threads'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
BootStatus,
|
|
3
|
+
import {
|
|
4
|
+
type Adapter,
|
|
5
|
+
type BootStatus,
|
|
7
6
|
ClientSessionLeaderThreadProxy,
|
|
8
|
-
IntentionalShutdownCause,
|
|
9
|
-
LockStatus,
|
|
10
|
-
MakeSqliteDb,
|
|
11
|
-
|
|
7
|
+
type IntentionalShutdownCause,
|
|
8
|
+
type LockStatus,
|
|
9
|
+
type MakeSqliteDb,
|
|
10
|
+
makeClientSession,
|
|
11
|
+
type SyncOptions,
|
|
12
|
+
UnexpectedError,
|
|
12
13
|
} from '@livestore/common'
|
|
13
|
-
import { makeClientSession, UnexpectedError } from '@livestore/common'
|
|
14
14
|
import { Eventlog, LeaderThreadCtx } from '@livestore/common/leader-thread'
|
|
15
15
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
16
16
|
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
@@ -33,10 +33,10 @@ import {
|
|
|
33
33
|
import { PlatformNode } from '@livestore/utils/node'
|
|
34
34
|
import * as Webmesh from '@livestore/webmesh'
|
|
35
35
|
|
|
36
|
-
import type { TestingOverrides } from '../leader-thread-shared.
|
|
37
|
-
import { makeLeaderThread } from '../leader-thread-shared.
|
|
38
|
-
import { makeShutdownChannel } from '../shutdown-channel.
|
|
39
|
-
import * as WorkerSchema from '../worker-schema.
|
|
36
|
+
import type { TestingOverrides } from '../leader-thread-shared.ts'
|
|
37
|
+
import { makeLeaderThread } from '../leader-thread-shared.ts'
|
|
38
|
+
import { makeShutdownChannel } from '../shutdown-channel.ts'
|
|
39
|
+
import * as WorkerSchema from '../worker-schema.ts'
|
|
40
40
|
|
|
41
41
|
export interface NodeAdapterOptions {
|
|
42
42
|
storage: WorkerSchema.StorageType
|
|
@@ -90,7 +90,7 @@ export const makeWorkerAdapter = ({
|
|
|
90
90
|
...options
|
|
91
91
|
}: NodeAdapterOptions & {
|
|
92
92
|
/**
|
|
93
|
-
* Example: `new URL('./livestore.worker.
|
|
93
|
+
* Example: `new URL('./livestore.worker.ts', import.meta.url)`
|
|
94
94
|
*/
|
|
95
95
|
workerUrl: URL
|
|
96
96
|
}): Adapter => makeAdapterImpl({ ...options, leaderThread: { _tag: 'multi-threaded', workerUrl } })
|
|
@@ -147,7 +147,7 @@ const makeAdapterImpl = ({
|
|
|
147
147
|
// TODO actually implement this multi-session support
|
|
148
148
|
const lockStatus = yield* SubscriptionRef.make<LockStatus>('has-lock')
|
|
149
149
|
|
|
150
|
-
const devtoolsOptions: WorkerSchema.
|
|
150
|
+
const devtoolsOptions: WorkerSchema.LeaderWorkerInnerInitialMessage['devtools'] =
|
|
151
151
|
devtoolsEnabled && devtoolsOptionsInput !== undefined
|
|
152
152
|
? {
|
|
153
153
|
enabled: true,
|
|
@@ -188,6 +188,7 @@ const makeAdapterImpl = ({
|
|
|
188
188
|
})
|
|
189
189
|
|
|
190
190
|
syncInMemoryDb.import(initialSnapshot)
|
|
191
|
+
syncInMemoryDb.debug.head = leaderThread.initialState.leaderHead
|
|
191
192
|
|
|
192
193
|
const clientSession = yield* makeClientSession({
|
|
193
194
|
...adapterArgs,
|
|
@@ -214,7 +215,6 @@ const makeAdapterImpl = ({
|
|
|
214
215
|
return clientSession
|
|
215
216
|
}).pipe(
|
|
216
217
|
Effect.withSpan('@livestore/adapter-node:adapter'),
|
|
217
|
-
Effect.parallelFinalizers,
|
|
218
218
|
Effect.provide(PlatformNode.NodeFileSystem.layer),
|
|
219
219
|
Effect.provide(FetchHttpClient.layer),
|
|
220
220
|
)) satisfies Adapter
|
|
@@ -237,7 +237,7 @@ const makeLocalLeaderThread = ({
|
|
|
237
237
|
syncOptions: SyncOptions | undefined
|
|
238
238
|
storage: WorkerSchema.StorageType
|
|
239
239
|
syncPayload: Schema.JsonValue | undefined
|
|
240
|
-
devtools: WorkerSchema.
|
|
240
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessage['devtools']
|
|
241
241
|
testing?: {
|
|
242
242
|
overrides?: TestingOverrides
|
|
243
243
|
}
|
|
@@ -262,23 +262,24 @@ const makeLocalLeaderThread = ({
|
|
|
262
262
|
|
|
263
263
|
const initialLeaderHead = Eventlog.getClientHeadFromDb(dbEventlog)
|
|
264
264
|
|
|
265
|
-
const leaderThread =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
265
|
+
const leaderThread = ClientSessionLeaderThreadProxy.of(
|
|
266
|
+
{
|
|
267
|
+
events: {
|
|
268
|
+
pull: ({ cursor }) => syncProcessor.pull({ cursor }),
|
|
269
|
+
push: (batch) =>
|
|
270
|
+
syncProcessor.push(
|
|
271
|
+
batch.map((item) => new LiveStoreEvent.EncodedWithMeta(item)),
|
|
272
|
+
{ waitForProcessing: true },
|
|
273
|
+
),
|
|
274
|
+
},
|
|
275
|
+
initialState: { leaderHead: initialLeaderHead, migrationsReport: initialState.migrationsReport },
|
|
276
|
+
export: Effect.sync(() => dbState.export()),
|
|
277
|
+
getEventlogData: Effect.sync(() => dbEventlog.export()),
|
|
278
|
+
getSyncState: syncProcessor.syncState,
|
|
279
|
+
sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
|
|
275
280
|
},
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
getEventlogData: Effect.sync(() => dbEventlog.export()),
|
|
279
|
-
getSyncState: syncProcessor.syncState,
|
|
280
|
-
sendDevtoolsMessage: (message) => extraIncomingMessagesQueue.offer(message),
|
|
281
|
-
} satisfies ClientSessionLeaderThreadProxy
|
|
281
|
+
{ overrides: testing?.overrides?.clientSession?.leaderThreadProxy },
|
|
282
|
+
)
|
|
282
283
|
|
|
283
284
|
const initialSnapshot = dbState.export()
|
|
284
285
|
|
|
@@ -304,7 +305,7 @@ const makeWorkerLeaderThread = ({
|
|
|
304
305
|
sessionId: string
|
|
305
306
|
workerUrl: URL
|
|
306
307
|
storage: WorkerSchema.StorageType
|
|
307
|
-
devtools: WorkerSchema.
|
|
308
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessage['devtools']
|
|
308
309
|
bootStatusQueue: Queue.Queue<BootStatus>
|
|
309
310
|
syncPayload: Schema.JsonValue | undefined
|
|
310
311
|
testing?: {
|
|
@@ -318,11 +319,11 @@ const makeWorkerLeaderThread = ({
|
|
|
318
319
|
})
|
|
319
320
|
const nodeWorkerLayer = yield* Layer.build(PlatformNode.NodeWorker.layer(() => nodeWorker))
|
|
320
321
|
|
|
321
|
-
const worker = yield* Worker.makePoolSerialized<typeof WorkerSchema.
|
|
322
|
+
const worker = yield* Worker.makePoolSerialized<typeof WorkerSchema.LeaderWorkerInnerRequest.Type>({
|
|
322
323
|
size: 1,
|
|
323
324
|
concurrency: 100,
|
|
324
325
|
initialMessage: () =>
|
|
325
|
-
new WorkerSchema.
|
|
326
|
+
new WorkerSchema.LeaderWorkerInnerInitialMessage({
|
|
326
327
|
storeId,
|
|
327
328
|
clientId,
|
|
328
329
|
storage,
|
|
@@ -336,21 +337,7 @@ const makeWorkerLeaderThread = ({
|
|
|
336
337
|
Effect.withSpan('@livestore/adapter-node:adapter:setupLeaderThread'),
|
|
337
338
|
)
|
|
338
339
|
|
|
339
|
-
|
|
340
|
-
Effect.gen(function* () {
|
|
341
|
-
// We first try to gracefully shutdown the leader worker and then forcefully terminate it
|
|
342
|
-
yield* Effect.raceFirst(
|
|
343
|
-
runInWorker(new WorkerSchema.LeaderWorkerInner.Shutdown()).pipe(Effect.andThen(() => nodeWorker.terminate())),
|
|
344
|
-
|
|
345
|
-
Effect.sync(() => {
|
|
346
|
-
console.warn('[@livestore/adapter-node:adapter] Worker did not gracefully shutdown in time, terminating it')
|
|
347
|
-
nodeWorker.terminate()
|
|
348
|
-
}).pipe(Effect.delay(1000)),
|
|
349
|
-
).pipe(Effect.exit) // The disconnect is to prevent the interrupt to bubble out
|
|
350
|
-
}).pipe(Effect.withSpan('@livestore/adapter-node:adapter:shutdown'), Effect.tapCauseLogPretty, Effect.orDie),
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
const runInWorker = <TReq extends typeof WorkerSchema.LeaderWorkerInner.Request.Type>(
|
|
340
|
+
const runInWorker = <TReq extends typeof WorkerSchema.LeaderWorkerInnerRequest.Type>(
|
|
354
341
|
req: TReq,
|
|
355
342
|
): TReq extends Schema.WithResult<infer A, infer _I, infer _E, infer _EI, infer R>
|
|
356
343
|
? Effect.Effect<A, UnexpectedError, R>
|
|
@@ -371,7 +358,7 @@ const makeWorkerLeaderThread = ({
|
|
|
371
358
|
Effect.catchAllDefect((cause) => new UnexpectedError({ cause })),
|
|
372
359
|
) as any
|
|
373
360
|
|
|
374
|
-
const runInWorkerStream = <TReq extends typeof WorkerSchema.
|
|
361
|
+
const runInWorkerStream = <TReq extends typeof WorkerSchema.LeaderWorkerInnerRequest.Type>(
|
|
375
362
|
req: TReq,
|
|
376
363
|
): TReq extends Schema.WithResult<infer A, infer _I, infer _E, infer _EI, infer R>
|
|
377
364
|
? Stream.Stream<A, UnexpectedError, R>
|
|
@@ -387,7 +374,7 @@ const makeWorkerLeaderThread = ({
|
|
|
387
374
|
Stream.withSpan(`@livestore/adapter-node:client-session:runInWorkerStream:${req._tag}`),
|
|
388
375
|
) as any
|
|
389
376
|
|
|
390
|
-
const bootStatusFiber = yield* runInWorkerStream(new WorkerSchema.
|
|
377
|
+
const bootStatusFiber = yield* runInWorkerStream(new WorkerSchema.LeaderWorkerInnerBootStatusStream()).pipe(
|
|
391
378
|
Stream.tap((bootStatus) => Queue.offer(bootStatusQueue, bootStatus)),
|
|
392
379
|
Stream.runDrain,
|
|
393
380
|
Effect.tapErrorCause((cause) => (Cause.isInterruptedOnly(cause) ? Effect.void : shutdown(cause))),
|
|
@@ -402,47 +389,50 @@ const makeWorkerLeaderThread = ({
|
|
|
402
389
|
Effect.forkScoped,
|
|
403
390
|
)
|
|
404
391
|
|
|
405
|
-
const initialLeaderHead = yield* runInWorker(new WorkerSchema.
|
|
392
|
+
const initialLeaderHead = yield* runInWorker(new WorkerSchema.LeaderWorkerInnerGetLeaderHead())
|
|
406
393
|
|
|
407
|
-
const bootResult = yield* runInWorker(new WorkerSchema.
|
|
394
|
+
const bootResult = yield* runInWorker(new WorkerSchema.LeaderWorkerInnerGetRecreateSnapshot()).pipe(
|
|
408
395
|
Effect.timeout(10_000),
|
|
409
396
|
UnexpectedError.mapToUnexpectedError,
|
|
410
397
|
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
411
398
|
)
|
|
412
399
|
|
|
413
|
-
const leaderThread =
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
400
|
+
const leaderThread = ClientSessionLeaderThreadProxy.of(
|
|
401
|
+
{
|
|
402
|
+
events: {
|
|
403
|
+
pull: ({ cursor }) =>
|
|
404
|
+
runInWorkerStream(new WorkerSchema.LeaderWorkerInnerPullStream({ cursor })).pipe(Stream.orDie),
|
|
405
|
+
push: (batch) =>
|
|
406
|
+
runInWorker(new WorkerSchema.LeaderWorkerInnerPushToLeader({ batch })).pipe(
|
|
407
|
+
Effect.withSpan('@livestore/adapter-node:client-session:pushToLeader', {
|
|
408
|
+
attributes: { batchSize: batch.length },
|
|
409
|
+
}),
|
|
410
|
+
),
|
|
411
|
+
},
|
|
412
|
+
initialState: {
|
|
413
|
+
leaderHead: initialLeaderHead,
|
|
414
|
+
migrationsReport: bootResult.migrationsReport,
|
|
415
|
+
},
|
|
416
|
+
export: runInWorker(new WorkerSchema.LeaderWorkerInnerExport()).pipe(
|
|
417
|
+
Effect.timeout(10_000),
|
|
418
|
+
UnexpectedError.mapToUnexpectedError,
|
|
419
|
+
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
420
|
+
),
|
|
421
|
+
getEventlogData: Effect.dieMessage('Not implemented'),
|
|
422
|
+
getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInnerGetLeaderSyncState()).pipe(
|
|
423
|
+
UnexpectedError.mapToUnexpectedError,
|
|
424
|
+
Effect.withSpan('@livestore/adapter-node:client-session:getLeaderSyncState'),
|
|
425
|
+
),
|
|
426
|
+
sendDevtoolsMessage: (message) =>
|
|
427
|
+
runInWorker(new WorkerSchema.LeaderWorkerInnerExtraDevtoolsMessage({ message })).pipe(
|
|
428
|
+
UnexpectedError.mapToUnexpectedError,
|
|
429
|
+
Effect.withSpan('@livestore/adapter-node:client-session:devtoolsMessageForLeader'),
|
|
424
430
|
),
|
|
425
431
|
},
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
migrationsReport: bootResult.migrationsReport,
|
|
432
|
+
{
|
|
433
|
+
overrides: testing?.overrides?.clientSession?.leaderThreadProxy,
|
|
429
434
|
},
|
|
430
|
-
|
|
431
|
-
Effect.timeout(10_000),
|
|
432
|
-
UnexpectedError.mapToUnexpectedError,
|
|
433
|
-
Effect.withSpan('@livestore/adapter-node:client-session:export'),
|
|
434
|
-
),
|
|
435
|
-
getEventlogData: Effect.dieMessage('Not implemented'),
|
|
436
|
-
getSyncState: runInWorker(new WorkerSchema.LeaderWorkerInner.GetLeaderSyncState()).pipe(
|
|
437
|
-
UnexpectedError.mapToUnexpectedError,
|
|
438
|
-
Effect.withSpan('@livestore/adapter-node:client-session:getLeaderSyncState'),
|
|
439
|
-
),
|
|
440
|
-
sendDevtoolsMessage: (message) =>
|
|
441
|
-
runInWorker(new WorkerSchema.LeaderWorkerInner.ExtraDevtoolsMessage({ message })).pipe(
|
|
442
|
-
UnexpectedError.mapToUnexpectedError,
|
|
443
|
-
Effect.withSpan('@livestore/adapter-node:client-session:devtoolsMessageForLeader'),
|
|
444
|
-
),
|
|
445
|
-
} satisfies ClientSessionLeaderThreadProxy
|
|
435
|
+
)
|
|
446
436
|
|
|
447
437
|
return { leaderThread, initialSnapshot: bootResult.snapshot }
|
|
448
438
|
})
|
|
@@ -2,7 +2,7 @@ import http from 'node:http'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
4
|
import type { Devtools } from '@livestore/common'
|
|
5
|
-
import { LS_DEV } from '@livestore/utils'
|
|
5
|
+
import { isReadonlyArray, LS_DEV } from '@livestore/utils'
|
|
6
6
|
import type { HttpClient } from '@livestore/utils/effect'
|
|
7
7
|
import {
|
|
8
8
|
Deferred,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { PlatformNode } from '@livestore/utils/node'
|
|
19
19
|
import { makeMeshNode, makeWebSocketEdge } from '@livestore/webmesh'
|
|
20
20
|
|
|
21
|
-
import { makeViteMiddleware } from './vite-dev-server.
|
|
21
|
+
import { makeViteMiddleware } from './vite-dev-server.ts'
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Starts a devtools HTTP/WS server which serves ...
|
|
@@ -31,7 +31,7 @@ export const startDevtoolsServer = ({
|
|
|
31
31
|
port,
|
|
32
32
|
host,
|
|
33
33
|
}: {
|
|
34
|
-
schemaPath: string
|
|
34
|
+
schemaPath: string | ReadonlyArray<string>
|
|
35
35
|
clientSessionInfo: Devtools.SessionInfo.SessionInfo | undefined
|
|
36
36
|
host: string
|
|
37
37
|
port: number
|
|
@@ -39,7 +39,9 @@ export const startDevtoolsServer = ({
|
|
|
39
39
|
Effect.gen(function* () {
|
|
40
40
|
const viteMiddleware = yield* makeViteMiddleware({
|
|
41
41
|
mode: { _tag: 'node', url: `http://${host}:${port}` },
|
|
42
|
-
schemaPath:
|
|
42
|
+
schemaPath: isReadonlyArray(schemaPath)
|
|
43
|
+
? schemaPath.map((schemaPath) => path.resolve(process.cwd(), schemaPath))
|
|
44
|
+
: path.resolve(process.cwd(), schemaPath),
|
|
43
45
|
viteConfig: (viteConfig) => {
|
|
44
46
|
if (LS_DEV) {
|
|
45
47
|
viteConfig.server ??= {}
|
|
@@ -85,7 +87,7 @@ export const startDevtoolsServer = ({
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
// We want to keep the websocket open until the client disconnects or the server shuts down
|
|
88
|
-
yield* Effect.never
|
|
90
|
+
return yield* Effect.never
|
|
89
91
|
}),
|
|
90
92
|
webChannel.closedDeferred,
|
|
91
93
|
)
|
package/src/devtools/mod.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type { ViteDevtoolsOptions } from './vite-dev-server.
|
|
3
|
-
export {
|
|
1
|
+
export { startDevtoolsServer } from './devtools-server.ts'
|
|
2
|
+
export type { ViteDevtoolsOptions } from './vite-dev-server.ts'
|
|
3
|
+
export { makeViteMiddleware } from './vite-dev-server.ts'
|
|
@@ -3,6 +3,7 @@ import path from 'node:path'
|
|
|
3
3
|
import type { Devtools } from '@livestore/common'
|
|
4
4
|
import { UnexpectedError } from '@livestore/common'
|
|
5
5
|
import { livestoreDevtoolsPlugin } from '@livestore/devtools-vite'
|
|
6
|
+
import { isReadonlyArray } from '@livestore/utils'
|
|
6
7
|
import { Effect } from '@livestore/utils/effect'
|
|
7
8
|
import { getFreePort } from '@livestore/utils/node'
|
|
8
9
|
import * as Vite from 'vite'
|
|
@@ -15,7 +16,7 @@ export type ViteDevtoolsOptions = {
|
|
|
15
16
|
*
|
|
16
17
|
* Example: `./src/schema.ts`
|
|
17
18
|
*/
|
|
18
|
-
schemaPath: string
|
|
19
|
+
schemaPath: string | ReadonlyArray<string>
|
|
19
20
|
/**
|
|
20
21
|
* The mode of the devtools server.
|
|
21
22
|
*
|
|
@@ -44,7 +45,9 @@ export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<
|
|
|
44
45
|
base: '/_livestore/',
|
|
45
46
|
plugins: [
|
|
46
47
|
livestoreDevtoolsPlugin({
|
|
47
|
-
schemaPath:
|
|
48
|
+
schemaPath: isReadonlyArray(options.schemaPath)
|
|
49
|
+
? options.schemaPath.map((schemaPath) => path.resolve(cwd, schemaPath))
|
|
50
|
+
: path.resolve(cwd, options.schemaPath),
|
|
48
51
|
mode: options.mode,
|
|
49
52
|
path: '/',
|
|
50
53
|
}),
|
package/src/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { makeAdapter, makeWorkerAdapter } from './client-session/adapter.
|
|
1
|
+
export { makeAdapter, makeWorkerAdapter } from './client-session/adapter.ts'
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
const run = async () => {
|
|
7
7
|
const start = Date.now()
|
|
8
8
|
// @ts-expect-error todo
|
|
9
|
-
const _module = await import('./leader-thread.bundle.
|
|
9
|
+
const _module = await import('./leader-thread.bundle.ts')
|
|
10
10
|
const end = Date.now()
|
|
11
11
|
console.log(`[@livestore/adapter-node:leader] Loaded in ${end - start}ms`)
|
|
12
12
|
}
|
|
@@ -16,16 +16,22 @@ import type { FileSystem, HttpClient, Layer, Schema, Scope } from '@livestore/ut
|
|
|
16
16
|
import { Effect } from '@livestore/utils/effect'
|
|
17
17
|
import * as Webmesh from '@livestore/webmesh'
|
|
18
18
|
|
|
19
|
-
import { makeShutdownChannel } from './shutdown-channel.
|
|
20
|
-
import type * as WorkerSchema from './worker-schema.
|
|
19
|
+
import { makeShutdownChannel } from './shutdown-channel.ts'
|
|
20
|
+
import type * as WorkerSchema from './worker-schema.ts'
|
|
21
21
|
|
|
22
22
|
export type TestingOverrides = {
|
|
23
23
|
clientSession?: {
|
|
24
|
-
leaderThreadProxy?:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
dbEventlog?: (makeSqliteDb: MakeSqliteDb) => Effect.Effect<SqliteDb, UnexpectedError>
|
|
24
|
+
leaderThreadProxy?: (
|
|
25
|
+
original: ClientSessionLeaderThreadProxy.ClientSessionLeaderThreadProxy,
|
|
26
|
+
) => Partial<ClientSessionLeaderThreadProxy.ClientSessionLeaderThreadProxy>
|
|
28
27
|
}
|
|
28
|
+
makeLeaderThread?: (makeSqliteDb: MakeSqliteDb) => Effect.Effect<
|
|
29
|
+
{
|
|
30
|
+
dbEventlog: SqliteDb
|
|
31
|
+
dbState: SqliteDb
|
|
32
|
+
},
|
|
33
|
+
UnexpectedError
|
|
34
|
+
>
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
export interface MakeLeaderThreadArgs {
|
|
@@ -34,7 +40,7 @@ export interface MakeLeaderThreadArgs {
|
|
|
34
40
|
syncOptions: SyncOptions | undefined
|
|
35
41
|
storage: WorkerSchema.StorageType
|
|
36
42
|
makeSqliteDb: MakeNodeSqliteDb
|
|
37
|
-
devtools: WorkerSchema.
|
|
43
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessage['devtools']
|
|
38
44
|
schema: LiveStoreSchema
|
|
39
45
|
syncPayload: Schema.JsonValue | undefined
|
|
40
46
|
testing: TestingOverrides | undefined
|
|
@@ -62,8 +68,10 @@ export const makeLeaderThread = ({
|
|
|
62
68
|
schema.state.sqlite.migrations.strategy === 'manual' ? 'fixed' : schema.state.sqlite.hash.toString()
|
|
63
69
|
|
|
64
70
|
const makeDb = (kind: 'state' | 'eventlog') => {
|
|
65
|
-
if (testing?.makeLeaderThread
|
|
66
|
-
return testing
|
|
71
|
+
if (testing?.makeLeaderThread) {
|
|
72
|
+
return testing
|
|
73
|
+
.makeLeaderThread(makeSqliteDb)
|
|
74
|
+
.pipe(Effect.map(({ dbEventlog, dbState }) => (kind === 'state' ? dbState : dbEventlog)))
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
return storage.type === 'in-memory'
|
|
@@ -123,7 +131,7 @@ const makeDevtoolsOptions = ({
|
|
|
123
131
|
dbEventlog: LeaderSqliteDb
|
|
124
132
|
storeId: string
|
|
125
133
|
clientId: string
|
|
126
|
-
devtools: WorkerSchema.
|
|
134
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessage['devtools']
|
|
127
135
|
}): Effect.Effect<DevtoolsOptions, UnexpectedError, Scope.Scope> =>
|
|
128
136
|
Effect.gen(function* () {
|
|
129
137
|
if (devtools.enabled === false) {
|
|
@@ -136,7 +144,7 @@ const makeDevtoolsOptions = ({
|
|
|
136
144
|
enabled: true,
|
|
137
145
|
boot: Effect.gen(function* () {
|
|
138
146
|
// Lazy import to improve startup time
|
|
139
|
-
const { startDevtoolsServer } = yield* Effect.promise(() => import('./devtools/devtools-server.
|
|
147
|
+
const { startDevtoolsServer } = yield* Effect.promise(() => import('./devtools/devtools-server.ts'))
|
|
140
148
|
|
|
141
149
|
// TODO instead of failing when the port is already in use, we should try to use that WS server instead of starting a new one
|
|
142
150
|
if (devtools.useExistingDevtoolsServer === false) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './thread-polyfill.
|
|
1
|
+
import './thread-polyfill.ts'
|
|
2
2
|
|
|
3
3
|
import inspector from 'node:inspector'
|
|
4
4
|
|
|
@@ -29,9 +29,9 @@ import {
|
|
|
29
29
|
import { PlatformNode } from '@livestore/utils/node'
|
|
30
30
|
import type * as otel from '@opentelemetry/api'
|
|
31
31
|
|
|
32
|
-
import type { TestingOverrides } from './leader-thread-shared.
|
|
33
|
-
import { makeLeaderThread } from './leader-thread-shared.
|
|
34
|
-
import * as WorkerSchema from './worker-schema.
|
|
32
|
+
import type { TestingOverrides } from './leader-thread-shared.ts'
|
|
33
|
+
import { makeLeaderThread } from './leader-thread-shared.ts'
|
|
34
|
+
import * as WorkerSchema from './worker-schema.ts'
|
|
35
35
|
|
|
36
36
|
export type WorkerOptions = {
|
|
37
37
|
schema: LiveStoreSchema
|
|
@@ -47,7 +47,10 @@ export type WorkerOptions = {
|
|
|
47
47
|
export const getWorkerArgs = () => Schema.decodeSync(WorkerSchema.WorkerArgv)(process.argv[2]!)
|
|
48
48
|
|
|
49
49
|
export const makeWorker = (options: WorkerOptions) => {
|
|
50
|
-
makeWorkerEffect(options).pipe(
|
|
50
|
+
makeWorkerEffect(options).pipe(
|
|
51
|
+
Effect.provide(Logger.prettyWithThread(options.otelOptions?.serviceName ?? 'livestore-node-leader-thread')),
|
|
52
|
+
PlatformNode.NodeRuntime.runMain,
|
|
53
|
+
)
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
export const makeWorkerEffect = (options: WorkerOptions) => {
|
|
@@ -57,7 +60,7 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
|
|
|
57
60
|
)
|
|
58
61
|
: undefined
|
|
59
62
|
|
|
60
|
-
return WorkerRunner.layerSerialized(WorkerSchema.
|
|
63
|
+
return WorkerRunner.layerSerialized(WorkerSchema.LeaderWorkerInnerRequest, {
|
|
61
64
|
InitialMessage: (args) =>
|
|
62
65
|
Effect.gen(function* () {
|
|
63
66
|
const sqlite3 = yield* Effect.promise(() => loadSqlite3Wasm()).pipe(
|
|
@@ -153,7 +156,9 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
|
|
|
153
156
|
thread: options.otelOptions?.serviceName ?? 'livestore-node-leader-thread',
|
|
154
157
|
processId: process.pid,
|
|
155
158
|
}),
|
|
156
|
-
Effect
|
|
159
|
+
// TODO bring back with Effect 4 once it's easier to work with replacing loggers.
|
|
160
|
+
// We basically only want to provide this logger if it's replacing the default logger, not if there's a custom logger already provided.
|
|
161
|
+
// Effect.provide(Logger.prettyWithThread(options.otelOptions?.serviceName ?? 'livestore-node-leader-thread')),
|
|
157
162
|
Effect.provide(FetchHttpClient.layer),
|
|
158
163
|
Effect.provide(PlatformNode.NodeFileSystem.layer),
|
|
159
164
|
TracingLive ? Effect.provide(TracingLive) : identity,
|
package/src/shutdown-channel.ts
CHANGED
package/src/webchannel.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BroadcastChannel as NodeBroadcastChannel } from 'node:worker_threads'
|
|
2
2
|
|
|
3
3
|
import type { Either, ParseResult } from '@livestore/utils/effect'
|
|
4
4
|
import { Deferred, Effect, Exit, Schema, Scope, Stream, WebChannel } from '@livestore/utils/effect'
|
|
@@ -37,7 +37,6 @@ export const makeBroadcastChannel = <Msg, MsgEncoded>({
|
|
|
37
37
|
const listen = Stream.asyncPush<Either.Either<Msg, ParseResult.ParseError>>((emit) =>
|
|
38
38
|
Effect.acquireRelease(
|
|
39
39
|
Effect.gen(function* () {
|
|
40
|
-
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
|
41
40
|
channel.onmessage = (event: any) => {
|
|
42
41
|
return emit.single(Schema.decodeEither(schema)(event.data))
|
|
43
42
|
}
|