@livestore/adapter-node 0.4.0-dev.9 → 0.5.0-dev.0
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 +69 -3
- package/dist/client-session/adapter.d.ts.map +1 -1
- package/dist/client-session/adapter.js +160 -62
- package/dist/client-session/adapter.js.map +1 -1
- package/dist/devtools/devtools-server.d.ts.map +1 -1
- package/dist/devtools/devtools-server.js +25 -19
- package/dist/devtools/devtools-server.js.map +1 -1
- package/dist/devtools/mod.d.ts +1 -1
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +1 -1
- package/dist/devtools/mod.js.map +1 -1
- package/dist/devtools/vite-dev-server.d.ts +22 -4
- package/dist/devtools/vite-dev-server.d.ts.map +1 -1
- package/dist/devtools/vite-dev-server.js +45 -11
- package/dist/devtools/vite-dev-server.js.map +1 -1
- package/dist/leader-thread-shared.d.ts +8 -7
- package/dist/leader-thread-shared.d.ts.map +1 -1
- package/dist/leader-thread-shared.js +19 -16
- package/dist/leader-thread-shared.js.map +1 -1
- package/dist/make-leader-worker.d.ts +5 -3
- package/dist/make-leader-worker.d.ts.map +1 -1
- package/dist/make-leader-worker.js +75 -59
- package/dist/make-leader-worker.js.map +1 -1
- package/dist/rpc-worker.d.ts +8 -0
- package/dist/rpc-worker.d.ts.map +1 -0
- package/dist/rpc-worker.js +5 -0
- package/dist/rpc-worker.js.map +1 -0
- package/dist/shutdown-channel.d.ts.map +1 -1
- package/dist/shutdown-channel.js.map +1 -1
- package/dist/webchannel.d.ts +1 -1
- package/dist/webchannel.d.ts.map +1 -1
- package/dist/webchannel.js +17 -18
- package/dist/webchannel.js.map +1 -1
- package/dist/worker-schema.d.ts +274 -138
- package/dist/worker-schema.d.ts.map +1 -1
- package/dist/worker-schema.js +79 -45
- package/dist/worker-schema.js.map +1 -1
- package/package.json +51 -20
- package/src/client-session/adapter.ts +228 -124
- package/src/devtools/devtools-server.ts +50 -35
- package/src/devtools/mod.ts +1 -1
- package/src/devtools/vite-dev-server.ts +65 -15
- package/src/leader-thread-shared.ts +37 -34
- package/src/make-leader-worker.ts +164 -115
- package/src/rpc-worker.ts +28 -0
- package/src/shutdown-channel.ts +1 -0
- package/src/webchannel.ts +21 -28
- package/src/worker-schema.ts +132 -117
|
@@ -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 {
|
|
5
|
+
import { LS_DEV } from '@livestore/utils'
|
|
6
6
|
import type { HttpClient } from '@livestore/utils/effect'
|
|
7
7
|
import {
|
|
8
8
|
Deferred,
|
|
@@ -20,6 +20,16 @@ import { makeMeshNode, makeWebSocketEdge } from '@livestore/webmesh'
|
|
|
20
20
|
|
|
21
21
|
import { makeViteMiddleware } from './vite-dev-server.ts'
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Determines if a request URL should be routed to the Vite middleware.
|
|
25
|
+
* Includes LiveStore devtools paths and Vite internal paths like `/@fs/`, `/@vite/`, etc.
|
|
26
|
+
*/
|
|
27
|
+
const shouldRouteToVite = (url: string): boolean =>
|
|
28
|
+
url.startsWith('/_livestore') ||
|
|
29
|
+
url.startsWith('/@fs') ||
|
|
30
|
+
url.startsWith('/@vite') ||
|
|
31
|
+
url.startsWith('/@react-refresh')
|
|
32
|
+
|
|
23
33
|
/**
|
|
24
34
|
* Starts a devtools HTTP/WS server which serves ...
|
|
25
35
|
* - the Devtools UI via Vite
|
|
@@ -37,24 +47,28 @@ export const startDevtoolsServer = ({
|
|
|
37
47
|
port: number
|
|
38
48
|
}): Effect.Effect<never, never, HttpClient.HttpClient> =>
|
|
39
49
|
Effect.gen(function* () {
|
|
40
|
-
const viteMiddleware = yield*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
const viteMiddleware = yield* Effect.acquireRelease(
|
|
51
|
+
makeViteMiddleware({
|
|
52
|
+
mode: { _tag: 'node', url: `http://${host}:${port}` },
|
|
53
|
+
schemaPath:
|
|
54
|
+
typeof schemaPath === 'string'
|
|
55
|
+
? path.resolve(process.cwd(), schemaPath)
|
|
56
|
+
: schemaPath.map((schemaPath) => path.resolve(process.cwd(), schemaPath)),
|
|
57
|
+
viteConfig: (viteConfig) => {
|
|
58
|
+
if (LS_DEV === true) {
|
|
59
|
+
viteConfig.server ??= {}
|
|
60
|
+
viteConfig.server.fs ??= {}
|
|
61
|
+
viteConfig.server.fs.strict = false
|
|
62
|
+
|
|
63
|
+
viteConfig.optimizeDeps ??= {}
|
|
64
|
+
viteConfig.optimizeDeps.force = true
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return viteConfig
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
(viteMiddleware) => Effect.promise(() => viteMiddleware.close()),
|
|
71
|
+
)
|
|
58
72
|
|
|
59
73
|
const relayNodeName = 'ws'
|
|
60
74
|
|
|
@@ -63,7 +77,7 @@ export const startDevtoolsServer = ({
|
|
|
63
77
|
const handler = Effect.gen(function* () {
|
|
64
78
|
const req = yield* HttpServerRequest.HttpServerRequest
|
|
65
79
|
|
|
66
|
-
if (Headers.has(req.headers, 'upgrade')) {
|
|
80
|
+
if (Headers.has(req.headers, 'upgrade') === true) {
|
|
67
81
|
// yield* Effect.logDebug(`WS Relay ${relayNodeName}: WS upgrade request ${req.url}`)
|
|
68
82
|
|
|
69
83
|
const socket = yield* req.upgrade
|
|
@@ -77,11 +91,12 @@ export const startDevtoolsServer = ({
|
|
|
77
91
|
// To handle websocket closing, we need to race the `webChannel.closedDeferred` to properly interrupt the handler
|
|
78
92
|
yield* Effect.raceFirst(
|
|
79
93
|
Effect.gen(function* () {
|
|
80
|
-
yield*
|
|
81
|
-
.addEdge({ target: from, edgeChannel: webChannel, replaceIfExists: true })
|
|
82
|
-
|
|
94
|
+
yield* Effect.acquireRelease(
|
|
95
|
+
node.addEdge({ target: from, edgeChannel: webChannel, replaceIfExists: true }),
|
|
96
|
+
() => node.removeEdge(from).pipe(Effect.orDie),
|
|
97
|
+
)
|
|
83
98
|
|
|
84
|
-
if (LS_DEV) {
|
|
99
|
+
if (LS_DEV === true) {
|
|
85
100
|
yield* Effect.log(`WS Relay ${relayNodeName}: added edge from '${from}'`)
|
|
86
101
|
yield* Effect.addFinalizerLog(`WS Relay ${relayNodeName}: removed edge from '${from}'`)
|
|
87
102
|
}
|
|
@@ -89,22 +104,22 @@ export const startDevtoolsServer = ({
|
|
|
89
104
|
// We want to keep the websocket open until the client disconnects or the server shuts down
|
|
90
105
|
return yield* Effect.never
|
|
91
106
|
}),
|
|
92
|
-
webChannel.closedDeferred,
|
|
107
|
+
Deferred.await(webChannel.closedDeferred),
|
|
93
108
|
)
|
|
94
109
|
|
|
95
110
|
return HttpServerResponse.empty({ status: 101 })
|
|
96
111
|
} else {
|
|
97
112
|
if (req.url === '/' || req.url === '') {
|
|
98
113
|
return HttpServerResponse.redirect('/_livestore/node')
|
|
99
|
-
} else if (req.url
|
|
114
|
+
} else if (shouldRouteToVite(req.url) === true) {
|
|
100
115
|
// Here we're delegating to the Vite middleware
|
|
101
116
|
|
|
102
117
|
// TODO replace this once @effect/platform-node supports Node HTTP middlewares
|
|
103
118
|
const nodeReq = PlatformNode.NodeHttpServerRequest.toIncomingMessage(req)
|
|
104
119
|
const nodeRes = PlatformNode.NodeHttpServerRequest.toServerResponse(req)
|
|
105
|
-
const deferred = yield* Deferred.make()
|
|
106
|
-
viteMiddleware.middlewares(nodeReq, nodeRes, () => Deferred.
|
|
107
|
-
yield* deferred
|
|
120
|
+
const deferred = yield* Deferred.make<void>()
|
|
121
|
+
viteMiddleware.middlewares(nodeReq, nodeRes, () => Deferred.doneUnsafe(deferred, Exit.void))
|
|
122
|
+
yield* Deferred.await(deferred)
|
|
108
123
|
|
|
109
124
|
// The response is already sent, so we need to return an empty response (which won't be sent)
|
|
110
125
|
return HttpServerResponse.empty()
|
|
@@ -112,11 +127,12 @@ export const startDevtoolsServer = ({
|
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
return HttpServerResponse.text('Not found')
|
|
115
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.interruptible)
|
|
130
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.interruptible, HttpMiddleware.withLoggerDisabled)
|
|
116
131
|
|
|
117
|
-
const sessionSuffix =
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
const sessionSuffix =
|
|
133
|
+
clientSessionInfo !== undefined
|
|
134
|
+
? `/${clientSessionInfo.storeId}/${clientSessionInfo.clientId}/${clientSessionInfo.sessionId}/${clientSessionInfo.schemaAlias}`
|
|
135
|
+
: '?autoconnect'
|
|
120
136
|
|
|
121
137
|
// Use `localhost` instead of `0.0.0.0` as it doesn't have the `navigator.locks` web adapter limitation (https://share.cleanshot.com/nHBnmk6S)
|
|
122
138
|
const maybeLocalhost = host === '0.0.0.0' ? 'localhost' : host
|
|
@@ -129,8 +145,7 @@ export const startDevtoolsServer = ({
|
|
|
129
145
|
Effect.withSpan('@livestore/adapter-node:startDevtoolsServer', {
|
|
130
146
|
attributes: { clientSessionInfo, port, host, schemaPath },
|
|
131
147
|
}),
|
|
132
|
-
|
|
133
|
-
Layer.unwrapScoped,
|
|
148
|
+
Layer.unwrap,
|
|
134
149
|
Layer.provide(PlatformNode.NodeHttpServer.layer(() => http.createServer(), { port, host })),
|
|
135
150
|
Layer.launch,
|
|
136
151
|
Effect.orDie,
|
package/src/devtools/mod.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { startDevtoolsServer } from './devtools-server.ts'
|
|
2
2
|
export type { ViteDevtoolsOptions } from './vite-dev-server.ts'
|
|
3
|
-
export { makeViteMiddleware } from './vite-dev-server.ts'
|
|
3
|
+
export { DevtoolsViteNotInstalledError, makeViteMiddleware } from './vite-dev-server.ts'
|
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
|
|
3
2
|
import type { Devtools } from '@livestore/common'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { isReadonlyArray } from '@livestore/utils'
|
|
7
|
-
import { Effect } from '@livestore/utils/effect'
|
|
3
|
+
import { UnknownError } from '@livestore/common'
|
|
4
|
+
import { Effect, Schema } from '@livestore/utils/effect'
|
|
8
5
|
import { getFreePort } from '@livestore/utils/node'
|
|
9
|
-
import * as Vite from 'vite'
|
|
6
|
+
import type * as Vite from 'vite'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Error thrown when @livestore/devtools-vite is not installed.
|
|
10
|
+
* This is a peer dependency that must be installed separately.
|
|
11
|
+
*/
|
|
12
|
+
export class DevtoolsViteNotInstalledError extends Schema.TaggedError<DevtoolsViteNotInstalledError>(
|
|
13
|
+
'~@livestore/adapter-node/DevtoolsViteNotInstalledError',
|
|
14
|
+
)('DevtoolsViteNotInstalledError', {
|
|
15
|
+
cause: Schema.Defect(),
|
|
16
|
+
}) {
|
|
17
|
+
override get message(): string {
|
|
18
|
+
return (
|
|
19
|
+
`@livestore/devtools-vite is required for devtools but not installed. ` +
|
|
20
|
+
`Install it with: pnpm add @livestore/devtools-vite@<version>. ` +
|
|
21
|
+
`Make sure to use the same version as @livestore/adapter-node.`
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Error thrown when vite is not installed for the devtools server path. */
|
|
27
|
+
export class ViteNotInstalledError extends Schema.TaggedError<ViteNotInstalledError>(
|
|
28
|
+
'~@livestore/adapter-node/ViteNotInstalledError',
|
|
29
|
+
)('ViteNotInstalledError', {
|
|
30
|
+
cause: Schema.Defect(),
|
|
31
|
+
}) {
|
|
32
|
+
override get message(): string {
|
|
33
|
+
return (
|
|
34
|
+
`vite is required for @livestore/adapter-node/devtools but not installed. ` +
|
|
35
|
+
`Install it with: pnpm add -D vite@<version>.`
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
10
39
|
|
|
11
40
|
export type ViteDevtoolsOptions = {
|
|
12
41
|
viteConfig?: (config: Vite.UserConfig) => Vite.UserConfig
|
|
@@ -26,11 +55,16 @@ export type ViteDevtoolsOptions = {
|
|
|
26
55
|
}
|
|
27
56
|
|
|
28
57
|
// NOTE this is currently also used in @livestore/devtools-expo
|
|
29
|
-
export const makeViteMiddleware = (
|
|
58
|
+
export const makeViteMiddleware = (
|
|
59
|
+
options: ViteDevtoolsOptions,
|
|
60
|
+
): Effect.Effect<Vite.ViteDevServer, DevtoolsViteNotInstalledError | ViteNotInstalledError | UnknownError> =>
|
|
30
61
|
Effect.gen(function* () {
|
|
62
|
+
const { livestoreDevtoolsPlugin } = yield* importDevtoolsVite()
|
|
63
|
+
const Vite = yield* importVite()
|
|
64
|
+
|
|
31
65
|
const cwd = process.cwd()
|
|
32
66
|
|
|
33
|
-
const hmrPort = yield* getFreePort.pipe(
|
|
67
|
+
const hmrPort = yield* getFreePort.pipe(UnknownError.mapToUnknownError)
|
|
34
68
|
|
|
35
69
|
const defaultViteConfig = Vite.defineConfig({
|
|
36
70
|
server: {
|
|
@@ -39,15 +73,16 @@ export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<
|
|
|
39
73
|
port: hmrPort,
|
|
40
74
|
},
|
|
41
75
|
// Relaxing fs access for monorepo setup
|
|
42
|
-
fs: { strict: process.env.LS_DEV ? false : true },
|
|
76
|
+
fs: { strict: process.env.LS_DEV !== undefined ? false : true },
|
|
43
77
|
},
|
|
44
78
|
appType: 'spa',
|
|
45
79
|
base: '/_livestore/',
|
|
46
80
|
plugins: [
|
|
47
81
|
livestoreDevtoolsPlugin({
|
|
48
|
-
schemaPath:
|
|
49
|
-
|
|
50
|
-
|
|
82
|
+
schemaPath:
|
|
83
|
+
typeof options.schemaPath === 'string'
|
|
84
|
+
? path.resolve(cwd, options.schemaPath)
|
|
85
|
+
: options.schemaPath.map((schemaPath) => path.resolve(cwd, schemaPath)),
|
|
51
86
|
mode: options.mode,
|
|
52
87
|
path: '/',
|
|
53
88
|
}),
|
|
@@ -58,9 +93,24 @@ export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<
|
|
|
58
93
|
|
|
59
94
|
const viteConfig = options.viteConfig?.(defaultViteConfig) ?? defaultViteConfig
|
|
60
95
|
|
|
61
|
-
const viteServer = yield* Effect.promise(() => Vite.createServer(viteConfig)).pipe(
|
|
62
|
-
UnexpectedError.mapToUnexpectedError,
|
|
63
|
-
)
|
|
96
|
+
const viteServer = yield* Effect.promise(() => Vite.createServer(viteConfig)).pipe(UnknownError.mapToUnknownError)
|
|
64
97
|
|
|
65
98
|
return viteServer
|
|
66
99
|
}).pipe(Effect.withSpan('@livestore/adapter-node:devtools:makeViteServer'))
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Dynamically imports @livestore/devtools-vite.
|
|
103
|
+
* This package is a peer dependency and may not be installed.
|
|
104
|
+
*/
|
|
105
|
+
const importDevtoolsVite = () =>
|
|
106
|
+
Effect.tryPromise({
|
|
107
|
+
try: () => import('@livestore/devtools-vite'),
|
|
108
|
+
catch: (cause) => new DevtoolsViteNotInstalledError({ cause }),
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
/** Dynamically imports vite for the devtools-only server path. */
|
|
112
|
+
const importVite = () =>
|
|
113
|
+
Effect.tryPromise({
|
|
114
|
+
try: () => import('vite'),
|
|
115
|
+
catch: (cause) => new ViteNotInstalledError({ cause }),
|
|
116
|
+
})
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import inspector from 'node:inspector'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
|
-
if (process.execArgv.includes('--inspect')) {
|
|
4
|
+
if (process.execArgv.includes('--inspect') === true) {
|
|
5
5
|
inspector.open()
|
|
6
6
|
inspector.waitForDebugger()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
import type { ClientSessionLeaderThreadProxy, MakeSqliteDb, SqliteDb, SyncOptions } from '@livestore/common'
|
|
10
|
-
import { Devtools, liveStoreStorageFormatVersion, migrateDb,
|
|
10
|
+
import { Devtools, liveStoreStorageFormatVersion, migrateDb, StateHead, UnknownError } from '@livestore/common'
|
|
11
11
|
import type { DevtoolsOptions, LeaderSqliteDb, LeaderThreadCtx } from '@livestore/common/leader-thread'
|
|
12
12
|
import { configureConnection, makeLeaderThreadLayer } from '@livestore/common/leader-thread'
|
|
13
13
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
14
|
+
import { getStateDbBaseName } from '@livestore/common/schema'
|
|
14
15
|
import type { MakeNodeSqliteDb } from '@livestore/sqlite-wasm/node'
|
|
15
|
-
import type { FileSystem, HttpClient,
|
|
16
|
-
import { Effect } from '@livestore/utils/effect'
|
|
16
|
+
import type { FileSystem, HttpClient, Schema, Scope } from '@livestore/utils/effect'
|
|
17
|
+
import { Effect, Layer } from '@livestore/utils/effect'
|
|
17
18
|
import * as Webmesh from '@livestore/webmesh'
|
|
18
19
|
|
|
19
20
|
import { makeShutdownChannel } from './shutdown-channel.ts'
|
|
@@ -30,7 +31,7 @@ export type TestingOverrides = {
|
|
|
30
31
|
dbEventlog: SqliteDb
|
|
31
32
|
dbState: SqliteDb
|
|
32
33
|
},
|
|
33
|
-
|
|
34
|
+
UnknownError
|
|
34
35
|
>
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -40,9 +41,10 @@ export interface MakeLeaderThreadArgs {
|
|
|
40
41
|
syncOptions: SyncOptions | undefined
|
|
41
42
|
storage: WorkerSchema.StorageType
|
|
42
43
|
makeSqliteDb: MakeNodeSqliteDb
|
|
43
|
-
devtools: WorkerSchema.
|
|
44
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessagePayload['devtools']
|
|
44
45
|
schema: LiveStoreSchema
|
|
45
|
-
|
|
46
|
+
syncPayloadEncoded: Schema.Json | undefined
|
|
47
|
+
syncPayloadSchema: Schema.Schema<any> | undefined
|
|
46
48
|
testing: TestingOverrides | undefined
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -54,21 +56,19 @@ export const makeLeaderThread = ({
|
|
|
54
56
|
storage,
|
|
55
57
|
devtools,
|
|
56
58
|
schema,
|
|
57
|
-
|
|
59
|
+
syncPayloadEncoded,
|
|
60
|
+
syncPayloadSchema,
|
|
58
61
|
testing,
|
|
59
62
|
}: MakeLeaderThreadArgs): Effect.Effect<
|
|
60
|
-
Layer.Layer<LeaderThreadCtx,
|
|
61
|
-
|
|
63
|
+
Layer.Layer<LeaderThreadCtx, UnknownError, Scope.Scope | HttpClient.HttpClient | FileSystem.FileSystem>,
|
|
64
|
+
UnknownError,
|
|
62
65
|
Scope.Scope
|
|
63
66
|
> =>
|
|
64
67
|
Effect.gen(function* () {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const schemaHashSuffix =
|
|
68
|
-
schema.state.sqlite.migrations.strategy === 'manual' ? 'fixed' : schema.state.sqlite.hash.toString()
|
|
68
|
+
const services = yield* Effect.context()
|
|
69
69
|
|
|
70
70
|
const makeDb = (kind: 'state' | 'eventlog') => {
|
|
71
|
-
if (testing?.makeLeaderThread) {
|
|
71
|
+
if (testing?.makeLeaderThread !== undefined) {
|
|
72
72
|
return testing
|
|
73
73
|
.makeLeaderThread(makeSqliteDb)
|
|
74
74
|
.pipe(Effect.map(({ dbEventlog, dbState }) => (kind === 'state' ? dbState : dbEventlog)))
|
|
@@ -77,18 +77,21 @@ export const makeLeaderThread = ({
|
|
|
77
77
|
return storage.type === 'in-memory'
|
|
78
78
|
? makeSqliteDb({
|
|
79
79
|
_tag: 'in-memory',
|
|
80
|
-
configureDb: (db) =>
|
|
81
|
-
configureConnection(db, { foreignKeys: true }).pipe(Effect.provide(runtime), Effect.runSync),
|
|
80
|
+
configureDb: (db) => configureConnection(db, { foreignKeys: true }).pipe(Effect.runSyncWith(services)),
|
|
82
81
|
})
|
|
83
|
-
:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
: Effect.acquireRelease(
|
|
83
|
+
makeSqliteDb({
|
|
84
|
+
_tag: 'fs',
|
|
85
|
+
directory: path.join(storage.baseDirectory ?? '', storeId),
|
|
86
|
+
fileName:
|
|
87
|
+
kind === 'state'
|
|
88
|
+
? `${getStateDbBaseName(schema)}@${liveStoreStorageFormatVersion}.db`
|
|
89
|
+
: `eventlog@${liveStoreStorageFormatVersion}.db`,
|
|
90
|
+
// TODO enable WAL for nodejs
|
|
91
|
+
configureDb: (db) => configureConnection(db, { foreignKeys: true }).pipe(Effect.runSyncWith(services)),
|
|
92
|
+
}),
|
|
93
|
+
(db) => Effect.sync(() => db.close()),
|
|
94
|
+
)
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
// Might involve some async work, so we're running them concurrently
|
|
@@ -113,18 +116,17 @@ export const makeLeaderThread = ({
|
|
|
113
116
|
dbEventlog,
|
|
114
117
|
devtoolsOptions,
|
|
115
118
|
shutdownChannel,
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
syncPayloadEncoded,
|
|
120
|
+
syncPayloadSchema: syncPayloadSchema as Schema.Decoder<Schema.Json, never> | undefined,
|
|
121
|
+
}).pipe(Layer.provide(StateHead.layer({ dbState })))
|
|
118
122
|
}).pipe(
|
|
119
123
|
Effect.tapCauseLogPretty,
|
|
120
|
-
|
|
124
|
+
UnknownError.mapToUnknownError,
|
|
121
125
|
Effect.withSpan('@livestore/adapter-node:makeLeaderThread', {
|
|
122
126
|
attributes: { storeId, clientId, storage, devtools, syncOptions },
|
|
123
127
|
}),
|
|
124
128
|
)
|
|
125
129
|
|
|
126
|
-
const getStateDbFileName = (suffix: string) => `state${suffix}@${liveStoreStorageFormatVersion}.db`
|
|
127
|
-
|
|
128
130
|
const makeDevtoolsOptions = ({
|
|
129
131
|
dbState,
|
|
130
132
|
dbEventlog,
|
|
@@ -136,8 +138,8 @@ const makeDevtoolsOptions = ({
|
|
|
136
138
|
dbEventlog: LeaderSqliteDb
|
|
137
139
|
storeId: string
|
|
138
140
|
clientId: string
|
|
139
|
-
devtools: WorkerSchema.
|
|
140
|
-
}): Effect.Effect<DevtoolsOptions,
|
|
141
|
+
devtools: WorkerSchema.LeaderWorkerInnerInitialMessagePayload['devtools']
|
|
142
|
+
}): Effect.Effect<DevtoolsOptions, UnknownError, Scope.Scope> =>
|
|
141
143
|
Effect.gen(function* () {
|
|
142
144
|
if (devtools.enabled === false) {
|
|
143
145
|
return {
|
|
@@ -161,6 +163,7 @@ const makeDevtoolsOptions = ({
|
|
|
161
163
|
sessionId: 'static', // TODO make this dynamic
|
|
162
164
|
schemaAlias: devtools.schemaAlias,
|
|
163
165
|
isLeader: true,
|
|
166
|
+
origin: undefined,
|
|
164
167
|
}),
|
|
165
168
|
port: devtools.port,
|
|
166
169
|
host: devtools.host,
|
|
@@ -180,7 +183,7 @@ const makeDevtoolsOptions = ({
|
|
|
180
183
|
eventlog: dbEventlog.metadata.persistenceInfo,
|
|
181
184
|
}
|
|
182
185
|
|
|
183
|
-
return { node, persistenceInfo, mode: 'proxy' }
|
|
186
|
+
return { node, persistenceInfo, mode: 'proxy' as const }
|
|
184
187
|
}),
|
|
185
188
|
}
|
|
186
189
|
})
|