@effect-app/vue 4.0.0-beta.309 → 4.0.0-beta.310
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/CHANGELOG.md +7 -0
- package/dist/atomQuery.d.ts +4 -0
- package/dist/atomQuery.d.ts.map +1 -1
- package/dist/atomQuery.js +19 -2
- package/dist/dependencyMetadata.d.ts +7 -0
- package/dist/dependencyMetadata.d.ts.map +1 -1
- package/dist/dependencyMetadata.js +38 -1
- package/dist/internal/tanstackQuery.d.ts.map +1 -1
- package/dist/internal/tanstackQuery.js +12 -6
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +4 -3
- package/dist/mutate.d.ts +1 -0
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +19 -6
- package/dist/query.d.ts +3 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -1
- package/package.json +2 -2
- package/src/atomQuery.ts +20 -1
- package/src/dependencyMetadata.ts +42 -0
- package/src/internal/tanstackQuery.ts +20 -5
- package/src/makeClient.ts +5 -1
- package/src/mutate.ts +29 -4
- package/src/query.ts +7 -0
- package/test/dependencyInvalidation.test.ts +29 -5
|
@@ -7,6 +7,33 @@ import * as Hash from "effect/Hash"
|
|
|
7
7
|
// cached-within-ttl) — the atom equivalent of the former tanstack query cache.
|
|
8
8
|
type Entry = { readonly key: ReadonlyArray<unknown>; readonly reads: DataDependencies.DataDependencies }
|
|
9
9
|
const readDependencies = new Map<number, Entry>()
|
|
10
|
+
export type QueryInvalidationMode = "await" | "soft"
|
|
11
|
+
type InvalidationModeEntry = { awaitSubscribers: number; softSubscribers: number }
|
|
12
|
+
const invalidationModes = new Map<number, InvalidationModeEntry>()
|
|
13
|
+
|
|
14
|
+
export const registerQueryInvalidationMode = (
|
|
15
|
+
key: ReadonlyArray<unknown>,
|
|
16
|
+
mode: QueryInvalidationMode
|
|
17
|
+
): () => void => {
|
|
18
|
+
const hash = Hash.hash(key)
|
|
19
|
+
const entry = invalidationModes.get(hash) ?? { awaitSubscribers: 0, softSubscribers: 0 }
|
|
20
|
+
if (mode === "soft") entry.softSubscribers++
|
|
21
|
+
else entry.awaitSubscribers++
|
|
22
|
+
invalidationModes.set(hash, entry)
|
|
23
|
+
let active = true
|
|
24
|
+
return () => {
|
|
25
|
+
if (!active) return
|
|
26
|
+
active = false
|
|
27
|
+
if (mode === "soft") entry.softSubscribers--
|
|
28
|
+
else entry.awaitSubscribers--
|
|
29
|
+
if (entry.awaitSubscribers === 0 && entry.softSubscribers === 0) invalidationModes.delete(hash)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const getQueryInvalidationMode = (key: ReadonlyArray<unknown>): QueryInvalidationMode => {
|
|
34
|
+
const entry = invalidationModes.get(Hash.hash(key))
|
|
35
|
+
return entry !== undefined && entry.awaitSubscribers === 0 && entry.softSubscribers > 0 ? "soft" : "await"
|
|
36
|
+
}
|
|
10
37
|
|
|
11
38
|
export const setQueryReadDependencies = (
|
|
12
39
|
key: ReadonlyArray<unknown>,
|
|
@@ -40,3 +67,18 @@ export const getDerivedInvalidationKeys = (
|
|
|
40
67
|
}
|
|
41
68
|
return keys
|
|
42
69
|
}
|
|
70
|
+
|
|
71
|
+
export const partitionInvalidationKeys = (
|
|
72
|
+
keys: ReadonlyArray<ReadonlyArray<unknown>>
|
|
73
|
+
): {
|
|
74
|
+
readonly awaitKeys: ReadonlyArray<ReadonlyArray<unknown>>
|
|
75
|
+
readonly softKeys: ReadonlyArray<ReadonlyArray<unknown>>
|
|
76
|
+
} => {
|
|
77
|
+
const awaitKeys: Array<ReadonlyArray<unknown>> = []
|
|
78
|
+
const softKeys: Array<ReadonlyArray<unknown>> = []
|
|
79
|
+
for (const key of keys) {
|
|
80
|
+
if (getQueryInvalidationMode(key) === "soft") softKeys.push(key)
|
|
81
|
+
else awaitKeys.push(key)
|
|
82
|
+
}
|
|
83
|
+
return { awaitKeys, softKeys }
|
|
84
|
+
}
|
|
@@ -15,7 +15,7 @@ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
|
15
15
|
import * as Atom from "effect/unstable/reactivity/Atom"
|
|
16
16
|
import { computed, type MaybeRefOrGetter, shallowRef, toValue, watch, type WatchSource } from "vue"
|
|
17
17
|
import { replaceEqualDeep } from "../atomQuery.ts"
|
|
18
|
-
import { clearQueryReadDependencies, setQueryReadDependencies } from "../dependencyMetadata.ts"
|
|
18
|
+
import { clearQueryReadDependencies, registerQueryInvalidationMode, setQueryReadDependencies } from "../dependencyMetadata.ts"
|
|
19
19
|
import { reportRuntimeError } from "../lib.ts"
|
|
20
20
|
import type { QueryInvalidator } from "../mutate.ts"
|
|
21
21
|
import type { CustomDefinedInitialQueryOptions, CustomDefinedPlaceholderQueryOptions, CustomUndefinedInitialQueryOptions, CustomUseQueryOptions, MakeQuery2, QueryCacheUpdater, QueryHandle, QueryObserverResult, RefetchOptions } from "../query.ts"
|
|
@@ -111,6 +111,15 @@ export const makeTanstackQueryInvalidator = (queryClient: QueryClient): QueryInv
|
|
|
111
111
|
},
|
|
112
112
|
{ discard: true, concurrency: "inherit" }
|
|
113
113
|
)
|
|
114
|
+
}),
|
|
115
|
+
invalidateSoft: (keys) =>
|
|
116
|
+
Effect.gen(function*() {
|
|
117
|
+
const span = yield* Effect.currentParentSpan.pipe(Effect.orElseSucceed(() => undefined))
|
|
118
|
+
yield* Effect.forEach(
|
|
119
|
+
keys,
|
|
120
|
+
(queryKey) => Effect.promise(() => queryClient.invalidateQueries({ queryKey }, { updateMeta: { span } })),
|
|
121
|
+
{ discard: true, concurrency: "inherit" }
|
|
122
|
+
)
|
|
114
123
|
})
|
|
115
124
|
})
|
|
116
125
|
|
|
@@ -165,15 +174,21 @@ export const makeTanstackQuery = <R>(
|
|
|
165
174
|
...(options?.refetchInterval !== undefined ? { refetchInterval: options.refetchInterval } : {}),
|
|
166
175
|
...(options?.select !== undefined ? { select: options.select } : {})
|
|
167
176
|
}
|
|
177
|
+
const resolvedQueryKey = computed(() => {
|
|
178
|
+
const input = resolveInput(arg, options?.mode)
|
|
179
|
+
return fullQueryKey(q, queryKey, input)
|
|
180
|
+
})
|
|
181
|
+
watch(
|
|
182
|
+
resolvedQueryKey,
|
|
183
|
+
(key, _, onCleanup) => onCleanup(registerQueryInvalidationMode(key, options?.invalidation ?? "await")),
|
|
184
|
+
{ immediate: true }
|
|
185
|
+
)
|
|
168
186
|
const tanstack = useTanstackQuery<A, CauseException<E>, TData>({
|
|
169
187
|
...tanstackOptions,
|
|
170
188
|
enabled,
|
|
171
189
|
throwOnError: false,
|
|
172
190
|
retry: (retryCount: number, error: unknown) => isRetryable(error) && retryCount < 5,
|
|
173
|
-
queryKey:
|
|
174
|
-
const input = resolveInput(arg, options?.mode)
|
|
175
|
-
return fullQueryKey(q, queryKey, input)
|
|
176
|
-
}),
|
|
191
|
+
queryKey: resolvedQueryKey,
|
|
177
192
|
queryFn: (
|
|
178
193
|
{ meta, signal }: {
|
|
179
194
|
readonly meta?: { readonly span?: Tracer.AnySpan | undefined } | undefined
|
package/src/makeClient.ts
CHANGED
|
@@ -19,7 +19,7 @@ import * as Struct from "effect/Struct"
|
|
|
19
19
|
import type * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
20
20
|
import * as Reactivity from "effect/unstable/reactivity/Reactivity"
|
|
21
21
|
import { type ComputedRef, effectScope, onBeforeUnmount, onScopeDispose, ref, type WatchSource } from "vue"
|
|
22
|
-
import { type AtomClientRuntime, invalidateAndAwait, makeAtomClientRuntime } from "./atomQuery.ts"
|
|
22
|
+
import { type AtomClientRuntime, invalidateAndAwait, invalidateSoft, makeAtomClientRuntime } from "./atomQuery.ts"
|
|
23
23
|
import { type Commander, CommanderStatic, type Progress } from "./commander.ts"
|
|
24
24
|
import { makeTanstackQuery, makeTanstackQueryCacheUpdater, makeTanstackQueryClient, makeTanstackQueryInvalidator } from "./internal/tanstackQuery.ts"
|
|
25
25
|
import { type I18n } from "./intl.ts"
|
|
@@ -720,6 +720,10 @@ const makeResolvedAtomQueryInvalidator = <R>(getContext: () => Context.Context<R
|
|
|
720
720
|
invalidateAndAwait: (keys) =>
|
|
721
721
|
invalidateAndAwait(keys).pipe(
|
|
722
722
|
Effect.provideService(Reactivity.Reactivity, getReactivity())
|
|
723
|
+
),
|
|
724
|
+
invalidateSoft: (keys) =>
|
|
725
|
+
invalidateSoft(keys).pipe(
|
|
726
|
+
Effect.provideService(Reactivity.Reactivity, getReactivity())
|
|
723
727
|
)
|
|
724
728
|
}
|
|
725
729
|
}
|
package/src/mutate.ts
CHANGED
|
@@ -13,8 +13,9 @@ import * as Stream from "effect/Stream"
|
|
|
13
13
|
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
14
14
|
import type * as Reactivity from "effect/unstable/reactivity/Reactivity"
|
|
15
15
|
import { computed, type ComputedRef, shallowRef } from "vue"
|
|
16
|
-
import { invalidateAndAwait } from "./atomQuery.ts"
|
|
17
|
-
import { getDerivedInvalidationKeys } from "./dependencyMetadata.ts"
|
|
16
|
+
import { invalidateAndAwait, invalidateSoft } from "./atomQuery.ts"
|
|
17
|
+
import { getDerivedInvalidationKeys, partitionInvalidationKeys } from "./dependencyMetadata.ts"
|
|
18
|
+
import { reportRuntimeError } from "./lib.ts"
|
|
18
19
|
|
|
19
20
|
export type GetQueryKey = (h: { id: string; options?: ClientForOptions }) => string[]
|
|
20
21
|
|
|
@@ -119,10 +120,12 @@ export type QueryInvalidationEffect<R = never> = (
|
|
|
119
120
|
) => Effect.Effect<void, never, R>
|
|
120
121
|
export interface QueryInvalidator<R = never> {
|
|
121
122
|
readonly invalidateAndAwait: QueryInvalidationEffect<R>
|
|
123
|
+
readonly invalidateSoft?: QueryInvalidationEffect<R>
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
export const atomQueryInvalidator: QueryInvalidator<Reactivity.Reactivity> = {
|
|
125
|
-
invalidateAndAwait
|
|
127
|
+
invalidateAndAwait,
|
|
128
|
+
invalidateSoft
|
|
126
129
|
}
|
|
127
130
|
|
|
128
131
|
export const combineQueryInvalidators = <R>(
|
|
@@ -133,6 +136,12 @@ export const combineQueryInvalidators = <R>(
|
|
|
133
136
|
invalidators,
|
|
134
137
|
(invalidator) => invalidator.invalidateAndAwait(keys),
|
|
135
138
|
{ discard: true, concurrency: "inherit" }
|
|
139
|
+
),
|
|
140
|
+
invalidateSoft: (keys) =>
|
|
141
|
+
Effect.forEach(
|
|
142
|
+
invalidators,
|
|
143
|
+
(invalidator) => invalidator.invalidateSoft?.(keys) ?? Effect.void,
|
|
144
|
+
{ discard: true, concurrency: "inherit" }
|
|
136
145
|
)
|
|
137
146
|
})
|
|
138
147
|
|
|
@@ -322,10 +331,14 @@ const buildInvalidateCache = <RInvalidator>(
|
|
|
322
331
|
|
|
323
332
|
if (!isReadonlyArrayNonEmpty(keys)) return Effect.void
|
|
324
333
|
|
|
334
|
+
const { awaitKeys, softKeys } = partitionInvalidationKeys(keys)
|
|
335
|
+
|
|
325
336
|
return Effect
|
|
326
337
|
.andThen(
|
|
327
338
|
Effect.annotateCurrentSpan({
|
|
328
339
|
keys,
|
|
340
|
+
awaitKeys,
|
|
341
|
+
softKeys,
|
|
329
342
|
clientKeys,
|
|
330
343
|
serverKeys,
|
|
331
344
|
derivedKeys,
|
|
@@ -333,7 +346,19 @@ const buildInvalidateCache = <RInvalidator>(
|
|
|
333
346
|
}),
|
|
334
347
|
// refetch + AWAIT every live query registered under these keys, so by the time the
|
|
335
348
|
// mutation resolves the affected queries are fresh.
|
|
336
|
-
|
|
349
|
+
Effect.gen(function*() {
|
|
350
|
+
if (softKeys.length > 0) {
|
|
351
|
+
yield* (queryInvalidator.invalidateSoft?.(softKeys) ?? Effect.void).pipe(
|
|
352
|
+
Effect.catchCause((cause) =>
|
|
353
|
+
reportRuntimeError(cause, { invalidation: "soft", keys: softKeys }).pipe(Effect.asVoid)
|
|
354
|
+
),
|
|
355
|
+
Effect.forkDetach({ startImmediately: true })
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
if (awaitKeys.length > 0) {
|
|
359
|
+
yield* queryInvalidator.invalidateAndAwait(awaitKeys)
|
|
360
|
+
}
|
|
361
|
+
})
|
|
337
362
|
)
|
|
338
363
|
.pipe(
|
|
339
364
|
Effect.tap(Effect.sleep(0.1)), // allow for refs to update etc
|
package/src/query.ts
CHANGED
|
@@ -18,6 +18,7 @@ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
|
18
18
|
import * as Atom from "effect/unstable/reactivity/Atom"
|
|
19
19
|
import { computed, type ComputedRef, effectScope, type MaybeRefOrGetter, onBeforeUnmount, onMounted, onScopeDispose, ref, toValue, type WatchSource } from "vue"
|
|
20
20
|
import { type AtomClientRuntime, type AtomQueryOptions, awaitAtomResult, buildQueryFamily, buildStreamQueryFamily, disabledQueryAtom, isStaleResult, queryKeyForAtom, refreshAtomWithCurrentSpan, staleTimeMsOf, withQueryOptions } from "./atomQuery.ts"
|
|
21
|
+
import type { QueryInvalidationMode } from "./dependencyMetadata.ts"
|
|
21
22
|
import type { LiveQueryOptions } from "./liveQueryInvalidation.ts"
|
|
22
23
|
import { latestDefined } from "./suspense.ts"
|
|
23
24
|
|
|
@@ -203,6 +204,7 @@ export interface CustomUseQueryOptions<
|
|
|
203
204
|
/** poll: re-fetch every N ms (tanstack refetchInterval) */
|
|
204
205
|
readonly refetchInterval?: number
|
|
205
206
|
readonly live?: boolean | LiveQueryOptions
|
|
207
|
+
readonly invalidation?: QueryInvalidationMode
|
|
206
208
|
readonly select?: (data: TQueryFnData) => TData
|
|
207
209
|
/** accepted for source compatibility; not used by the atom engine */
|
|
208
210
|
readonly retry?: boolean | number
|
|
@@ -256,6 +258,7 @@ export interface AtomQueryNewOptions<TQueryFnData = unknown, TData = TQueryFnDat
|
|
|
256
258
|
readonly refreshEvery?: number
|
|
257
259
|
readonly refetchInterval?: number
|
|
258
260
|
readonly live?: boolean | LiveQueryOptions
|
|
261
|
+
readonly invalidation?: QueryInvalidationMode
|
|
259
262
|
readonly select?: (data: TQueryFnData) => TData
|
|
260
263
|
}
|
|
261
264
|
|
|
@@ -327,6 +330,7 @@ const normalizeQueryOptions = (options?: {
|
|
|
327
330
|
readonly refetchInterval?: number
|
|
328
331
|
readonly refreshEvery?: number
|
|
329
332
|
readonly live?: boolean | LiveQueryOptions
|
|
333
|
+
readonly invalidation?: QueryInvalidationMode
|
|
330
334
|
}): AtomQueryOptions => {
|
|
331
335
|
const out: {
|
|
332
336
|
staleTime?: number
|
|
@@ -335,6 +339,7 @@ const normalizeQueryOptions = (options?: {
|
|
|
335
339
|
structuralSharing?: boolean
|
|
336
340
|
refetchInterval?: number
|
|
337
341
|
live?: boolean | LiveQueryOptions
|
|
342
|
+
invalidation?: QueryInvalidationMode
|
|
338
343
|
} = {}
|
|
339
344
|
if (options?.staleTime !== undefined) out.staleTime = options.staleTime
|
|
340
345
|
const gcTime = options?.idleTTL ?? options?.gcTime
|
|
@@ -345,6 +350,7 @@ const normalizeQueryOptions = (options?: {
|
|
|
345
350
|
const refetchInterval = options?.refreshEvery ?? options?.refetchInterval
|
|
346
351
|
if (refetchInterval !== undefined) out.refetchInterval = refetchInterval
|
|
347
352
|
if (options?.live !== undefined) out.live = options.live
|
|
353
|
+
if (options?.invalidation !== undefined) out.invalidation = options.invalidation
|
|
348
354
|
return out
|
|
349
355
|
}
|
|
350
356
|
|
|
@@ -521,6 +527,7 @@ const observedAtom = <A, E>(
|
|
|
521
527
|
readonly refetchInterval?: number
|
|
522
528
|
readonly refreshEvery?: number
|
|
523
529
|
readonly live?: boolean | LiveQueryOptions
|
|
530
|
+
readonly invalidation?: QueryInvalidationMode
|
|
524
531
|
}
|
|
525
532
|
): Atom.Atom<AsyncResult.AsyncResult<A, E>> =>
|
|
526
533
|
withQueryOptions(atom, normalizeQueryOptions(options), queryKeyForAtom(atom))
|
|
@@ -13,7 +13,7 @@ import { TestClock } from "effect/testing"
|
|
|
13
13
|
import * as Reactivity from "effect/unstable/reactivity/Reactivity"
|
|
14
14
|
import { createApp, effectScope, ref } from "vue"
|
|
15
15
|
import { awaitAtomResult, buildQueryFamily, invalidateAndAwait, makeAtomClientRuntime } from "../src/atomQuery.js"
|
|
16
|
-
import { clearQueryReadDependencies, getDerivedInvalidationKeys, setQueryReadDependencies } from "../src/dependencyMetadata.js"
|
|
16
|
+
import { clearQueryReadDependencies, getDerivedInvalidationKeys, partitionInvalidationKeys, registerQueryInvalidationMode, setQueryReadDependencies } from "../src/dependencyMetadata.js"
|
|
17
17
|
import { makeTanstackQuery, makeTanstackQueryInvalidator } from "../src/internal/tanstackQuery.js"
|
|
18
18
|
import { invalidateQueries, makeStreamMutation2, type MutationOptionsBase } from "../src/mutate.js"
|
|
19
19
|
|
|
@@ -58,6 +58,30 @@ it("getDerivedInvalidationKeys returns keys of queries whose reads intersect the
|
|
|
58
58
|
}
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
+
it("uses the strictest active query invalidation mode", () => {
|
|
62
|
+
const overviewKey = ["$Overview", "$List", undefined]
|
|
63
|
+
const pickListKey = ["$PickList", "$List", undefined]
|
|
64
|
+
|
|
65
|
+
const unregisterSoft = registerQueryInvalidationMode(overviewKey, "soft")
|
|
66
|
+
const unregisterAwait = registerQueryInvalidationMode(pickListKey, "await")
|
|
67
|
+
const unregisterStrictOverview = registerQueryInvalidationMode(overviewKey, "await")
|
|
68
|
+
try {
|
|
69
|
+
expect(partitionInvalidationKeys([overviewKey, pickListKey])).toEqual({
|
|
70
|
+
awaitKeys: [overviewKey, pickListKey],
|
|
71
|
+
softKeys: []
|
|
72
|
+
})
|
|
73
|
+
unregisterStrictOverview()
|
|
74
|
+
expect(partitionInvalidationKeys([overviewKey, pickListKey])).toEqual({
|
|
75
|
+
awaitKeys: [pickListKey],
|
|
76
|
+
softKeys: [overviewKey]
|
|
77
|
+
})
|
|
78
|
+
} finally {
|
|
79
|
+
unregisterStrictOverview()
|
|
80
|
+
unregisterSoft()
|
|
81
|
+
unregisterAwait()
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
61
85
|
it("clearing read dependencies drops the query from derivation", () => {
|
|
62
86
|
const inventoryKey = ["$Inventory", "List", undefined]
|
|
63
87
|
setQueryReadDependencies(inventoryKey, new Set([repo]))
|
|
@@ -135,7 +159,7 @@ it("atom engine: a query records its read deps so a command's writes derive it",
|
|
|
135
159
|
|
|
136
160
|
const unmount = defaultRegistry.mount(atom)
|
|
137
161
|
try {
|
|
138
|
-
await Effect.runPromise(awaitAtomResult(defaultRegistry, atom)
|
|
162
|
+
await Effect.runPromise(awaitAtomResult(defaultRegistry, atom))
|
|
139
163
|
expect(runs).toBe(1)
|
|
140
164
|
|
|
141
165
|
const fullKey = [...makeQueryKey(self), undefined]
|
|
@@ -224,7 +248,7 @@ it("atom engine: disposing the query atom clears its recorded reads", async () =
|
|
|
224
248
|
const fullKey = [...makeQueryKey(self), undefined]
|
|
225
249
|
|
|
226
250
|
const unmount = defaultRegistry.mount(atom)
|
|
227
|
-
await Effect.runPromise(awaitAtomResult(defaultRegistry, atom)
|
|
251
|
+
await Effect.runPromise(awaitAtomResult(defaultRegistry, atom))
|
|
228
252
|
expect(getDerivedInvalidationKeys(new Set([atomRepo]))).toContainEqual(fullKey)
|
|
229
253
|
|
|
230
254
|
// Disposing the registry runs the atom's finalizers, including `trackReadDependencies`.
|
|
@@ -291,12 +315,12 @@ const makeAtomHarness = (queryRepo: DataDependencies.DataDependency): EngineHarn
|
|
|
291
315
|
return {
|
|
292
316
|
queryFullKey: [...makeQueryKey(self), undefined],
|
|
293
317
|
serverInvalidationKey: makeQueryKey(self),
|
|
294
|
-
fetchInitial: () => Effect.runPromise(awaitAtomResult(defaultRegistry, atom)
|
|
318
|
+
fetchInitial: () => Effect.runPromise(awaitAtomResult(defaultRegistry, atom)),
|
|
295
319
|
runs: () => runs,
|
|
296
320
|
runCommand: (options, command) =>
|
|
297
321
|
Effect.runPromise(
|
|
298
322
|
invalidateQueries({ id: "MatrixAtom.Save" }, options, invalidator)(command, { id: "x" })
|
|
299
|
-
.pipe(Effect.andThen(awaitAtomResult(defaultRegistry, atom).pipe(Effect.exit)))
|
|
323
|
+
.pipe(Effect.andThen(awaitAtomResult(defaultRegistry, atom).pipe(Effect.exit)))
|
|
300
324
|
),
|
|
301
325
|
dispose: () => {
|
|
302
326
|
unmount()
|