0.2.1 #26
@@ -39,16 +39,10 @@ export namespace Component {
|
|||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
readonly displayName?: string
|
readonly displayName?: string
|
||||||
readonly finalizerExecutionMode: "sync" | "fork"
|
|
||||||
readonly finalizerExecutionStrategy: ExecutionStrategy.ExecutionStrategy
|
readonly finalizerExecutionStrategy: ExecutionStrategy.ExecutionStrategy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScopeOptions {
|
|
||||||
readonly finalizerExecutionMode?: "sync" | "fork"
|
|
||||||
readonly finalizerExecutionStrategy?: ExecutionStrategy.ExecutionStrategy
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ComponentProto = Object.freeze({
|
const ComponentProto = Object.freeze({
|
||||||
...Effectable.CommitPrototype,
|
...Effectable.CommitPrototype,
|
||||||
@@ -88,10 +82,9 @@ const ComponentProto = Object.freeze({
|
|||||||
},
|
},
|
||||||
} as const)
|
} as const)
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions: Component.Options = {
|
||||||
finalizerExecutionMode: "fork",
|
|
||||||
finalizerExecutionStrategy: ExecutionStrategy.sequential,
|
finalizerExecutionStrategy: ExecutionStrategy.sequential,
|
||||||
} as const
|
}
|
||||||
|
|
||||||
const nonReactiveTags = [Tracer.ParentSpan] as const
|
const nonReactiveTags = [Tracer.ParentSpan] as const
|
||||||
|
|
||||||
@@ -419,10 +412,16 @@ export namespace ScopeMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export namespace useScope {
|
||||||
|
export interface Options {
|
||||||
|
readonly finalizerExecutionStrategy?: ExecutionStrategy.ExecutionStrategy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useScope: {
|
export const useScope: {
|
||||||
(
|
(
|
||||||
deps: React.DependencyList,
|
deps: React.DependencyList,
|
||||||
options?: ScopeOptions,
|
options?: useScope.Options,
|
||||||
): Effect.Effect<Scope.Scope>
|
): Effect.Effect<Scope.Scope>
|
||||||
} = Effect.fnUntraced(function*(deps, options) {
|
} = Effect.fnUntraced(function*(deps, options) {
|
||||||
// biome-ignore lint/style/noNonNullAssertion: context initialization
|
// biome-ignore lint/style/noNonNullAssertion: context initialization
|
||||||
@@ -441,7 +440,7 @@ export const useScope: {
|
|||||||
scope => Ref.update(scopeMap.ref, HashMap.set(key, {
|
scope => Ref.update(scopeMap.ref, HashMap.set(key, {
|
||||||
scope,
|
scope,
|
||||||
closeFiber: Option.none(),
|
closeFiber: Option.none(),
|
||||||
}))
|
})),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
scope => [key, scope] as const,
|
scope => [key, scope] as const,
|
||||||
@@ -476,21 +475,6 @@ export const useScope: {
|
|||||||
return scope
|
return scope
|
||||||
})
|
})
|
||||||
|
|
||||||
const closeScope = (
|
|
||||||
scope: Scope.CloseableScope,
|
|
||||||
runtime: Runtime.Runtime<never>,
|
|
||||||
options?: ScopeOptions,
|
|
||||||
) => {
|
|
||||||
switch (options?.finalizerExecutionMode ?? "sync") {
|
|
||||||
case "sync":
|
|
||||||
Runtime.runSync(runtime)(Scope.close(scope, Exit.void))
|
|
||||||
break
|
|
||||||
case "fork":
|
|
||||||
Runtime.runFork(runtime)(Scope.close(scope, Exit.void))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useOnMount: {
|
export const useOnMount: {
|
||||||
<A, E, R>(
|
<A, E, R>(
|
||||||
f: () => Effect.Effect<A, E, R>
|
f: () => Effect.Effect<A, E, R>
|
||||||
@@ -516,52 +500,69 @@ export const useOnChange: {
|
|||||||
return yield* React.useMemo(() => Runtime.runSync(runtime)(Effect.cached(f())), deps)
|
return yield* React.useMemo(() => Runtime.runSync(runtime)(Effect.cached(f())), deps)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export namespace useReactEffect {
|
||||||
|
export interface Options {
|
||||||
|
readonly finalizerExecutionMode?: "sync" | "fork"
|
||||||
|
readonly finalizerExecutionStrategy?: ExecutionStrategy.ExecutionStrategy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useReactEffect: {
|
export const useReactEffect: {
|
||||||
<E, R>(
|
<E, R>(
|
||||||
f: () => Effect.Effect<void, E, R>,
|
f: () => Effect.Effect<void, E, R>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: ScopeOptions,
|
options?: useReactEffect.Options,
|
||||||
): Effect.Effect<void, never, Exclude<R, Scope.Scope>>
|
): Effect.Effect<void, never, Exclude<R, Scope.Scope>>
|
||||||
} = Effect.fnUntraced(function* <E, R>(
|
} = Effect.fnUntraced(function* <E, R>(
|
||||||
f: () => Effect.Effect<void, E, R>,
|
f: () => Effect.Effect<void, E, R>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: ScopeOptions,
|
options?: useReactEffect.Options,
|
||||||
) {
|
) {
|
||||||
const runtime = yield* Effect.runtime<Exclude<R, Scope.Scope>>()
|
const runtime = yield* Effect.runtime<Exclude<R, Scope.Scope>>()
|
||||||
|
|
||||||
React.useEffect(() => Effect.Do.pipe(
|
|
||||||
Effect.bind("scope", () => Scope.make(options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential)),
|
|
||||||
Effect.bind("exit", ({ scope }) => Effect.exit(Effect.provideService(f(), Scope.Scope, scope))),
|
|
||||||
Effect.map(({ scope }) =>
|
|
||||||
() => closeScope(scope, runtime, options)
|
|
||||||
),
|
|
||||||
Runtime.runSync(runtime),
|
|
||||||
// biome-ignore lint/correctness/useExhaustiveDependencies: use of React.DependencyList
|
// biome-ignore lint/correctness/useExhaustiveDependencies: use of React.DependencyList
|
||||||
), deps)
|
React.useEffect(() => runReactEffect(runtime, f, options), deps)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const runReactEffect = <E, R>(
|
||||||
|
runtime: Runtime.Runtime<Exclude<R, Scope.Scope>>,
|
||||||
|
f: () => Effect.Effect<void, E, R>,
|
||||||
|
options?: useReactEffect.Options,
|
||||||
|
) => Effect.Do.pipe(
|
||||||
|
Effect.bind("scope", () => Scope.make(options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential)),
|
||||||
|
Effect.bind("exit", ({ scope }) => Effect.exit(Effect.provideService(f(), Scope.Scope, scope))),
|
||||||
|
Effect.map(({ scope }) =>
|
||||||
|
() => {
|
||||||
|
switch (options?.finalizerExecutionMode ?? "sync") {
|
||||||
|
case "sync":
|
||||||
|
Runtime.runSync(runtime)(Scope.close(scope, Exit.void))
|
||||||
|
break
|
||||||
|
case "fork":
|
||||||
|
Runtime.runFork(runtime)(Scope.close(scope, Exit.void))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Runtime.runSync(runtime),
|
||||||
|
)
|
||||||
|
|
||||||
|
export namespace useReactLayoutEffect {
|
||||||
|
export type Options = useReactEffect.Options
|
||||||
|
}
|
||||||
|
|
||||||
export const useReactLayoutEffect: {
|
export const useReactLayoutEffect: {
|
||||||
<E, R>(
|
<E, R>(
|
||||||
f: () => Effect.Effect<void, E, R>,
|
f: () => Effect.Effect<void, E, R>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: ScopeOptions,
|
options?: useReactLayoutEffect.Options,
|
||||||
): Effect.Effect<void, never, Exclude<R, Scope.Scope>>
|
): Effect.Effect<void, never, Exclude<R, Scope.Scope>>
|
||||||
} = Effect.fnUntraced(function* <E, R>(
|
} = Effect.fnUntraced(function* <E, R>(
|
||||||
f: () => Effect.Effect<void, E, R>,
|
f: () => Effect.Effect<void, E, R>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: ScopeOptions,
|
options?: useReactLayoutEffect.Options,
|
||||||
) {
|
) {
|
||||||
const runtime = yield* Effect.runtime<Exclude<R, Scope.Scope>>()
|
const runtime = yield* Effect.runtime<Exclude<R, Scope.Scope>>()
|
||||||
|
|
||||||
React.useLayoutEffect(() => Effect.Do.pipe(
|
|
||||||
Effect.bind("scope", () => Scope.make(options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential)),
|
|
||||||
Effect.bind("exit", ({ scope }) => Effect.exit(Effect.provideService(f(), Scope.Scope, scope))),
|
|
||||||
Effect.map(({ scope }) =>
|
|
||||||
() => closeScope(scope, runtime, options)
|
|
||||||
),
|
|
||||||
Runtime.runSync(runtime),
|
|
||||||
// biome-ignore lint/correctness/useExhaustiveDependencies: use of React.DependencyList
|
// biome-ignore lint/correctness/useExhaustiveDependencies: use of React.DependencyList
|
||||||
), deps)
|
React.useLayoutEffect(() => runReactEffect(runtime, f, options), deps)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const useCallbackSync: {
|
export const useCallbackSync: {
|
||||||
@@ -598,14 +599,18 @@ export const useCallbackPromise: {
|
|||||||
return React.useCallback((...args: Args) => Runtime.runPromise(runtimeRef.current)(f(...args)), deps)
|
return React.useCallback((...args: Args) => Runtime.runPromise(runtimeRef.current)(f(...args)), deps)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export namespace useContext {
|
||||||
|
export type Options = useScope.Options
|
||||||
|
}
|
||||||
|
|
||||||
export const useContext: {
|
export const useContext: {
|
||||||
<ROut, E, RIn>(
|
<ROut, E, RIn>(
|
||||||
layer: Layer.Layer<ROut, E, RIn>,
|
layer: Layer.Layer<ROut, E, RIn>,
|
||||||
options?: ScopeOptions,
|
options?: useContext.Options,
|
||||||
): Effect.Effect<Context.Context<ROut>, E, RIn>
|
): Effect.Effect<Context.Context<ROut>, E, RIn>
|
||||||
} = Effect.fnUntraced(function* <ROut, E, RIn>(
|
} = Effect.fnUntraced(function* <ROut, E, RIn>(
|
||||||
layer: Layer.Layer<ROut, E, RIn>,
|
layer: Layer.Layer<ROut, E, RIn>,
|
||||||
options?: ScopeOptions,
|
options?: useContext.Options,
|
||||||
) {
|
) {
|
||||||
const scope = yield* useScope([layer], options)
|
const scope = yield* useScope([layer], options)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user