0.1.0 #1
@@ -1,23 +1,24 @@
|
|||||||
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 type * as ReffuseReactContext from "./ReffuseReactContext.js"
|
import * as ReffuseReactContext from "./ReffuseReactContext.js"
|
||||||
import * as ReffuseReactContextProvider from "./ReffuseReactContextProvider.js"
|
|
||||||
|
|
||||||
|
|
||||||
export class Reffuse<
|
export class Reffuse<
|
||||||
R extends RuntimeR | ContextR,
|
|
||||||
RuntimeR,
|
RuntimeR,
|
||||||
ContextR,
|
ContextR extends ParentContextR | OwnContextR,
|
||||||
Parent extends Reffuse<any, any, any, any>,
|
OwnContextR,
|
||||||
|
ParentContextR = never,
|
||||||
> {
|
> {
|
||||||
|
|
||||||
readonly Context = React.createContext<ReffuseReactContext.Value<RuntimeR, ContextR>>(null!)
|
readonly Context = React.createContext<ReffuseReactContext.Value<RuntimeR, ContextR>>(null!)
|
||||||
readonly Provider: ReffuseReactContextProvider.ReffuseReactContextProvider<R>
|
readonly Provider: ReffuseReactContext.Provider<RuntimeR, OwnContextR, ParentContextR>
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
runtime: Runtime.Runtime<RuntimeR>
|
runtime: Runtime.Runtime<RuntimeR>,
|
||||||
|
parent?: Reffuse<RuntimeR, ParentContextR, unknown, unknown>,
|
||||||
) {
|
) {
|
||||||
this.Provider = ReffuseReactContextProvider.make(runtime, this.Context)
|
// TODO: split into makeProvider and makeScopedProvider
|
||||||
|
this.Provider = ReffuseReactContext.makeProvider(runtime, this.Context, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +34,9 @@ export class Reffuse<
|
|||||||
useRunSync() {
|
useRunSync() {
|
||||||
const { runtime, context } = React.useContext(this.Context)
|
const { runtime, context } = React.useContext(this.Context)
|
||||||
|
|
||||||
return React.useCallback(<A, E>(effect: Effect.Effect<A, E, R>): A => effect.pipe(
|
return React.useCallback(<A, E>(
|
||||||
|
effect: Effect.Effect<A, E, RuntimeR | ContextR>
|
||||||
|
): A => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
Runtime.runSync(runtime),
|
Runtime.runSync(runtime),
|
||||||
), [runtime, context])
|
), [runtime, context])
|
||||||
@@ -43,7 +46,7 @@ export class Reffuse<
|
|||||||
const { runtime, context } = React.useContext(this.Context)
|
const { runtime, context } = React.useContext(this.Context)
|
||||||
|
|
||||||
return React.useCallback(<A, E>(
|
return React.useCallback(<A, E>(
|
||||||
effect: Effect.Effect<A, E, R>,
|
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
||||||
options?: { readonly signal?: AbortSignal },
|
options?: { readonly signal?: AbortSignal },
|
||||||
): Promise<A> => effect.pipe(
|
): Promise<A> => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
@@ -55,7 +58,7 @@ export class Reffuse<
|
|||||||
const { runtime, context } = React.useContext(this.Context)
|
const { runtime, context } = React.useContext(this.Context)
|
||||||
|
|
||||||
return React.useCallback(<A, E>(
|
return React.useCallback(<A, E>(
|
||||||
effect: Effect.Effect<A, E, R>,
|
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
||||||
options?: Runtime.RunForkOptions,
|
options?: Runtime.RunForkOptions,
|
||||||
): Fiber.RuntimeFiber<A, E> => effect.pipe(
|
): Fiber.RuntimeFiber<A, E> => effect.pipe(
|
||||||
Effect.provide(context),
|
Effect.provide(context),
|
||||||
@@ -65,7 +68,7 @@ export class Reffuse<
|
|||||||
|
|
||||||
|
|
||||||
useFork<A, E>(
|
useFork<A, E>(
|
||||||
self: Effect.Effect<A, E, R | Scope.Scope>,
|
self: Effect.Effect<A, E, RuntimeR | ContextR | Scope.Scope>,
|
||||||
deps?: React.DependencyList,
|
deps?: React.DependencyList,
|
||||||
options?: Runtime.RunForkOptions,
|
options?: Runtime.RunForkOptions,
|
||||||
): void {
|
): void {
|
||||||
@@ -83,7 +86,7 @@ export class Reffuse<
|
|||||||
return React.useMemo(() => runSync(SubscriptionRef.make(value)), [])
|
return React.useMemo(() => runSync(SubscriptionRef.make(value)), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, R>): SubscriptionRef.SubscriptionRef<A> {
|
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, RuntimeR | ContextR>): SubscriptionRef.SubscriptionRef<A> {
|
||||||
const runSync = this.useRunSync()
|
const runSync = this.useRunSync()
|
||||||
|
|
||||||
return React.useMemo(() => runSync(effect.pipe(
|
return React.useMemo(() => runSync(effect.pipe(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Effect, Runtime, type Context, type Layer } from "effect"
|
import { Context, Effect, Runtime, type Layer } from "effect"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
|
import type * as Reffuse from "./Reffuse.js"
|
||||||
|
|
||||||
|
|
||||||
export interface Value<RuntimeR, ContextR> {
|
export interface Value<RuntimeR, ContextR> {
|
||||||
@@ -8,32 +9,66 @@ export interface Value<RuntimeR, ContextR> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface ProviderProps<R> {
|
export type Provider<
|
||||||
readonly layer: Layer.Layer<R, unknown>
|
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
|
readonly children?: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Provider<R> = React.FC<ProviderProps<R>>
|
export function makeProvider<
|
||||||
|
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 parent
|
||||||
|
? function ReffuseReactContextProvider(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])
|
||||||
|
|
||||||
export function makeProvider<R>(
|
return (
|
||||||
runtime: Runtime.Runtime<never>,
|
<ReactContext
|
||||||
Context: React.Context<Value<R>>,
|
{...props}
|
||||||
) {
|
value={value}
|
||||||
return function ReffuseReactContextProvider(props: ProviderProps<R>) {
|
/>
|
||||||
const value = React.useMemo(() => ({
|
)
|
||||||
runtime,
|
}
|
||||||
context: Effect.context<R>().pipe(
|
: function ReffuseReactContextProvider(props) {
|
||||||
Effect.provide(props.layer),
|
const value = React.useMemo(() => ({
|
||||||
Runtime.runSync(runtime),
|
runtime,
|
||||||
),
|
context: Effect.context<ContextR>().pipe(
|
||||||
}), [props.layer])
|
Effect.provide(props.layer),
|
||||||
|
Effect.provide(Context.empty() as Context.Context<ParentContextR>), // Required for type safety
|
||||||
|
Runtime.runSync(runtime),
|
||||||
|
),
|
||||||
|
}), [props.layer])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Context
|
<ReactContext
|
||||||
{...props}
|
{...props}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Effect, Runtime, type Layer } from "effect"
|
|
||||||
import React from "react"
|
|
||||||
import type * as ReffuseReactContext from "./ReffuseReactContext.js"
|
|
||||||
|
|
||||||
|
|
||||||
export interface Props<R> {
|
|
||||||
readonly layer: Layer.Layer<R, unknown>
|
|
||||||
readonly children?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ReffuseReactContextProvider<R> = React.FC<Props<R>>
|
|
||||||
|
|
||||||
|
|
||||||
export function make<R>(
|
|
||||||
runtime: Runtime.Runtime<never>,
|
|
||||||
Context: React.Context<ReffuseReactContext.ReffuseReactContext<R>>,
|
|
||||||
) {
|
|
||||||
return function ReffuseReactContextProvider(props: Props<R>) {
|
|
||||||
const value = React.useMemo(() => ({
|
|
||||||
runtime,
|
|
||||||
context: Effect.context<R>().pipe(
|
|
||||||
Effect.provide(props.layer),
|
|
||||||
Runtime.runSync(runtime),
|
|
||||||
),
|
|
||||||
}), [props.layer])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Context
|
|
||||||
{...props}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user