0.1.0 #1

Merged
Thilawyn merged 87 commits from next into master 2025-01-18 00:54:42 +01:00
3 changed files with 53 additions and 38 deletions
Showing only changes of commit 102e8a12b6 - Show all commits

View File

@@ -1,47 +1,52 @@
import { Context, Effect, Layer } from "effect" import { Context, Effect, Layer, Runtime } from "effect"
import React from "react" import React from "react"
import * as ReffuseRuntime from "./ReffuseRuntime.js"
export interface ReffuseContext<R> { export class ReffuseContext<R> {
readonly Context: React.Context<Context.Context<R>>
readonly Context = React.createContext<Context.Context<R>>(null!)
readonly Provider: ReffuseContextReactProvider<R> readonly Provider: ReffuseContextReactProvider<R>
constructor() {
this.Provider = (props) => {
const runtime = ReffuseRuntime.use()
const value = React.useMemo(() => Effect.context<R>().pipe(
Effect.provide(props.layer),
Runtime.runSync(runtime),
), [runtime, props.layer])
return (
<this.Context
{...props}
value={value}
/>
)
}
this.Provider.displayName = "ReffuseContextReactProvider"
}
use(): Context.Context<R> {
return React.useContext(this.Context)
}
useLayer(): Layer.Layer<R> {
const context = this.use()
return React.useMemo(() => Layer.effectContext(Effect.succeed(context)), [context])
}
} }
export type ReffuseContextReactProvider<R> = React.FC<{ export type ReffuseContextReactProvider<R> = React.FC<{
readonly layer: Layer.Layer<R, unknown, never> readonly layer: Layer.Layer<R, unknown>
readonly children?: React.ReactNode readonly children?: React.ReactNode
}> }>
export type R<T> = T extends ReffuseContext<infer R> ? R : never export type R<T> = T extends ReffuseContext<infer R> ? R : never
export function make<R>(): ReffuseContext<R> { export function make<R = never>() {
const Context = React.createContext<Context.Context<R>>(null!) return new ReffuseContext<R>()
return {
Context,
Provider: function ReffuseContextReactProvider(props) {
return (
<Context
{...props}
/>
)
},
}
} }
declare const MyService1: ReturnType<typeof Context.GenericTag<"MyService1", { readonly myService1: true }>>
declare const MyService2: ReturnType<typeof Context.GenericTag<"MyService2", { readonly myService2: true }>>
declare const Context1: Context.Context<typeof MyService1>
declare const Context2: Context.Context<typeof MyService2>
declare const MyService3: ReturnType<typeof Context.GenericTag<"MyService3", { readonly myService3: true }>>
declare const MyService3Live: Layer.Layer<typeof MyService3, never, typeof MyService1>
const res = MyService3Live.pipe(
Layer.provide(Layer.effectContext(Effect.succeed(Context1)))
)

View File

@@ -1,5 +0,0 @@
import type { Runtime } from "effect"
import React from "react"
export interface ReffuseRuntime<R> extends React.Context<Runtime.Runtime<R>> {}

View File

@@ -0,0 +1,15 @@
import { Runtime } from "effect"
import React from "react"
export const Context = React.createContext<Runtime.Runtime<never>>(null!)
export const Provider = (props: { readonly children?: React.ReactNode }) => (
<Context
{...props}
value={Runtime.defaultRuntime}
/>
)
Provider.displayName = "ReffuseRuntimeReactProvider"
export const use = () => React.useContext(Context)