0.1.0 #1
@@ -1,51 +1,27 @@
|
|||||||
import { Context, Effect, Fiber, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect"
|
import { Context, Effect, Fiber, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import * as ReffuseReactContext from "./ReffuseReactContext.js"
|
import * as ReffuseContext from "./ReffuseContext.js"
|
||||||
|
import * as ReffuseRuntime from "./ReffuseRuntime.js"
|
||||||
|
|
||||||
|
|
||||||
export class Reffuse<
|
export class Reffuse<R> {
|
||||||
RuntimeR,
|
|
||||||
ContextR extends ParentContextR | OwnContextR,
|
|
||||||
OwnContextR,
|
|
||||||
ParentContextR = never,
|
|
||||||
> {
|
|
||||||
|
|
||||||
readonly Context = React.createContext<ReffuseReactContext.Value<RuntimeR, ContextR>>(null!)
|
|
||||||
readonly Provider: ReffuseReactContext.Provider<RuntimeR, OwnContextR, ParentContextR>
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly runtime: Runtime.Runtime<RuntimeR>,
|
readonly contexts: readonly ReffuseContext.ReffuseContext<R>[]
|
||||||
parent?: Reffuse<RuntimeR, ParentContextR, unknown, unknown>,
|
) {}
|
||||||
) {
|
|
||||||
this.Provider = parent
|
|
||||||
? ReffuseReactContext.makeNestedProvider(runtime, this.Context, parent)
|
|
||||||
: ReffuseReactContext.makeRootProvider(runtime, this.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
extend<OwnContextR = never>() {
|
|
||||||
return new Reffuse<
|
|
||||||
RuntimeR,
|
|
||||||
ContextR | OwnContextR,
|
|
||||||
OwnContextR,
|
|
||||||
ContextR
|
|
||||||
>(this.runtime, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
useRuntime(): Runtime.Runtime<RuntimeR> {
|
useContext(): Context.Context<R> {
|
||||||
return React.useContext(this.Context).runtime
|
return ReffuseContext.useMergeAll(...this.contexts)
|
||||||
}
|
|
||||||
|
|
||||||
useContext(): Context.Context<ContextR> {
|
|
||||||
return React.useContext(this.Context).context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
useRunSync() {
|
useRunSync() {
|
||||||
const { runtime, context } = React.useContext(this.Context)
|
const runtime = ReffuseRuntime.useRuntime()
|
||||||
|
const context = this.useContext()
|
||||||
|
|
||||||
return React.useCallback(<A, E>(
|
return React.useCallback(<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>
|
effect: Effect.Effect<A, E, R>
|
||||||
): A => effect.pipe(
|
): A => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
Runtime.runSync(runtime),
|
Runtime.runSync(runtime),
|
||||||
@@ -53,10 +29,11 @@ export class Reffuse<
|
|||||||
}
|
}
|
||||||
|
|
||||||
useRunPromise() {
|
useRunPromise() {
|
||||||
const { runtime, context } = React.useContext(this.Context)
|
const runtime = ReffuseRuntime.useRuntime()
|
||||||
|
const context = this.useContext()
|
||||||
|
|
||||||
return React.useCallback(<A, E>(
|
return React.useCallback(<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
effect: Effect.Effect<A, E, R>,
|
||||||
options?: { readonly signal?: AbortSignal },
|
options?: { readonly signal?: AbortSignal },
|
||||||
): Promise<A> => effect.pipe(
|
): Promise<A> => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
@@ -65,10 +42,11 @@ export class Reffuse<
|
|||||||
}
|
}
|
||||||
|
|
||||||
useRunFork() {
|
useRunFork() {
|
||||||
const { runtime, context } = React.useContext(this.Context)
|
const runtime = ReffuseRuntime.useRuntime()
|
||||||
|
const context = this.useContext()
|
||||||
|
|
||||||
return React.useCallback(<A, E>(
|
return React.useCallback(<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
effect: Effect.Effect<A, E, R>,
|
||||||
options?: Runtime.RunForkOptions,
|
options?: Runtime.RunForkOptions,
|
||||||
): Fiber.RuntimeFiber<A, E> => effect.pipe(
|
): Fiber.RuntimeFiber<A, E> => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
@@ -78,7 +56,7 @@ export class Reffuse<
|
|||||||
|
|
||||||
|
|
||||||
useMemo<A, E>(
|
useMemo<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
effect: Effect.Effect<A, E, R>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: RenderOptions,
|
options?: RenderOptions,
|
||||||
): A {
|
): A {
|
||||||
@@ -104,7 +82,7 @@ export class Reffuse<
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
useSuspense<A, E>(
|
useSuspense<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
effect: Effect.Effect<A, E, R>,
|
||||||
options?: { readonly signal?: AbortSignal },
|
options?: { readonly signal?: AbortSignal },
|
||||||
): A {
|
): A {
|
||||||
const runPromise = this.useRunPromise()
|
const runPromise = this.useRunPromise()
|
||||||
@@ -112,7 +90,7 @@ export class Reffuse<
|
|||||||
}
|
}
|
||||||
|
|
||||||
useFork<A, E>(
|
useFork<A, E>(
|
||||||
effect: Effect.Effect<A, E, RuntimeR | ContextR | Scope.Scope>,
|
effect: Effect.Effect<A, E, R | Scope.Scope>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: Runtime.RunForkOptions & RenderOptions,
|
options?: Runtime.RunForkOptions & RenderOptions,
|
||||||
): void {
|
): void {
|
||||||
@@ -136,7 +114,7 @@ export class Reffuse<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, RuntimeR | ContextR>): SubscriptionRef.SubscriptionRef<A> {
|
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, R>): SubscriptionRef.SubscriptionRef<A> {
|
||||||
return this.useMemo(
|
return this.useMemo(
|
||||||
effect.pipe(Effect.flatMap(SubscriptionRef.make)),
|
effect.pipe(Effect.flatMap(SubscriptionRef.make)),
|
||||||
[],
|
[],
|
||||||
@@ -174,9 +152,9 @@ export interface RenderOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const make = <R = never>(): Reffuse<never, R, R> =>
|
export const make = <
|
||||||
new Reffuse(Runtime.defaultRuntime)
|
const Contexts extends readonly ReffuseContext.ReffuseContext<any>[]
|
||||||
|
>(
|
||||||
export const makeWithRuntime = <R = never>() =>
|
contexts: Contexts
|
||||||
<RuntimeR>(runtime: Runtime.Runtime<RuntimeR>): Reffuse<RuntimeR, R, R> =>
|
): Reffuse<{ [K in keyof Contexts]: ReffuseContext.R<Contexts[K]> }[number]> =>
|
||||||
new Reffuse(runtime)
|
new Reffuse(contexts)
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import { Context, Effect, Runtime, type Layer } from "effect"
|
|
||||||
import React from "react"
|
|
||||||
import type * as Reffuse from "./Reffuse.js"
|
|
||||||
|
|
||||||
|
|
||||||
export interface Value<RuntimeR, ContextR> {
|
|
||||||
readonly runtime: Runtime.Runtime<RuntimeR>
|
|
||||||
readonly context: Context.Context<ContextR>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export type Provider<
|
|
||||||
RuntimeR,
|
|
||||||
OwnContextR,
|
|
||||||
ParentContextR,
|
|
||||||
> = React.FC<ProviderProps<RuntimeR, OwnContextR, ParentContextR>>
|
|
||||||
|
|
||||||
export interface ProviderProps<
|
|
||||||
RuntimeR,
|
|
||||||
OwnContextR,
|
|
||||||
ParentContextR,
|
|
||||||
> {
|
|
||||||
readonly layer: Layer.Layer<OwnContextR, unknown, RuntimeR | ParentContextR>
|
|
||||||
readonly children?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeRootProvider<
|
|
||||||
RuntimeR,
|
|
||||||
ContextR extends ParentContextR | OwnContextR,
|
|
||||||
OwnContextR,
|
|
||||||
ParentContextR,
|
|
||||||
>(
|
|
||||||
runtime: Runtime.Runtime<RuntimeR>,
|
|
||||||
ReactContext: React.Context<Value<RuntimeR, ContextR>>,
|
|
||||||
): Provider<RuntimeR, OwnContextR, ParentContextR> {
|
|
||||||
return function ReffuseRootReactContextProvider(props) {
|
|
||||||
const value = React.useMemo(() => ({
|
|
||||||
runtime,
|
|
||||||
context: Effect.context<ContextR>().pipe(
|
|
||||||
Effect.provide(props.layer),
|
|
||||||
Effect.provide(Context.empty() as Context.Context<ParentContextR>), // Just there for type safety. ParentContextR is always never here anyway
|
|
||||||
Runtime.runSync(runtime),
|
|
||||||
),
|
|
||||||
}), [props.layer])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ReactContext
|
|
||||||
{...props}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeNestedProvider<
|
|
||||||
RuntimeR,
|
|
||||||
ContextR extends ParentContextR | OwnContextR,
|
|
||||||
OwnContextR,
|
|
||||||
ParentContextR,
|
|
||||||
>(
|
|
||||||
runtime: Runtime.Runtime<RuntimeR>,
|
|
||||||
ReactContext: React.Context<Value<RuntimeR, ContextR>>,
|
|
||||||
parent: Reffuse.Reffuse<RuntimeR, ParentContextR, unknown, unknown>,
|
|
||||||
): Provider<RuntimeR, OwnContextR, ParentContextR> {
|
|
||||||
return function ReffuseNestedReactContextProvider(props) {
|
|
||||||
const parentContext = parent.useContext()
|
|
||||||
|
|
||||||
const value = React.useMemo(() => ({
|
|
||||||
runtime,
|
|
||||||
context: Effect.context<ContextR>().pipe(
|
|
||||||
Effect.provide(props.layer),
|
|
||||||
Effect.provide(parentContext),
|
|
||||||
Runtime.runSync(runtime),
|
|
||||||
),
|
|
||||||
}), [props.layer, parentContext])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ReactContext
|
|
||||||
{...props}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user