@livestore/livestore 0.0.54 → 0.0.55-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/effect/LiveStore.d.ts +8 -7
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +10 -10
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/react/LiveStoreProvider.d.ts +2 -1
- package/dist/react/LiveStoreProvider.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.js +4 -4
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/store.d.ts +11 -7
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +33 -28
- package/dist/store.js.map +1 -1
- package/package.json +5 -5
- package/src/effect/LiveStore.ts +21 -19
- package/src/react/LiveStoreProvider.tsx +19 -16
- package/src/store.ts +47 -28
package/src/effect/LiveStore.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { BootDb, StoreAdapterFactory, UnexpectedError } from '@livestore/common'
|
|
1
|
+
import type { BootDb, BootStatus, StoreAdapterFactory, UnexpectedError } from '@livestore/common'
|
|
2
2
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
|
-
import type { Cause } from '@livestore/utils/effect'
|
|
4
|
-
import { Context, Deferred, Duration, Effect, Layer, OtelTracer, pipe
|
|
3
|
+
import type { Cause, Scope } from '@livestore/utils/effect'
|
|
4
|
+
import { Context, Deferred, Duration, Effect, FiberSet, Layer, OtelTracer, pipe } from '@livestore/utils/effect'
|
|
5
5
|
import * as otel from '@opentelemetry/api'
|
|
6
6
|
import type { GraphQLSchema } from 'graphql'
|
|
7
7
|
|
|
@@ -32,7 +32,7 @@ export type LiveStoreCreateStoreOptions<GraphQLContext extends BaseGraphQLContex
|
|
|
32
32
|
schema: LiveStoreSchema
|
|
33
33
|
graphQLOptions?: GraphQLOptions<GraphQLContext>
|
|
34
34
|
otelOptions?: OtelOptions
|
|
35
|
-
boot?: (db: BootDb, parentSpan: otel.Span) =>
|
|
35
|
+
boot?: (db: BootDb, parentSpan: otel.Span) => void | Promise<void> | Effect.Effect<void, unknown, otel.Tracer>
|
|
36
36
|
adapter: StoreAdapterFactory
|
|
37
37
|
batchUpdates?: (run: () => void) => void
|
|
38
38
|
disableDevtools?: boolean
|
|
@@ -43,7 +43,7 @@ export const LiveStoreContextRunning = Context.GenericTag<LiveStoreContextRunnin
|
|
|
43
43
|
'@livestore/livestore/effect/LiveStoreContextRunning',
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
export type DeferredStoreContext = Deferred.Deferred<LiveStoreContextRunning>
|
|
46
|
+
export type DeferredStoreContext = Deferred.Deferred<LiveStoreContextRunning, UnexpectedError>
|
|
47
47
|
export const DeferredStoreContext = Context.GenericTag<DeferredStoreContext>(
|
|
48
48
|
'@livestore/livestore/effect/DeferredStoreContext',
|
|
49
49
|
)
|
|
@@ -56,9 +56,10 @@ export type LiveStoreContextProps<GraphQLContext extends BaseGraphQLContext> = {
|
|
|
56
56
|
schema: Effect.Effect<GraphQLSchema, never, otel.Tracer>
|
|
57
57
|
makeContext: (db: MainDatabaseWrapper) => GraphQLContext
|
|
58
58
|
}
|
|
59
|
-
boot?: (db: BootDb) => Effect.Effect<void>
|
|
59
|
+
boot?: (db: BootDb) => Effect.Effect<void, unknown, otel.Tracer>
|
|
60
60
|
adapter: StoreAdapterFactory
|
|
61
61
|
disableDevtools?: boolean
|
|
62
|
+
onBootStatus?: (status: BootStatus) => void
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
export const LiveStoreContextLayer = <GraphQLContext extends BaseGraphQLContext>(
|
|
@@ -69,14 +70,18 @@ export const LiveStoreContextLayer = <GraphQLContext extends BaseGraphQLContext>
|
|
|
69
70
|
Layer.provide(LiveStoreContextDeferred),
|
|
70
71
|
)
|
|
71
72
|
|
|
72
|
-
export const LiveStoreContextDeferred = Layer.effect(
|
|
73
|
+
export const LiveStoreContextDeferred = Layer.effect(
|
|
74
|
+
DeferredStoreContext,
|
|
75
|
+
Deferred.make<LiveStoreContextRunning, UnexpectedError>(),
|
|
76
|
+
)
|
|
73
77
|
|
|
74
78
|
export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>({
|
|
75
79
|
schema,
|
|
76
80
|
graphQLOptions: graphQLOptions_,
|
|
77
|
-
boot
|
|
81
|
+
boot,
|
|
78
82
|
adapter,
|
|
79
83
|
disableDevtools,
|
|
84
|
+
onBootStatus,
|
|
80
85
|
}: LiveStoreContextProps<GraphQLContext>): Effect.Effect<
|
|
81
86
|
LiveStoreContextRunning,
|
|
82
87
|
UnexpectedError | Cause.TimeoutException,
|
|
@@ -84,23 +89,16 @@ export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>(
|
|
|
84
89
|
> =>
|
|
85
90
|
pipe(
|
|
86
91
|
Effect.gen(function* () {
|
|
87
|
-
const runtime = yield* Effect.runtime<never>()
|
|
88
|
-
|
|
89
92
|
const otelRootSpanContext = otel.context.active()
|
|
90
93
|
|
|
91
|
-
const storeScope = yield* Scope.make()
|
|
92
|
-
|
|
93
|
-
yield* Effect.addFinalizer((ex) => Scope.close(storeScope, ex))
|
|
94
|
-
|
|
95
94
|
const otelTracer = yield* OtelTracer.Tracer
|
|
96
95
|
|
|
97
96
|
const graphQLOptions = yield* graphQLOptions_
|
|
98
97
|
? Effect.all({ schema: graphQLOptions_.schema, makeContext: Effect.succeed(graphQLOptions_.makeContext) })
|
|
99
98
|
: Effect.succeed(undefined)
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
: undefined
|
|
100
|
+
// TODO join fiber set and close tear down parent scope in case of error (Needs refactor with Mike A)
|
|
101
|
+
const fiberSet = yield* FiberSet.make()
|
|
104
102
|
|
|
105
103
|
const store = yield* createStore({
|
|
106
104
|
schema,
|
|
@@ -112,14 +110,18 @@ export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>(
|
|
|
112
110
|
boot,
|
|
113
111
|
adapter,
|
|
114
112
|
disableDevtools,
|
|
115
|
-
|
|
113
|
+
fiberSet,
|
|
114
|
+
onBootStatus,
|
|
116
115
|
})
|
|
117
116
|
|
|
118
117
|
window.__debugLiveStore = store
|
|
119
118
|
|
|
120
119
|
return { stage: 'running', store } satisfies LiveStoreContextRunning
|
|
121
120
|
}),
|
|
121
|
+
Effect.tapErrorCause((cause) => Effect.flatMap(DeferredStoreContext, (def) => Deferred.failCause(def, cause))),
|
|
122
122
|
Effect.tap((storeCtx) => Effect.flatMap(DeferredStoreContext, (def) => Deferred.succeed(def, storeCtx))),
|
|
123
|
-
|
|
123
|
+
// This can take quite a while.
|
|
124
|
+
// TODO make this configurable
|
|
125
|
+
Effect.timeout(Duration.minutes(5)),
|
|
124
126
|
Effect.withSpan('@livestore/livestore/effect:makeLiveStoreContext'),
|
|
125
127
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type BootDb, type BootStatus, type StoreAdapterFactory, UnexpectedError } from '@livestore/common'
|
|
2
2
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
3
|
import { errorToString } from '@livestore/utils'
|
|
4
|
-
import { Effect, Exit, Logger, LogLevel, Schema, Scope } from '@livestore/utils/effect'
|
|
4
|
+
import { Effect, Exit, FiberSet, Logger, LogLevel, Schema, Scope } from '@livestore/utils/effect'
|
|
5
5
|
import type * as otel from '@opentelemetry/api'
|
|
6
6
|
import type { ReactElement, ReactNode } from 'react'
|
|
7
7
|
import React from 'react'
|
|
@@ -14,7 +14,7 @@ import { LiveStoreContext } from './LiveStoreContext.js'
|
|
|
14
14
|
|
|
15
15
|
interface LiveStoreProviderProps<GraphQLContext> {
|
|
16
16
|
schema: LiveStoreSchema
|
|
17
|
-
boot?: (db: BootDb, parentSpan: otel.Span) =>
|
|
17
|
+
boot?: (db: BootDb, parentSpan: otel.Span) => void | Promise<void> | Effect.Effect<void, unknown, otel.Tracer>
|
|
18
18
|
graphQLOptions?: GraphQLOptions<GraphQLContext>
|
|
19
19
|
otelOptions?: OtelOptions
|
|
20
20
|
renderLoading: (status: BootStatus) => ReactElement
|
|
@@ -153,20 +153,23 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
153
153
|
}
|
|
154
154
|
})
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
156
|
+
FiberSet.make().pipe(
|
|
157
|
+
Effect.andThen((fiberSet) =>
|
|
158
|
+
createStore({
|
|
159
|
+
fiberSet,
|
|
160
|
+
schema,
|
|
161
|
+
graphQLOptions,
|
|
162
|
+
otelOptions,
|
|
163
|
+
boot,
|
|
164
|
+
adapter,
|
|
165
|
+
batchUpdates,
|
|
166
|
+
disableDevtools,
|
|
167
|
+
onBootStatus: (status) => {
|
|
168
|
+
if (ctxValueRef.current.value.stage === 'running' || ctxValueRef.current.value.stage === 'error') return
|
|
169
|
+
setContextValue(status)
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
),
|
|
170
173
|
Effect.tapSync((store) => setContextValue({ stage: 'running', store })),
|
|
171
174
|
Effect.tapError((error) => Effect.sync(() => setContextValue({ stage: 'error', error }))),
|
|
172
175
|
Effect.tapDefect((defect) => Effect.sync(() => setContextValue({ stage: 'error', error: defect }))),
|
package/src/store.ts
CHANGED
|
@@ -17,11 +17,13 @@ import {
|
|
|
17
17
|
} from '@livestore/common'
|
|
18
18
|
import type { LiveStoreSchema, MutationEvent } from '@livestore/common/schema'
|
|
19
19
|
import { makeMutationEventSchemaMemo } from '@livestore/common/schema'
|
|
20
|
-
import { assertNever,
|
|
20
|
+
import { assertNever, makeNoopTracer, shouldNeverHappen, throttle } from '@livestore/utils'
|
|
21
21
|
import { cuid } from '@livestore/utils/cuid'
|
|
22
22
|
import {
|
|
23
23
|
Effect,
|
|
24
24
|
Exit,
|
|
25
|
+
FiberSet,
|
|
26
|
+
Inspectable,
|
|
25
27
|
Layer,
|
|
26
28
|
Logger,
|
|
27
29
|
LogLevel,
|
|
@@ -71,7 +73,7 @@ export type StoreOptions<
|
|
|
71
73
|
otelOptions: OtelOptions
|
|
72
74
|
reactivityGraph: ReactivityGraph
|
|
73
75
|
disableDevtools?: boolean
|
|
74
|
-
|
|
76
|
+
fiberSet: FiberSet.FiberSet
|
|
75
77
|
// TODO remove this temporary solution and find a better way to avoid re-processing the same mutation
|
|
76
78
|
__processedMutationIds: Set<string>
|
|
77
79
|
}
|
|
@@ -126,10 +128,10 @@ export type StoreMutateOptions = {
|
|
|
126
128
|
export class Store<
|
|
127
129
|
TGraphQLContext extends BaseGraphQLContext = BaseGraphQLContext,
|
|
128
130
|
TSchema extends LiveStoreSchema = LiveStoreSchema,
|
|
129
|
-
> {
|
|
131
|
+
> extends Inspectable.Class {
|
|
130
132
|
id = uniqueStoreId()
|
|
131
133
|
readonly devtoolsConnectionId = cuid()
|
|
132
|
-
private
|
|
134
|
+
private fiberSet: FiberSet.FiberSet
|
|
133
135
|
reactivityGraph: ReactivityGraph
|
|
134
136
|
mainDbWrapper: MainDatabaseWrapper
|
|
135
137
|
adapter: StoreAdapter
|
|
@@ -160,13 +162,15 @@ export class Store<
|
|
|
160
162
|
otelOptions,
|
|
161
163
|
disableDevtools,
|
|
162
164
|
__processedMutationIds,
|
|
163
|
-
|
|
165
|
+
fiberSet,
|
|
164
166
|
}: StoreOptions<TGraphQLContext, TSchema>) {
|
|
167
|
+
super()
|
|
168
|
+
|
|
165
169
|
this.mainDbWrapper = new MainDatabaseWrapper({ otel: otelOptions, db: adapter.mainDb })
|
|
166
170
|
this.adapter = adapter
|
|
167
171
|
this.schema = schema
|
|
168
172
|
|
|
169
|
-
this.
|
|
173
|
+
this.fiberSet = fiberSet
|
|
170
174
|
|
|
171
175
|
// TODO refactor
|
|
172
176
|
this.__mutationEventSchema = makeMutationEventSchemaMemo(schema)
|
|
@@ -239,7 +243,9 @@ export class Store<
|
|
|
239
243
|
otel.trace.getSpan(this.otel.queriesSpanContext)!.end()
|
|
240
244
|
}),
|
|
241
245
|
)
|
|
242
|
-
|
|
246
|
+
|
|
247
|
+
yield* Effect.never
|
|
248
|
+
}).pipe(Effect.scoped, Effect.withSpan('LiveStore:store-constructor'), FiberSet.run(fiberSet), runEffectFork)
|
|
243
249
|
}
|
|
244
250
|
|
|
245
251
|
static createStore = <TGraphQLContext extends BaseGraphQLContext, TSchema extends LiveStoreSchema = LiveStoreSchema>(
|
|
@@ -305,7 +311,7 @@ export class Store<
|
|
|
305
311
|
* Currently only used when shutting down the app for debugging purposes (e.g. to close Otel spans).
|
|
306
312
|
*/
|
|
307
313
|
destroy = async () => {
|
|
308
|
-
await
|
|
314
|
+
await FiberSet.clear(this.fiberSet).pipe(Effect.withSpan('Store:destroy'), runEffectPromise)
|
|
309
315
|
}
|
|
310
316
|
|
|
311
317
|
mutate: {
|
|
@@ -571,6 +577,7 @@ export class Store<
|
|
|
571
577
|
meta: { liveStoreRefType: 'table' },
|
|
572
578
|
})
|
|
573
579
|
|
|
580
|
+
// #region devtools
|
|
574
581
|
// TODO shutdown behaviour
|
|
575
582
|
private bootDevtools = () =>
|
|
576
583
|
Effect.gen(this, function* () {
|
|
@@ -584,6 +591,8 @@ export class Store<
|
|
|
584
591
|
|
|
585
592
|
const channelId = this.adapter.coordinator.devtools.channelId
|
|
586
593
|
|
|
594
|
+
const runtime = yield* Effect.runtime()
|
|
595
|
+
|
|
587
596
|
window.addEventListener('message', (event) => {
|
|
588
597
|
const decodedMessageRes = Schema.decodeOption(Devtools.DevtoolsWindowMessage.MessageForStore)(event.data)
|
|
589
598
|
if (decodedMessageRes._tag === 'None') return
|
|
@@ -773,7 +782,7 @@ export class Store<
|
|
|
773
782
|
|
|
774
783
|
storeMessagePort.start()
|
|
775
784
|
}),
|
|
776
|
-
|
|
785
|
+
Runtime.runFork(runtime),
|
|
777
786
|
)
|
|
778
787
|
|
|
779
788
|
return
|
|
@@ -782,6 +791,7 @@ export class Store<
|
|
|
782
791
|
|
|
783
792
|
sendToDevtoolsContentscript(Devtools.DevtoolsWindowMessage.StoreReady.make({ channelId }))
|
|
784
793
|
})
|
|
794
|
+
// #endregion devtools
|
|
785
795
|
|
|
786
796
|
__devDownloadDb = () => {
|
|
787
797
|
const data = this.mainDbWrapper.export()
|
|
@@ -795,6 +805,13 @@ export class Store<
|
|
|
795
805
|
|
|
796
806
|
// TODO allow for graceful store reset without requiring a full page reload (which should also call .boot)
|
|
797
807
|
dangerouslyResetStorage = (mode: ResetMode) => this.adapter.coordinator.dangerouslyReset(mode).pipe(runEffectPromise)
|
|
808
|
+
|
|
809
|
+
toJSON = () => {
|
|
810
|
+
return {
|
|
811
|
+
_tag: 'Store',
|
|
812
|
+
reactivityGraph: this.reactivityGraph.getSnapshot({ includeResults: true }),
|
|
813
|
+
}
|
|
814
|
+
}
|
|
798
815
|
}
|
|
799
816
|
|
|
800
817
|
export type CreateStoreOptions<TGraphQLContext extends BaseGraphQLContext, TSchema extends LiveStoreSchema> = {
|
|
@@ -803,7 +820,7 @@ export type CreateStoreOptions<TGraphQLContext extends BaseGraphQLContext, TSche
|
|
|
803
820
|
reactivityGraph?: ReactivityGraph
|
|
804
821
|
graphQLOptions?: GraphQLOptions<TGraphQLContext>
|
|
805
822
|
otelOptions?: Partial<OtelOptions>
|
|
806
|
-
boot?: (db: BootDb, parentSpan: otel.Span) =>
|
|
823
|
+
boot?: (db: BootDb, parentSpan: otel.Span) => void | Promise<void> | Effect.Effect<void, unknown, otel.Tracer>
|
|
807
824
|
batchUpdates?: (run: () => void) => void
|
|
808
825
|
disableDevtools?: boolean
|
|
809
826
|
onBootStatus?: (status: BootStatus) => void
|
|
@@ -827,9 +844,13 @@ export const createStorePromise = async <
|
|
|
827
844
|
})
|
|
828
845
|
}
|
|
829
846
|
|
|
830
|
-
return yield*
|
|
847
|
+
return yield* FiberSet.make().pipe(
|
|
848
|
+
Effect.andThen((fiberSet) => createStore({ ...options, fiberSet })),
|
|
849
|
+
Scope.extend(scope),
|
|
850
|
+
)
|
|
831
851
|
}).pipe(Effect.withSpan('createStore'), runEffectPromise)
|
|
832
852
|
|
|
853
|
+
// #region createStore
|
|
833
854
|
export const createStore = <
|
|
834
855
|
TGraphQLContext extends BaseGraphQLContext,
|
|
835
856
|
TSchema extends LiveStoreSchema = LiveStoreSchema,
|
|
@@ -843,8 +864,8 @@ export const createStore = <
|
|
|
843
864
|
batchUpdates,
|
|
844
865
|
disableDevtools,
|
|
845
866
|
onBootStatus,
|
|
846
|
-
|
|
847
|
-
}: CreateStoreOptions<TGraphQLContext, TSchema> & {
|
|
867
|
+
fiberSet,
|
|
868
|
+
}: CreateStoreOptions<TGraphQLContext, TSchema> & { fiberSet: FiberSet.FiberSet }): Effect.Effect<
|
|
848
869
|
Store<TGraphQLContext, TSchema>,
|
|
849
870
|
UnexpectedError,
|
|
850
871
|
Scope.Scope
|
|
@@ -859,7 +880,7 @@ export const createStore = <
|
|
|
859
880
|
return Effect.gen(function* () {
|
|
860
881
|
const span = yield* OtelTracer.currentOtelSpan.pipe(Effect.orDie)
|
|
861
882
|
|
|
862
|
-
const bootStatusQueue = yield* Queue.unbounded<BootStatus>()
|
|
883
|
+
const bootStatusQueue = yield* Queue.unbounded<BootStatus>().pipe(Effect.acquireRelease(Queue.shutdown))
|
|
863
884
|
|
|
864
885
|
yield* Queue.take(bootStatusQueue).pipe(
|
|
865
886
|
Effect.tapSync((status) => onBootStatus?.(status)),
|
|
@@ -872,7 +893,12 @@ export const createStore = <
|
|
|
872
893
|
schema,
|
|
873
894
|
devtoolsEnabled: disableDevtools !== true,
|
|
874
895
|
bootStatusQueue,
|
|
875
|
-
shutdown: (cause) =>
|
|
896
|
+
shutdown: (cause) =>
|
|
897
|
+
Effect.gen(function* () {
|
|
898
|
+
yield* Effect.logWarning(`Shutting down LiveStore`, cause)
|
|
899
|
+
// TODO close parent scope? (Needs refactor with Mike A)
|
|
900
|
+
yield* FiberSet.clear(fiberSet)
|
|
901
|
+
}).pipe(Effect.withSpan('livestore:shutdown')),
|
|
876
902
|
}).pipe(Effect.withPerformanceMeasure('livestore:makeAdapter'), Effect.withSpan('createStore:makeAdapter'))
|
|
877
903
|
|
|
878
904
|
if (batchUpdates !== undefined) {
|
|
@@ -950,19 +976,12 @@ export const createStore = <
|
|
|
950
976
|
},
|
|
951
977
|
}
|
|
952
978
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
// NOTE only awaiting if it's actually a promise to avoid unnecessary async/await
|
|
958
|
-
if (isPromise(booting)) {
|
|
959
|
-
yield* Effect.tryPromise({ try: () => booting, catch: (cause) => new UnexpectedError({ cause }) })
|
|
960
|
-
}
|
|
979
|
+
yield* Effect.tryAll(() => boot(bootDbImpl, span)).pipe(
|
|
980
|
+
UnexpectedError.mapToUnexpectedError,
|
|
981
|
+
Effect.withSpan('createStore:boot'),
|
|
982
|
+
)
|
|
961
983
|
}
|
|
962
984
|
|
|
963
|
-
// TODO: we can't apply the schema at this point, we've already loaded persisted data!
|
|
964
|
-
// Think about what to do about this case.
|
|
965
|
-
// await applySchema(db, schema)
|
|
966
985
|
return Store.createStore<TGraphQLContext, TSchema>(
|
|
967
986
|
{
|
|
968
987
|
adapter,
|
|
@@ -972,12 +991,11 @@ export const createStore = <
|
|
|
972
991
|
reactivityGraph,
|
|
973
992
|
disableDevtools,
|
|
974
993
|
__processedMutationIds,
|
|
975
|
-
|
|
994
|
+
fiberSet,
|
|
976
995
|
},
|
|
977
996
|
span,
|
|
978
997
|
)
|
|
979
998
|
}).pipe(
|
|
980
|
-
// Effect.scoped,
|
|
981
999
|
Effect.withSpan('createStore', {
|
|
982
1000
|
parent: otelOptions?.rootSpanContext
|
|
983
1001
|
? OtelTracer.makeExternalSpan(otel.trace.getSpanContext(otelOptions.rootSpanContext)!)
|
|
@@ -986,6 +1004,7 @@ export const createStore = <
|
|
|
986
1004
|
Effect.provide(TracingLive),
|
|
987
1005
|
)
|
|
988
1006
|
}
|
|
1007
|
+
// #endregion createStore
|
|
989
1008
|
|
|
990
1009
|
// TODO consider replacing with Effect's RC data structures
|
|
991
1010
|
class ReferenceCountedSet<T> {
|