@livestore/livestore 0.4.0 → 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/SqliteDbWrapper.d.ts.map +1 -1
- package/dist/SqliteDbWrapper.js +7 -5
- package/dist/SqliteDbWrapper.js.map +1 -1
- package/dist/SqliteDbWrapper.test.js +20 -3
- package/dist/SqliteDbWrapper.test.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +15 -15
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +17 -17
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/LiveStore.test.js +5 -6
- package/dist/effect/LiveStore.test.js.map +1 -1
- package/dist/live-queries/base-class.d.ts +19 -2
- package/dist/live-queries/base-class.d.ts.map +1 -1
- package/dist/live-queries/base-class.js +28 -2
- package/dist/live-queries/base-class.js.map +1 -1
- package/dist/live-queries/computed.d.ts.map +1 -1
- package/dist/live-queries/computed.js +4 -4
- package/dist/live-queries/computed.js.map +1 -1
- package/dist/live-queries/db-query.d.ts +2 -2
- package/dist/live-queries/db-query.d.ts.map +1 -1
- package/dist/live-queries/db-query.js +26 -17
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +9 -9
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/live-queries/signal.d.ts.map +1 -1
- package/dist/live-queries/signal.js +2 -2
- package/dist/live-queries/signal.js.map +1 -1
- package/dist/live-queries/signal.test.js +2 -2
- package/dist/live-queries/signal.test.js.map +1 -1
- package/dist/reactive.d.ts +1 -1
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +20 -1
- package/dist/reactive.js.map +1 -1
- package/dist/store/StoreRegistry.d.ts +12 -12
- package/dist/store/StoreRegistry.d.ts.map +1 -1
- package/dist/store/StoreRegistry.js +24 -24
- package/dist/store/StoreRegistry.js.map +1 -1
- package/dist/store/StoreRegistry.test.js +62 -59
- package/dist/store/StoreRegistry.test.js.map +1 -1
- package/dist/store/create-store.d.ts +12 -15
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +43 -24
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/devtools.d.ts +1 -2
- package/dist/store/devtools.d.ts.map +1 -1
- package/dist/store/devtools.js +3 -2
- package/dist/store/devtools.js.map +1 -1
- package/dist/store/store-eventstream.test.js +5 -5
- package/dist/store/store-eventstream.test.js.map +1 -1
- package/dist/store/store-types.d.ts +10 -28
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js +2 -38
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store-types.test.js +1 -1
- package/dist/store/store.d.ts +2 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +114 -56
- package/dist/store/store.js.map +1 -1
- package/dist/utils/dev.js +1 -1
- package/dist/utils/dev.js.map +1 -1
- package/dist/utils/stack-info.d.ts.map +1 -1
- package/dist/utils/stack-info.js +2 -1
- package/dist/utils/stack-info.js.map +1 -1
- package/dist/utils/tests/fixture.d.ts +26 -34
- package/dist/utils/tests/fixture.d.ts.map +1 -1
- package/package.json +14 -24
- package/src/SqliteDbWrapper.test.ts +25 -3
- package/src/SqliteDbWrapper.ts +12 -9
- package/src/effect/LiveStore.test.ts +16 -16
- package/src/effect/LiveStore.ts +79 -50
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +273 -49
- package/src/live-queries/base-class.ts +38 -6
- package/src/live-queries/computed.ts +5 -5
- package/src/live-queries/db-query.test.ts +9 -9
- package/src/live-queries/db-query.ts +42 -30
- package/src/live-queries/signal.test.ts +2 -2
- package/src/live-queries/signal.ts +3 -3
- package/src/reactive.ts +45 -35
- package/src/store/StoreRegistry.test.ts +62 -59
- package/src/store/StoreRegistry.ts +49 -38
- package/src/store/create-store.ts +85 -51
- package/src/store/devtools.ts +283 -283
- package/src/store/store-eventstream.test.ts +16 -7
- package/src/store/store-types.test.ts +1 -1
- package/src/store/store-types.ts +10 -56
- package/src/store/store.ts +148 -71
- package/src/utils/dev.ts +1 -1
- package/src/utils/stack-info.ts +4 -1
|
@@ -2,18 +2,17 @@ import * as otel from '@opentelemetry/api'
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
type Adapter,
|
|
5
|
+
type BackendIdMismatchError,
|
|
5
6
|
type BootStatus,
|
|
6
7
|
type ClientSession,
|
|
7
8
|
type ClientSessionDevtoolsChannel,
|
|
8
|
-
type ClientSessionSyncProcessorSimulationParams,
|
|
9
9
|
type IntentionalShutdownCause,
|
|
10
|
-
LogConfig,
|
|
11
10
|
type MaterializeError,
|
|
12
|
-
type BackendIdMismatchError,
|
|
13
11
|
type MigrationsReport,
|
|
14
12
|
provideOtel,
|
|
15
13
|
type ServerAheadError,
|
|
16
14
|
UnknownError,
|
|
15
|
+
type LogConfig,
|
|
17
16
|
} from '@livestore/common'
|
|
18
17
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
19
18
|
import { isDevEnv, LS_DEV, omitUndefineds } from '@livestore/utils'
|
|
@@ -27,7 +26,7 @@ import {
|
|
|
27
26
|
Layer,
|
|
28
27
|
OtelTracer,
|
|
29
28
|
Queue,
|
|
30
|
-
|
|
29
|
+
References,
|
|
31
30
|
Schema,
|
|
32
31
|
Scope,
|
|
33
32
|
TaskTracing,
|
|
@@ -43,6 +42,14 @@ import type {
|
|
|
43
42
|
import { StoreInternalsSymbol } from './store-types.ts'
|
|
44
43
|
import { STORE_DEFAULT_PARAMS, Store } from './store.ts'
|
|
45
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Hard upper bound (ms) for the detached shutdown drain. A dead/unresponsive leader must not keep
|
|
47
|
+
* the drain (and therefore the lifetime scope) alive forever; after this bound the scope is
|
|
48
|
+
* force-closed. Kept comfortably above the 1s caller-side soft wait so that a still-progressing
|
|
49
|
+
* in-flight leader push is allowed to finish rather than being interrupted.
|
|
50
|
+
*/
|
|
51
|
+
const SHUTDOWN_DRAIN_HARD_TIMEOUT_MS = 30_000
|
|
52
|
+
|
|
46
53
|
declare global {
|
|
47
54
|
/** Store instances for console debugging */
|
|
48
55
|
var __debugLiveStore: Record<string, Store<any, any>> | undefined
|
|
@@ -64,29 +71,28 @@ declare global {
|
|
|
64
71
|
* const { store } = yield* AppStore.Tag
|
|
65
72
|
* ```
|
|
66
73
|
*/
|
|
67
|
-
export class LiveStoreContextRunning extends Context.
|
|
68
|
-
LiveStoreContextRunning,
|
|
69
|
-
|
|
70
|
-
>() {
|
|
74
|
+
export class LiveStoreContextRunning extends Context.Service<LiveStoreContextRunning, LiveStoreContextRunning_>()(
|
|
75
|
+
'@livestore/livestore/effect/LiveStoreContextRunning',
|
|
76
|
+
) {
|
|
71
77
|
static fromDeferred = Effect.gen(function* () {
|
|
72
78
|
const deferred = yield* DeferredStoreContext
|
|
73
|
-
const ctx = yield* deferred
|
|
74
|
-
return Layer.succeed(LiveStoreContextRunning, ctx)
|
|
75
|
-
}).pipe(Layer.
|
|
79
|
+
const ctx = yield* Deferred.await(deferred)
|
|
80
|
+
return Layer.succeed(LiveStoreContextRunning, LiveStoreContextRunning.of(ctx))
|
|
81
|
+
}).pipe(Layer.unwrap)
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
/**
|
|
79
85
|
* @deprecated Use `StoreContext.DeferredTag` from `makeStoreContext()` instead.
|
|
80
86
|
*/
|
|
81
|
-
export class DeferredStoreContext extends Context.
|
|
87
|
+
export class DeferredStoreContext extends Context.Service<
|
|
82
88
|
DeferredStoreContext,
|
|
83
|
-
Deferred.Deferred<LiveStoreContextRunning['
|
|
84
|
-
>() {}
|
|
89
|
+
Deferred.Deferred<LiveStoreContextRunning['Service'], UnknownError>
|
|
90
|
+
>()('@livestore/livestore/effect/DeferredStoreContext') {}
|
|
85
91
|
|
|
86
92
|
export type LiveStoreContextProps<
|
|
87
93
|
TSchema extends LiveStoreSchema,
|
|
88
94
|
TContext = {},
|
|
89
|
-
TSyncPayloadSchema extends Schema.Schema
|
|
95
|
+
TSyncPayloadSchema extends Schema.Codec<Schema.Json, Schema.Json> = typeof Schema.Json,
|
|
90
96
|
> = {
|
|
91
97
|
schema: TSchema
|
|
92
98
|
/**
|
|
@@ -115,7 +121,7 @@ export type LiveStoreContextProps<
|
|
|
115
121
|
/**
|
|
116
122
|
* Schema describing the shape of the sync payload and used to encode it.
|
|
117
123
|
*
|
|
118
|
-
* - If omitted, `Schema.
|
|
124
|
+
* - If omitted, `Schema.Json` is used (no additional typing/validation).
|
|
119
125
|
* - Prefer exporting a schema from your app (e.g. `export const SyncPayload = Schema.Struct({ authToken: Schema.String })`)
|
|
120
126
|
* and pass it here to get end-to-end type safety and validation.
|
|
121
127
|
*/
|
|
@@ -130,14 +136,15 @@ export type LiveStoreContextProps<
|
|
|
130
136
|
* const SyncPayload = Schema.Struct({ authToken: Schema.String })
|
|
131
137
|
* useStore({ ..., syncPayloadSchema: SyncPayload, syncPayload: { authToken: '...' } })
|
|
132
138
|
*/
|
|
133
|
-
syncPayload?:
|
|
139
|
+
syncPayload?: TSyncPayloadSchema['Type']
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
export interface CreateStoreOptions<
|
|
137
143
|
TSchema extends LiveStoreSchema,
|
|
138
144
|
TContext = {},
|
|
139
|
-
TSyncPayloadSchema extends Schema.Schema
|
|
140
|
-
>
|
|
145
|
+
TSyncPayloadSchema extends Schema.Codec<Schema.Json, Schema.Json> = typeof Schema.Json,
|
|
146
|
+
>
|
|
147
|
+
extends LogConfig.LoggerOptions {
|
|
141
148
|
/** The LiveStore schema defining tables, events, and materializers. */
|
|
142
149
|
schema: TSchema
|
|
143
150
|
/** Adapter used for data storage and synchronization. */
|
|
@@ -192,7 +199,7 @@ export interface CreateStoreOptions<
|
|
|
192
199
|
/**
|
|
193
200
|
* Schema describing the shape of the sync payload and used to encode it.
|
|
194
201
|
*
|
|
195
|
-
* - If omitted, `Schema.
|
|
202
|
+
* - If omitted, `Schema.Json` is used (no additional typing/validation).
|
|
196
203
|
* - Prefer exporting a schema from your app (e.g. `export const SyncPayload = Schema.Struct({ authToken: Schema.String })`)
|
|
197
204
|
* and pass it here to get end-to-end type safety and validation.
|
|
198
205
|
*/
|
|
@@ -206,16 +213,13 @@ export interface CreateStoreOptions<
|
|
|
206
213
|
*
|
|
207
214
|
* @default undefined
|
|
208
215
|
*/
|
|
209
|
-
syncPayload?:
|
|
216
|
+
syncPayload?: TSyncPayloadSchema['Type']
|
|
210
217
|
/** Options provided to the Store constructor. */
|
|
211
218
|
params?: {
|
|
212
219
|
/** Max events pushed to the leader per write batch. */
|
|
213
220
|
leaderPushBatchSize?: number
|
|
214
221
|
/** Chunk size used when the stream replays confirmed events. */
|
|
215
222
|
eventQueryBatchSize?: number
|
|
216
|
-
simulation?: {
|
|
217
|
-
clientSessionSyncProcessor: typeof ClientSessionSyncProcessorSimulationParams.Type
|
|
218
|
-
}
|
|
219
223
|
}
|
|
220
224
|
debug?: {
|
|
221
225
|
instanceId?: string
|
|
@@ -225,7 +229,7 @@ export interface CreateStoreOptions<
|
|
|
225
229
|
export type CreateStoreOptionsPromise<
|
|
226
230
|
TSchema extends LiveStoreSchema = LiveStoreSchema.Any,
|
|
227
231
|
TContext = {},
|
|
228
|
-
TSyncPayloadSchema extends Schema.Schema
|
|
232
|
+
TSyncPayloadSchema extends Schema.Codec<Schema.Json, Schema.Json> = typeof Schema.Json,
|
|
229
233
|
> = CreateStoreOptions<TSchema, TContext, TSyncPayloadSchema> & {
|
|
230
234
|
signal?: AbortSignal
|
|
231
235
|
otelOptions?: Partial<OtelOptions>
|
|
@@ -235,7 +239,7 @@ export type CreateStoreOptionsPromise<
|
|
|
235
239
|
export const createStorePromise = async <
|
|
236
240
|
TSchema extends LiveStoreSchema = LiveStoreSchema.Any,
|
|
237
241
|
TContext = {},
|
|
238
|
-
TSyncPayloadSchema extends Schema.Schema
|
|
242
|
+
TSyncPayloadSchema extends Schema.Codec<Schema.Json, Schema.Json> = typeof Schema.Json,
|
|
239
243
|
>({
|
|
240
244
|
signal,
|
|
241
245
|
otelOptions,
|
|
@@ -243,15 +247,15 @@ export const createStorePromise = async <
|
|
|
243
247
|
}: CreateStoreOptionsPromise<TSchema, TContext, TSyncPayloadSchema>): Promise<Store<TSchema, TContext>> =>
|
|
244
248
|
Effect.gen(function* () {
|
|
245
249
|
const scope = yield* Scope.make()
|
|
246
|
-
const
|
|
250
|
+
const services = yield* Effect.context()
|
|
247
251
|
|
|
248
252
|
if (signal !== undefined) {
|
|
249
253
|
signal.addEventListener('abort', () => {
|
|
250
|
-
Scope.close(scope, Exit.void).pipe(Effect.tapCauseLogPretty,
|
|
254
|
+
Scope.close(scope, Exit.void).pipe(Effect.tapCauseLogPretty, Effect.runForkWith(services))
|
|
251
255
|
})
|
|
252
256
|
}
|
|
253
257
|
|
|
254
|
-
return yield* createStore({ ...options }).pipe(Scope.
|
|
258
|
+
return yield* createStore({ ...options }).pipe(Scope.provide(scope))
|
|
255
259
|
}).pipe(
|
|
256
260
|
Effect.withSpan('createStore', {
|
|
257
261
|
attributes: { storeId: options.storeId, disableDevtools: options.disableDevtools },
|
|
@@ -259,14 +263,19 @@ export const createStorePromise = async <
|
|
|
259
263
|
provideOtel(omitUndefineds({ parentSpanContext: otelOptions?.rootSpanContext, otelTracer: otelOptions?.tracer })),
|
|
260
264
|
Effect.tapCauseLogPretty,
|
|
261
265
|
Effect.annotateLogs({ thread: 'window' }),
|
|
262
|
-
|
|
266
|
+
Effect.provide(
|
|
267
|
+
Layer.mergeAll(
|
|
268
|
+
options.logger ?? Layer.empty,
|
|
269
|
+
Layer.succeed(References.MinimumLogLevel, options.logLevel ?? (isDevEnv() === true ? 'Debug' : 'Info')),
|
|
270
|
+
),
|
|
271
|
+
),
|
|
263
272
|
Effect.runPromise,
|
|
264
273
|
)
|
|
265
274
|
|
|
266
275
|
export const createStore = <
|
|
267
276
|
TSchema extends LiveStoreSchema = LiveStoreSchema.Any,
|
|
268
277
|
TContext = {},
|
|
269
|
-
TSyncPayloadSchema extends Schema.Schema
|
|
278
|
+
TSyncPayloadSchema extends Schema.Codec<Schema.Json, Schema.Json> = typeof Schema.Json,
|
|
270
279
|
>({
|
|
271
280
|
schema,
|
|
272
281
|
adapter,
|
|
@@ -295,18 +304,20 @@ export const createStore = <
|
|
|
295
304
|
yield* Effect.addFinalizer((_) => Scope.close(lifetimeScope, _))
|
|
296
305
|
|
|
297
306
|
const debugInstanceId = debug?.instanceId ?? nanoid(10)
|
|
298
|
-
const resolvedSyncPayloadSchema = (syncPayloadSchema ?? Schema.
|
|
307
|
+
const resolvedSyncPayloadSchema = (syncPayloadSchema ?? Schema.Json) as TSyncPayloadSchema
|
|
299
308
|
|
|
300
309
|
return yield* Effect.gen(function* () {
|
|
301
310
|
const span = yield* OtelTracer.currentOtelSpan.pipe(Effect.orDie)
|
|
302
311
|
const otelRootSpanContext = otel.trace.setSpan(otel.context.active(), span)
|
|
303
312
|
const otelTracer = yield* OtelTracer.OtelTracer
|
|
304
313
|
|
|
305
|
-
const bootStatusQueue = yield* Queue.unbounded<BootStatus>()
|
|
314
|
+
const bootStatusQueue = yield* Effect.acquireRelease(Queue.unbounded<BootStatus>(), Queue.shutdown)
|
|
306
315
|
|
|
307
316
|
yield* Queue.take(bootStatusQueue).pipe(
|
|
308
317
|
Effect.tapSync((status) => onBootStatus?.(status)),
|
|
309
|
-
Effect.tap((status) =>
|
|
318
|
+
Effect.tap((status) =>
|
|
319
|
+
status.stage === 'done' ? Queue.shutdown(bootStatusQueue).pipe(Effect.asVoid) : Effect.void,
|
|
320
|
+
),
|
|
310
321
|
Effect.forever,
|
|
311
322
|
Effect.tapCauseLogPretty,
|
|
312
323
|
Effect.forkScoped,
|
|
@@ -316,23 +327,40 @@ export const createStore = <
|
|
|
316
327
|
|
|
317
328
|
const connectDevtoolsToStore_ = (storeDevtoolsChannel: ClientSessionDevtoolsChannel) =>
|
|
318
329
|
Effect.gen(function* () {
|
|
319
|
-
const store = yield* storeDeferred
|
|
330
|
+
const store = yield* Deferred.await(storeDeferred)
|
|
320
331
|
yield* connectDevtoolsToStore({ storeDevtoolsChannel, store })
|
|
321
332
|
})
|
|
322
333
|
|
|
323
|
-
const
|
|
334
|
+
const services = yield* Effect.context<Scope.Scope>()
|
|
335
|
+
let shutdownSyncProcessor: ((exit: Exit.Exit<unknown, unknown>) => Effect.Effect<void>) | undefined
|
|
324
336
|
|
|
325
337
|
const shutdown = (
|
|
326
|
-
exit: Exit.Exit<
|
|
327
|
-
IntentionalShutdownCause,
|
|
328
|
-
UnknownError | MaterializeError | BackendIdMismatchError
|
|
329
|
-
>,
|
|
338
|
+
exit: Exit.Exit<IntentionalShutdownCause, UnknownError | MaterializeError | BackendIdMismatchError>,
|
|
330
339
|
) =>
|
|
331
340
|
Effect.gen(function* () {
|
|
332
|
-
|
|
341
|
+
// Hard outer bound on the DETACHED teardown: the processor drain `awaitEmpty`s the
|
|
342
|
+
// leader-push worker, which never completes if the leader is dead/unresponsive. Without a
|
|
343
|
+
// bound the drain would block forever, so `Scope.close(lifetimeScope)` (in `ensuring`)
|
|
344
|
+
// would never run and the lifetime scope + its resources would leak indefinitely (a later
|
|
345
|
+
// `createStore`/registry dispose on the same `storeId` would observe a never-closed store).
|
|
346
|
+
// Drain up to the bound, then force-close the scope regardless. The bound exceeds the
|
|
347
|
+
// caller-side wait below so an in-flight (but progressing) push is not cut short.
|
|
348
|
+
const closeFiber = yield* (shutdownSyncProcessor?.(exit) ?? Effect.void).pipe(
|
|
349
|
+
Effect.timeout(SHUTDOWN_DRAIN_HARD_TIMEOUT_MS),
|
|
350
|
+
Effect.catchTag('TimeoutError', () =>
|
|
351
|
+
Effect.logError(
|
|
352
|
+
`@livestore/livestore:shutdown: drain exceeded hard bound of ${SHUTDOWN_DRAIN_HARD_TIMEOUT_MS}ms; forcing scope close`,
|
|
353
|
+
),
|
|
354
|
+
),
|
|
355
|
+
Effect.ensuring(Scope.close(lifetimeScope, exit)),
|
|
356
|
+
Effect.forkDetach,
|
|
357
|
+
)
|
|
358
|
+
// Caller-side soft wait: stop blocking the shutdown() caller after 1s without cancelling
|
|
359
|
+
// the detached teardown above (which remains bounded by SHUTDOWN_DRAIN_HARD_TIMEOUT_MS).
|
|
360
|
+
yield* Fiber.join(closeFiber).pipe(
|
|
333
361
|
Effect.logWarnIfTakesLongerThan({ label: '@livestore/livestore:shutdown', duration: 500 }),
|
|
334
362
|
Effect.timeout(1000),
|
|
335
|
-
Effect.catchTag('
|
|
363
|
+
Effect.catchTag('TimeoutError', () =>
|
|
336
364
|
Effect.logError('@livestore/livestore:shutdown: Timed out after 1 second'),
|
|
337
365
|
),
|
|
338
366
|
)
|
|
@@ -344,7 +372,7 @@ export const createStore = <
|
|
|
344
372
|
yield* Effect.logDebug('LiveStore shutdown complete')
|
|
345
373
|
}).pipe(
|
|
346
374
|
Effect.withSpan('@livestore/livestore:shutdown'),
|
|
347
|
-
Effect.provide(
|
|
375
|
+
Effect.provide(services),
|
|
348
376
|
Effect.tapCauseLogPretty,
|
|
349
377
|
// Given that the shutdown flow might also interrupt the effect that is calling the shutdown,
|
|
350
378
|
// we want to detach the shutdown effect so it's not interrupted by itself
|
|
@@ -355,7 +383,7 @@ export const createStore = <
|
|
|
355
383
|
const syncPayloadEncoded =
|
|
356
384
|
syncPayload === undefined
|
|
357
385
|
? undefined
|
|
358
|
-
: yield* Schema.
|
|
386
|
+
: yield* Schema.encodeEffect(resolvedSyncPayloadSchema)(syncPayload).pipe(UnknownError.mapToUnknownError)
|
|
359
387
|
|
|
360
388
|
const clientSession: ClientSession = yield* adapter({
|
|
361
389
|
schema,
|
|
@@ -385,10 +413,10 @@ export const createStore = <
|
|
|
385
413
|
schema,
|
|
386
414
|
context,
|
|
387
415
|
otelOptions: { tracer: otelTracer, rootSpanContext: otelRootSpanContext },
|
|
388
|
-
effectContext: { lifetimeScope,
|
|
416
|
+
effectContext: { lifetimeScope, services },
|
|
389
417
|
// TODO find a better way to detect if we're running LiveStore in the LiveStore devtools
|
|
390
418
|
// But for now this is a good enough approximation with little downsides
|
|
391
|
-
__runningInDevtools: !
|
|
419
|
+
__runningInDevtools: !getDevtoolsEnabled(disableDevtools),
|
|
392
420
|
confirmUnsavedChanges,
|
|
393
421
|
// NOTE during boot we're not yet executing events in a batched context
|
|
394
422
|
// but only set the provided `batchUpdates` function after boot
|
|
@@ -397,26 +425,32 @@ export const createStore = <
|
|
|
397
425
|
params: {
|
|
398
426
|
leaderPushBatchSize: params?.leaderPushBatchSize ?? STORE_DEFAULT_PARAMS.leaderPushBatchSize,
|
|
399
427
|
eventQueryBatchSize: params?.eventQueryBatchSize ?? STORE_DEFAULT_PARAMS.eventQueryBatchSize,
|
|
400
|
-
...omitUndefineds({ simulation: params?.simulation }),
|
|
401
428
|
},
|
|
402
429
|
})
|
|
430
|
+
shutdownSyncProcessor = store[StoreInternalsSymbol].syncProcessor.shutdown
|
|
403
431
|
|
|
404
432
|
// Starts background fibers (syncing, event processing, etc) for store
|
|
405
433
|
yield* store[StoreInternalsSymbol].boot
|
|
406
434
|
|
|
407
435
|
if (boot !== undefined) {
|
|
408
436
|
// TODO also incorporate `boot` function progress into `bootStatusQueue`
|
|
409
|
-
|
|
437
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- user boot errors are immediately normalized to LiveStore UnknownError
|
|
438
|
+
yield* Effect.trySyncOrPromiseOrEffect(() =>
|
|
410
439
|
boot(store, { migrationsReport: clientSession.leaderThread.initialState.migrationsReport, parentSpan: span }),
|
|
411
440
|
).pipe(
|
|
412
441
|
UnknownError.mapToUnknownError,
|
|
413
|
-
Effect.provide(
|
|
442
|
+
Effect.provide(
|
|
443
|
+
Layer.succeed(
|
|
444
|
+
LiveStoreContextRunning,
|
|
445
|
+
LiveStoreContextRunning.of({ stage: 'running', store: store as any as Store }),
|
|
446
|
+
),
|
|
447
|
+
),
|
|
414
448
|
Effect.withSpan('createStore:boot'),
|
|
415
449
|
)
|
|
416
450
|
}
|
|
417
451
|
|
|
418
452
|
// NOTE it's important to yield here to allow the forked Effect in the store constructor to run
|
|
419
|
-
yield* Effect.yieldNow
|
|
453
|
+
yield* Effect.yieldNow
|
|
420
454
|
|
|
421
455
|
if (batchUpdates !== undefined) {
|
|
422
456
|
// Replacing the default batchUpdates function with the provided one after boot
|
|
@@ -440,7 +474,7 @@ export const createStore = <
|
|
|
440
474
|
Effect.withSpan('createStore', { attributes: { debugInstanceId, storeId } }),
|
|
441
475
|
Effect.annotateLogs({ debugInstanceId, storeId }),
|
|
442
476
|
LS_DEV === true ? TaskTracing.withAsyncTaggingTracing((name) => (console as any).createTask(name)) : identity,
|
|
443
|
-
Scope.
|
|
477
|
+
Scope.provide(lifetimeScope),
|
|
444
478
|
)
|
|
445
479
|
})
|
|
446
480
|
|