ScopeMap -> ScopeRegistry
Lint / lint (push) Failing after 43s

This commit is contained in:
Julien Valverdé
2026-07-22 22:51:38 +02:00
parent c151b4608f
commit 8fed17789a
5 changed files with 43 additions and 38 deletions
+8 -32
View File
@@ -2,6 +2,7 @@
/** 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 * as React from "react"
import * as ScopeRegistry from "./ScopeRegistry.js"
export const ComponentTypeId: unique symbol = Symbol.for("@effect-fc/Component/Component")
@@ -636,31 +637,6 @@ export const withContext: {
})
/**
* Internal Effect service that maintains a registry of scopes associated with React component instances.
*
* This service is used internally by the `useScope` hook to manage the lifecycle of component scopes,
* including tracking active scopes and coordinating their cleanup when components unmount or dependencies change.
*/
export class ScopeMap extends Context.Service<ScopeMap, {
readonly ref: Ref.Ref<HashMap.HashMap<object, ScopeMap.Entry>>
}>()(
"@effect-fc/Component/ScopeMap"
) {
static readonly layer = Layer.effect(ScopeMap, Effect.map(
Ref.make(HashMap.empty<object, ScopeMap.Entry>()),
ref => ({ ref }),
))
}
export declare namespace ScopeMap {
export interface Entry {
readonly scope: Scope.Closeable
readonly closeFiber: Option.Option<Fiber.Fiber<void>>
}
}
export declare namespace useScope {
export interface Options {
readonly finalizerExecutionStrategy?: "sequential" | "parallel"
@@ -694,14 +670,14 @@ export const useScope = Effect.fnUntraced(function*(
contextRef.current = yield* Effect.context()
const { key, scope } = React.useMemo(() => Effect.runSyncWith(contextRef.current)(Effect.Do.pipe(
Effect.bind("scopeMapRef", () => Effect.map(
ScopeMap as unknown as Effect.Effect<ScopeMap["Service"]>,
scopeMap => scopeMap.ref,
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(({ scopeMapRef, key, scope }) =>
Ref.update(scopeMapRef, HashMap.set(key, Equal.byReference({
Effect.tap(({ scopeRegistryRef, key, scope }) =>
Ref.update(scopeRegistryRef, HashMap.set(key, Equal.byReference({
scope,
closeFiber: Option.none(),
})))
@@ -711,8 +687,8 @@ export const useScope = Effect.fnUntraced(function*(
// biome-ignore lint/correctness/useExhaustiveDependencies: only reactive on "key"
React.useEffect(() => Effect.runSyncWith(contextRef.current)(
(ScopeMap as unknown as Effect.Effect<ScopeMap["Service"]>).pipe(
Effect.map(scopeMap => scopeMap.ref),
(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, {