@livestore/adapter-node 0.4.0-dev.22 → 0.4.0-dev.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/client-session/adapter.d.ts +1 -0
  3. package/dist/client-session/adapter.d.ts.map +1 -1
  4. package/dist/client-session/adapter.js +15 -23
  5. package/dist/client-session/adapter.js.map +1 -1
  6. package/dist/devtools/devtools-server.d.ts.map +1 -1
  7. package/dist/devtools/devtools-server.js +6 -6
  8. package/dist/devtools/devtools-server.js.map +1 -1
  9. package/dist/devtools/mod.d.ts +1 -1
  10. package/dist/devtools/mod.d.ts.map +1 -1
  11. package/dist/devtools/mod.js +1 -1
  12. package/dist/devtools/mod.js.map +1 -1
  13. package/dist/devtools/vite-dev-server.d.ts +25 -3
  14. package/dist/devtools/vite-dev-server.d.ts.map +1 -1
  15. package/dist/devtools/vite-dev-server.js +40 -5
  16. package/dist/devtools/vite-dev-server.js.map +1 -1
  17. package/dist/leader-thread-shared.js +2 -2
  18. package/dist/leader-thread-shared.js.map +1 -1
  19. package/dist/make-leader-worker.d.ts +1 -1
  20. package/dist/make-leader-worker.d.ts.map +1 -1
  21. package/dist/make-leader-worker.js +15 -17
  22. package/dist/make-leader-worker.js.map +1 -1
  23. package/dist/shutdown-channel.d.ts.map +1 -1
  24. package/dist/shutdown-channel.js.map +1 -1
  25. package/dist/worker-schema.d.ts +24 -24
  26. package/dist/worker-schema.d.ts.map +1 -1
  27. package/dist/worker-schema.js +16 -16
  28. package/dist/worker-schema.js.map +1 -1
  29. package/package.json +59 -19
  30. package/src/client-session/adapter.ts +26 -46
  31. package/src/devtools/devtools-server.ts +12 -10
  32. package/src/devtools/mod.ts +1 -1
  33. package/src/devtools/vite-dev-server.ts +60 -6
  34. package/src/leader-thread-shared.ts +4 -4
  35. package/src/make-leader-worker.ts +38 -47
  36. package/src/shutdown-channel.ts +1 -0
  37. package/src/worker-schema.ts +16 -16
@@ -1,12 +1,44 @@
1
1
  import path from 'node:path'
2
2
 
3
+ import type * as Vite from 'vite'
4
+
3
5
  import type { Devtools } from '@livestore/common'
4
6
  import { UnknownError } from '@livestore/common'
5
- import { livestoreDevtoolsPlugin } from '@livestore/devtools-vite'
6
7
  import { isReadonlyArray } from '@livestore/utils'
7
- import { Effect } from '@livestore/utils/effect'
8
+ import { Effect, Schema } from '@livestore/utils/effect'
8
9
  import { getFreePort } from '@livestore/utils/node'
9
- import * as Vite from 'vite'
10
+
11
+ /**
12
+ * Error thrown when @livestore/devtools-vite is not installed.
13
+ * This is a peer dependency that must be installed separately.
14
+ */
15
+ export class DevtoolsViteNotInstalledError extends Schema.TaggedError<DevtoolsViteNotInstalledError>(
16
+ '~@livestore/adapter-node/DevtoolsViteNotInstalledError',
17
+ )('DevtoolsViteNotInstalledError', {
18
+ cause: Schema.Defect,
19
+ }) {
20
+ override get message(): string {
21
+ return (
22
+ `@livestore/devtools-vite is required for devtools but not installed. ` +
23
+ `Install it with: pnpm add @livestore/devtools-vite@<version>. ` +
24
+ `Make sure to use the same version as @livestore/adapter-node.`
25
+ )
26
+ }
27
+ }
28
+
29
+ /** Error thrown when vite is not installed for the devtools server path. */
30
+ export class ViteNotInstalledError extends Schema.TaggedError<ViteNotInstalledError>(
31
+ '~@livestore/adapter-node/ViteNotInstalledError',
32
+ )('ViteNotInstalledError', {
33
+ cause: Schema.Defect,
34
+ }) {
35
+ override get message(): string {
36
+ return (
37
+ `vite is required for @livestore/adapter-node/devtools but not installed. ` +
38
+ `Install it with: pnpm add -D vite@<version>.`
39
+ )
40
+ }
41
+ }
10
42
 
11
43
  export type ViteDevtoolsOptions = {
12
44
  viteConfig?: (config: Vite.UserConfig) => Vite.UserConfig
@@ -26,8 +58,13 @@ export type ViteDevtoolsOptions = {
26
58
  }
27
59
 
28
60
  // NOTE this is currently also used in @livestore/devtools-expo
29
- export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<Vite.ViteDevServer, UnknownError> =>
61
+ export const makeViteMiddleware = (
62
+ options: ViteDevtoolsOptions,
63
+ ): Effect.Effect<Vite.ViteDevServer, DevtoolsViteNotInstalledError | ViteNotInstalledError | UnknownError> =>
30
64
  Effect.gen(function* () {
65
+ const { livestoreDevtoolsPlugin } = yield* importDevtoolsVite()
66
+ const Vite = yield* importVite()
67
+
31
68
  const cwd = process.cwd()
32
69
 
33
70
  const hmrPort = yield* getFreePort.pipe(UnknownError.mapToUnknownError)
@@ -39,13 +76,13 @@ export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<
39
76
  port: hmrPort,
40
77
  },
41
78
  // Relaxing fs access for monorepo setup
42
- fs: { strict: process.env.LS_DEV ? false : true },
79
+ fs: { strict: process.env.LS_DEV !== undefined ? false : true },
43
80
  },
44
81
  appType: 'spa',
45
82
  base: '/_livestore/',
46
83
  plugins: [
47
84
  livestoreDevtoolsPlugin({
48
- schemaPath: isReadonlyArray(options.schemaPath)
85
+ schemaPath: isReadonlyArray(options.schemaPath) === true
49
86
  ? options.schemaPath.map((schemaPath) => path.resolve(cwd, schemaPath))
50
87
  : path.resolve(cwd, options.schemaPath),
51
88
  mode: options.mode,
@@ -62,3 +99,20 @@ export const makeViteMiddleware = (options: ViteDevtoolsOptions): Effect.Effect<
62
99
 
63
100
  return viteServer
64
101
  }).pipe(Effect.withSpan('@livestore/adapter-node:devtools:makeViteServer'))
102
+
103
+ /**
104
+ * Dynamically imports @livestore/devtools-vite.
105
+ * This package is a peer dependency and may not be installed.
106
+ */
107
+ const importDevtoolsVite = () =>
108
+ Effect.tryPromise({
109
+ try: () => import('@livestore/devtools-vite'),
110
+ catch: (cause) => new DevtoolsViteNotInstalledError({ cause }),
111
+ })
112
+
113
+ /** Dynamically imports vite for the devtools-only server path. */
114
+ const importVite = () =>
115
+ Effect.tryPromise({
116
+ try: () => import('vite'),
117
+ catch: (cause) => new ViteNotInstalledError({ cause }),
118
+ })
@@ -1,7 +1,7 @@
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
  }
@@ -64,13 +64,13 @@ export const makeLeaderThread = ({
64
64
  Scope.Scope
65
65
  > =>
66
66
  Effect.gen(function* () {
67
- const runtime = yield* Effect.runtime<never>()
67
+ const runtime = yield* Effect.runtime()
68
68
 
69
69
  const schemaHashSuffix =
70
70
  schema.state.sqlite.migrations.strategy === 'manual' ? 'fixed' : schema.state.sqlite.hash.toString()
71
71
 
72
72
  const makeDb = (kind: 'state' | 'eventlog') => {
73
- if (testing?.makeLeaderThread) {
73
+ if (testing?.makeLeaderThread !== undefined) {
74
74
  return testing
75
75
  .makeLeaderThread(makeSqliteDb)
76
76
  .pipe(Effect.map(({ dbEventlog, dbState }) => (kind === 'state' ? dbState : dbEventlog)))
@@ -184,7 +184,7 @@ const makeDevtoolsOptions = ({
184
184
  eventlog: dbEventlog.metadata.persistenceInfo,
185
185
  }
186
186
 
187
- return { node, persistenceInfo, mode: 'proxy' }
187
+ return { node, persistenceInfo, mode: 'proxy' as const }
188
188
  }),
189
189
  }
190
190
  })
@@ -1,12 +1,13 @@
1
1
  import './thread-polyfill.ts'
2
-
3
2
  import inspector from 'node:inspector'
4
3
 
5
- if (process.execArgv.includes('--inspect')) {
4
+ if (process.execArgv.includes('--inspect') === true) {
6
5
  inspector.open()
7
6
  inspector.waitForDebugger()
8
7
  }
9
8
 
9
+ import type * as otel from '@opentelemetry/api'
10
+
10
11
  import type { SyncOptions } from '@livestore/common'
11
12
  import { LogConfig, UnknownError } from '@livestore/common'
12
13
  import type { StreamEventsOptions } from '@livestore/common/leader-thread'
@@ -17,7 +18,6 @@ import { loadSqlite3Wasm } from '@livestore/sqlite-wasm/load-wasm'
17
18
  import { sqliteDbFactory } from '@livestore/sqlite-wasm/node'
18
19
  import { Effect, FetchHttpClient, Layer, OtelTracer, Schema, Stream, WorkerRunner } from '@livestore/utils/effect'
19
20
  import { PlatformNode } from '@livestore/utils/node'
20
- import type * as otel from '@opentelemetry/api'
21
21
 
22
22
  import type { TestingOverrides } from './leader-thread-shared.ts'
23
23
  import { makeLeaderThread } from './leader-thread-shared.ts'
@@ -42,7 +42,7 @@ export const makeWorker = (options: WorkerOptions) => {
42
42
  }
43
43
 
44
44
  export const makeWorkerEffect = (options: WorkerOptions) => {
45
- const TracingLive = options.otelOptions?.tracer
45
+ const TracingLive = options.otelOptions?.tracer !== undefined
46
46
  ? Layer.unwrapEffect(Effect.map(OtelTracer.make, Layer.setTracer)).pipe(
47
47
  Layer.provideMerge(Layer.succeed(OtelTracer.OtelTracer, options.otelOptions.tracer)),
48
48
  )
@@ -103,69 +103,60 @@ export const makeWorkerEffect = (options: WorkerOptions) => {
103
103
  ),
104
104
  Export: () =>
105
105
  Effect.andThen(LeaderThreadCtx, (_) => _.dbState.export()).pipe(
106
- UnknownError.mapToUnknownError,
107
106
  Effect.withSpan('@livestore/adapter-node:worker:Export'),
108
107
  ),
109
108
  ExportEventlog: () =>
110
109
  Effect.andThen(LeaderThreadCtx, (_) => _.dbEventlog.export()).pipe(
111
- UnknownError.mapToUnknownError,
112
110
  Effect.withSpan('@livestore/adapter-node:worker:ExportEventlog'),
113
111
  ),
114
- GetLeaderHead: () =>
115
- Effect.gen(function* () {
116
- const workerCtx = yield* LeaderThreadCtx
117
- return Eventlog.getClientHeadFromDb(workerCtx.dbEventlog)
118
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('@livestore/adapter-node:worker:GetLeaderHead')),
119
- GetLeaderSyncState: () =>
120
- Effect.gen(function* () {
121
- const workerCtx = yield* LeaderThreadCtx
122
- return yield* workerCtx.syncProcessor.syncState
123
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('@livestore/adapter-node:worker:GetLeaderSyncState')),
112
+ GetLeaderHead: Effect.fn('@livestore/adapter-node:worker:GetLeaderHead')(function* () {
113
+ const workerCtx = yield* LeaderThreadCtx
114
+ return Eventlog.getClientHeadFromDb(workerCtx.dbEventlog)
115
+ }),
116
+ GetLeaderSyncState: Effect.fn('@livestore/adapter-node:worker:GetLeaderSyncState')(function* () {
117
+ const workerCtx = yield* LeaderThreadCtx
118
+ return yield* workerCtx.syncProcessor.syncState
119
+ }),
124
120
  SyncStateStream: () =>
125
121
  Effect.gen(function* () {
126
122
  const workerCtx = yield* LeaderThreadCtx
127
123
  return workerCtx.syncProcessor.syncState.changes
128
124
  }).pipe(Stream.unwrapScoped),
129
- GetNetworkStatus: () =>
130
- Effect.gen(function* () {
131
- const workerCtx = yield* LeaderThreadCtx
132
- return yield* workerCtx.networkStatus
133
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('@livestore/adapter-node:worker:GetNetworkStatus')),
125
+ GetNetworkStatus: Effect.fn('@livestore/adapter-node:worker:GetNetworkStatus')(function* () {
126
+ const workerCtx = yield* LeaderThreadCtx
127
+ return yield* workerCtx.networkStatus
128
+ }),
134
129
  NetworkStatusStream: () =>
135
130
  Effect.gen(function* () {
136
131
  const workerCtx = yield* LeaderThreadCtx
137
132
  return workerCtx.networkStatus.changes
138
133
  }).pipe(Stream.unwrapScoped),
139
- GetRecreateSnapshot: () =>
140
- Effect.gen(function* () {
141
- const workerCtx = yield* LeaderThreadCtx
142
- // const result = yield* Deferred.await(workerCtx.initialSetupDeferred)
143
- // NOTE we can only return the cached snapshot once as it's transferred (i.e. disposed), so we need to set it to undefined
144
- // const cachedSnapshot =
145
- // result._tag === 'Recreate' ? yield* Ref.getAndSet(result.snapshotRef, undefined) : undefined
146
- // return cachedSnapshot ?? workerCtx.db.export()
147
- const snapshot = workerCtx.dbState.export()
148
- return { snapshot, migrationsReport: workerCtx.initialState.migrationsReport }
149
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('@livestore/adapter-node:worker:GetRecreateSnapshot')),
150
- Shutdown: () =>
151
- // @effect-diagnostics-next-line unnecessaryEffectGen:off
152
- Effect.gen(function* () {
153
- // const { db, dbEventlog } = yield* LeaderThreadCtx
154
- yield* Effect.logDebug('[@livestore/adapter-node:worker] Shutdown')
134
+ GetRecreateSnapshot: Effect.fn('@livestore/adapter-node:worker:GetRecreateSnapshot')(function* () {
135
+ const workerCtx = yield* LeaderThreadCtx
136
+ // const result = yield* Deferred.await(workerCtx.initialSetupDeferred)
137
+ // NOTE we can only return the cached snapshot once as it's transferred (i.e. disposed), so we need to set it to undefined
138
+ // const cachedSnapshot =
139
+ // result._tag === 'Recreate' ? yield* Ref.getAndSet(result.snapshotRef, undefined) : undefined
140
+ // return cachedSnapshot ?? workerCtx.db.export()
141
+ const snapshot = workerCtx.dbState.export()
142
+ return { snapshot, migrationsReport: workerCtx.initialState.migrationsReport }
143
+ }),
144
+ Shutdown: Effect.fn('@livestore/adapter-node:worker:Shutdown')(function* () {
145
+ // const { db, dbEventlog } = yield* LeaderThreadCtx
146
+ yield* Effect.logDebug('[@livestore/adapter-node:worker] Shutdown')
155
147
 
156
- // if (devtools.enabled) {
157
- // yield* FiberSet.clear(devtools.connections)
158
- // }
159
- // db.close()
160
- // dbEventlog.close()
148
+ // if (devtools.enabled) {
149
+ // yield* FiberSet.clear(devtools.connections)
150
+ // }
151
+ // db.close()
152
+ // dbEventlog.close()
161
153
 
162
- // Buy some time for Otel to flush
163
- // TODO find a cleaner way to do this
164
- // yield* Effect.sleep(1000)
165
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('@livestore/adapter-node:worker:Shutdown')),
154
+ // Buy some time for Otel to flush
155
+ // TODO find a cleaner way to do this
156
+ // yield* Effect.sleep(1000)
157
+ }),
166
158
  ExtraDevtoolsMessage: ({ message }) =>
167
159
  Effect.andThen(LeaderThreadCtx, (_) => _.extraIncomingMessagesQueue.offer(message)).pipe(
168
- UnknownError.mapToUnknownError,
169
160
  Effect.withSpan('@livestore/adapter-node:worker:ExtraDevtoolsMessage'),
170
161
  ),
171
162
  }).pipe(
@@ -1,5 +1,6 @@
1
1
  import { ShutdownChannel } from '@livestore/common/leader-thread'
2
2
  import type { Effect, Scope } from '@livestore/utils/effect'
3
+
3
4
  import { makeBroadcastChannel } from './webchannel.ts'
4
5
 
5
6
  export const makeShutdownChannel = (
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BootStatus,
3
3
  Devtools,
4
- LeaderAheadError,
4
+ RejectedPushError,
5
5
  MigrationsReport,
6
6
  SyncBackend,
7
7
  SyncState,
@@ -62,7 +62,7 @@ export class LeaderWorkerOuterInitialMessage extends Schema.TaggedRequest<Leader
62
62
  {
63
63
  payload: { port: Transferable.MessagePort },
64
64
  success: Schema.Void,
65
- failure: UnknownError,
65
+ failure: Schema.Never,
66
66
  },
67
67
  ) {}
68
68
 
@@ -98,7 +98,7 @@ export class LeaderWorkerInnerBootStatusStream extends Schema.TaggedRequest<Lead
98
98
  {
99
99
  payload: {},
100
100
  success: BootStatus,
101
- failure: UnknownError,
101
+ failure: Schema.Never,
102
102
  },
103
103
  ) {}
104
104
 
@@ -109,7 +109,7 @@ export class LeaderWorkerInnerPullStream extends Schema.TaggedRequest<LeaderWork
109
109
  success: Schema.Struct({
110
110
  payload: SyncState.PayloadUpstream,
111
111
  }),
112
- failure: UnknownError,
112
+ failure: Schema.Never,
113
113
  }) {}
114
114
 
115
115
  export class LeaderWorkerInnerStreamEvents extends Schema.TaggedRequest<LeaderWorkerInnerStreamEvents>()(
@@ -117,7 +117,7 @@ export class LeaderWorkerInnerStreamEvents extends Schema.TaggedRequest<LeaderWo
117
117
  {
118
118
  payload: StreamEventsOptionsFields,
119
119
  success: LiveStoreEvent.Client.Encoded,
120
- failure: UnknownError,
120
+ failure: Schema.Never,
121
121
  },
122
122
  ) {}
123
123
 
@@ -128,14 +128,14 @@ export class LeaderWorkerInnerPushToLeader extends Schema.TaggedRequest<LeaderWo
128
128
  batch: Schema.Array(Schema.typeSchema(LiveStoreEvent.Client.Encoded)),
129
129
  },
130
130
  success: Schema.Void as Schema.Schema<void>,
131
- failure: Schema.Union(UnknownError, LeaderAheadError),
131
+ failure: RejectedPushError,
132
132
  },
133
133
  ) {}
134
134
 
135
135
  export class LeaderWorkerInnerExport extends Schema.TaggedRequest<LeaderWorkerInnerExport>()('Export', {
136
136
  payload: {},
137
137
  success: Transferable.Uint8Array as Schema.Schema<Uint8Array<ArrayBuffer>>,
138
- failure: UnknownError,
138
+ failure: Schema.Never,
139
139
  }) {}
140
140
 
141
141
  export class LeaderWorkerInnerGetRecreateSnapshot extends Schema.TaggedRequest<LeaderWorkerInnerGetRecreateSnapshot>()(
@@ -146,7 +146,7 @@ export class LeaderWorkerInnerGetRecreateSnapshot extends Schema.TaggedRequest<L
146
146
  snapshot: Transferable.Uint8Array as Schema.Schema<Uint8Array<ArrayBuffer>>,
147
147
  migrationsReport: MigrationsReport,
148
148
  }),
149
- failure: UnknownError,
149
+ failure: Schema.Never,
150
150
  },
151
151
  ) {}
152
152
 
@@ -155,7 +155,7 @@ export class LeaderWorkerInnerExportEventlog extends Schema.TaggedRequest<Leader
155
155
  {
156
156
  payload: {},
157
157
  success: Transferable.Uint8Array as Schema.Schema<Uint8Array<ArrayBuffer>>,
158
- failure: UnknownError,
158
+ failure: Schema.Never,
159
159
  },
160
160
  ) {}
161
161
 
@@ -164,7 +164,7 @@ export class LeaderWorkerInnerGetLeaderHead extends Schema.TaggedRequest<LeaderW
164
164
  {
165
165
  payload: {},
166
166
  success: Schema.typeSchema(EventSequenceNumber.Client.Composite),
167
- failure: UnknownError,
167
+ failure: Schema.Never,
168
168
  },
169
169
  ) {}
170
170
 
@@ -173,7 +173,7 @@ export class LeaderWorkerInnerGetLeaderSyncState extends Schema.TaggedRequest<Le
173
173
  {
174
174
  payload: {},
175
175
  success: SyncState.SyncState,
176
- failure: UnknownError,
176
+ failure: Schema.Never,
177
177
  },
178
178
  ) {}
179
179
 
@@ -182,7 +182,7 @@ export class LeaderWorkerInnerSyncStateStream extends Schema.TaggedRequest<Leade
182
182
  {
183
183
  payload: {},
184
184
  success: SyncState.SyncState,
185
- failure: UnknownError,
185
+ failure: Schema.Never,
186
186
  },
187
187
  ) {}
188
188
 
@@ -191,7 +191,7 @@ export class LeaderWorkerInnerGetNetworkStatus extends Schema.TaggedRequest<Lead
191
191
  {
192
192
  payload: {},
193
193
  success: SyncBackend.NetworkStatus,
194
- failure: UnknownError,
194
+ failure: Schema.Never,
195
195
  },
196
196
  ) {}
197
197
 
@@ -200,14 +200,14 @@ export class LeaderWorkerInnerNetworkStatusStream extends Schema.TaggedRequest<L
200
200
  {
201
201
  payload: {},
202
202
  success: SyncBackend.NetworkStatus,
203
- failure: UnknownError,
203
+ failure: Schema.Never,
204
204
  },
205
205
  ) {}
206
206
 
207
207
  export class LeaderWorkerInnerShutdown extends Schema.TaggedRequest<LeaderWorkerInnerShutdown>()('Shutdown', {
208
208
  payload: {},
209
209
  success: Schema.Void,
210
- failure: UnknownError,
210
+ failure: Schema.Never,
211
211
  }) {}
212
212
 
213
213
  export class LeaderWorkerInnerExtraDevtoolsMessage extends Schema.TaggedRequest<LeaderWorkerInnerExtraDevtoolsMessage>()(
@@ -217,7 +217,7 @@ export class LeaderWorkerInnerExtraDevtoolsMessage extends Schema.TaggedRequest<
217
217
  message: Devtools.Leader.MessageToApp,
218
218
  },
219
219
  success: Schema.Void,
220
- failure: UnknownError,
220
+ failure: Schema.Never,
221
221
  },
222
222
  ) {}
223
223