@@ -1,6 +1,6 @@
|
||||
/** biome-ignore-all lint/complexity/noBannedTypes: {} is the default type for React props */
|
||||
/** biome-ignore-all lint/complexity/useArrowFunction: necessary for class prototypes */
|
||||
import { Cause, Context, type Duration, Effect, Equal, Equivalence, Exit, Fiber, Function, HashMap, identity, Layer, Option, Pipeable, Predicate, Ref, Scheduler, Scope, Tracer } from "effect"
|
||||
import { Context, type Duration, Effect, Equivalence, Exit, Function, identity, Layer, Pipeable, Predicate, Scheduler, Scope, Tracer } from "effect"
|
||||
import * as React from "react"
|
||||
import * as ScopeRegistry from "./ScopeRegistry.js"
|
||||
|
||||
@@ -668,54 +668,26 @@ export const useScope = Effect.fnUntraced(function*(
|
||||
// biome-ignore lint/style/noNonNullAssertion: context initialization
|
||||
const contextRef = React.useRef<Context.Context<never>>(null!)
|
||||
contextRef.current = yield* Effect.context()
|
||||
const registry = yield* ScopeRegistry.ScopeRegistry as unknown as Effect.Effect<ScopeRegistry.ScopeRegistryService>
|
||||
|
||||
const { key, scope } = React.useMemo(() => Effect.runSyncWith(contextRef.current)(Effect.Do.pipe(
|
||||
Effect.bind("scopeRegistryRef", () => Effect.map(
|
||||
ScopeRegistry.ScopeRegistry as unknown as Effect.Effect<ScopeRegistry.ScopeRegistry["Service"]>,
|
||||
scopeRegistry => scopeRegistry.ref,
|
||||
)),
|
||||
Effect.let("key", () => Equal.byReference({})),
|
||||
Effect.bind("scope", () => Scope.make(options?.finalizerExecutionStrategy ?? defaultOptions.finalizerExecutionStrategy)),
|
||||
Effect.tap(({ scopeRegistryRef, key, scope }) =>
|
||||
Ref.update(scopeRegistryRef, HashMap.set(key, Equal.byReference({
|
||||
scope,
|
||||
closeFiber: Option.none(),
|
||||
})))
|
||||
),
|
||||
const [key, scope] = React.useMemo(() => Effect.runSyncWith(contextRef.current)(Effect.gen(function*() {
|
||||
const key = ScopeRegistry.makeKey()
|
||||
const entry = yield* registry.register(key, {
|
||||
finalizerExecutionStrategy: options?.finalizerExecutionStrategy ?? defaultOptions.finalizerExecutionStrategy,
|
||||
finalizerExecutionDebounce: options?.finalizerExecutionDebounce ?? defaultOptions.finalizerExecutionDebounce,
|
||||
})
|
||||
|
||||
return [key, entry.scope]
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: use of React.DependencyList
|
||||
)), deps)
|
||||
})), deps)
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: only reactive on "key"
|
||||
React.useEffect(() => Effect.runSyncWith(contextRef.current)(
|
||||
(ScopeRegistry.ScopeRegistry as unknown as Effect.Effect<ScopeRegistry.ScopeRegistry["Service"]>).pipe(
|
||||
Effect.map(scopeRegistry => scopeRegistry.ref),
|
||||
Effect.tap(ref => Ref.get(ref).pipe(
|
||||
Effect.flatMap(map => Effect.fromOption(HashMap.get(map, key))),
|
||||
Effect.flatMap(entry => Option.match(entry.closeFiber, {
|
||||
onSome: fiber => Effect.forkDetach(Fiber.interrupt(fiber)),
|
||||
onNone: () => Effect.void,
|
||||
})),
|
||||
)),
|
||||
Effect.map(ref =>
|
||||
() => Effect.runSyncWith(contextRef.current)(Effect.flatMap(
|
||||
Effect.sleep(options?.finalizerExecutionDebounce ?? defaultOptions.finalizerExecutionDebounce).pipe(
|
||||
Effect.andThen(Scope.close(scope, Exit.void)),
|
||||
Effect.onExit(exit => Exit.match(exit, {
|
||||
onSuccess: () => Ref.update(ref, HashMap.remove(key)),
|
||||
onFailure: cause => Cause.hasInterruptsOnly(cause)
|
||||
? Effect.void
|
||||
: Ref.update(ref, HashMap.remove(key)),
|
||||
})),
|
||||
Effect.forkDetach,
|
||||
),
|
||||
fiber => Ref.update(ref, HashMap.set(key, Equal.byReference({
|
||||
scope,
|
||||
closeFiber: Option.some(fiber),
|
||||
}))),
|
||||
))
|
||||
),
|
||||
)
|
||||
), [key])
|
||||
React.useEffect(() => {
|
||||
Effect.runSyncWith(contextRef.current)(registry.commit(key))
|
||||
return () => {
|
||||
Effect.runSyncWith(contextRef.current)(registry.release(key))
|
||||
}
|
||||
}, [key])
|
||||
|
||||
return scope
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user