This commit is contained in:
@@ -1,47 +0,0 @@
|
|||||||
import { Effect, type Layer, ManagedRuntime, type Runtime } from "effect"
|
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
|
|
||||||
export interface ReactManagedRuntime<R, ER> {
|
|
||||||
readonly runtime: ManagedRuntime.ManagedRuntime<R, ER>
|
|
||||||
readonly context: React.Context<Runtime.Runtime<R>>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const make = <R, ER>(
|
|
||||||
layer: Layer.Layer<R, ER>,
|
|
||||||
memoMap?: Layer.MemoMap,
|
|
||||||
): ReactManagedRuntime<R, ER> => ({
|
|
||||||
runtime: ManagedRuntime.make(layer, memoMap),
|
|
||||||
context: React.createContext<Runtime.Runtime<R>>(null!),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
export interface ProviderProps<R, ER> extends React.SuspenseProps {
|
|
||||||
readonly runtime: ReactManagedRuntime<R, ER>
|
|
||||||
readonly children?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Provider<R, ER>(
|
|
||||||
{ runtime, children, ...suspenseProps }: ProviderProps<R, ER>
|
|
||||||
): React.ReactNode {
|
|
||||||
const promise = React.useMemo(() => Effect.runPromise(runtime.runtime.runtimeEffect), [runtime])
|
|
||||||
|
|
||||||
return React.createElement(
|
|
||||||
React.Suspense,
|
|
||||||
suspenseProps,
|
|
||||||
React.createElement(ProviderInner<R, ER>, { runtime, promise, children }),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProviderInnerProps<R, ER> {
|
|
||||||
readonly runtime: ReactManagedRuntime<R, ER>
|
|
||||||
readonly promise: Promise<Runtime.Runtime<R>>
|
|
||||||
readonly children?: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProviderInner<R, ER>(
|
|
||||||
{ runtime, promise, children }: ProviderInnerProps<R, ER>
|
|
||||||
): React.ReactNode {
|
|
||||||
const value = React.use(promise)
|
|
||||||
return React.createElement(runtime.context, { value }, children)
|
|
||||||
}
|
|
||||||
64
packages/effect-fc/src/ReactRuntime.ts
Normal file
64
packages/effect-fc/src/ReactRuntime.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { Effect, type Layer, ManagedRuntime, Predicate, type Runtime } from "effect"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
|
||||||
|
export const TypeId: unique symbol = Symbol.for("effect-fc/ReactRuntime")
|
||||||
|
export type TypeId = typeof TypeId
|
||||||
|
|
||||||
|
export interface ReactRuntime<R, ER> {
|
||||||
|
new(_: never): {}
|
||||||
|
readonly [TypeId]: TypeId
|
||||||
|
readonly runtime: ManagedRuntime.ManagedRuntime<R, ER>
|
||||||
|
readonly context: React.Context<Runtime.Runtime<R>>
|
||||||
|
}
|
||||||
|
|
||||||
|
const ReactRuntimeProto = Object.freeze({ [TypeId]: TypeId } as const)
|
||||||
|
|
||||||
|
|
||||||
|
export const isReactRuntime = (u: unknown): u is ReactRuntime<unknown, unknown> => Predicate.hasProperty(u, TypeId)
|
||||||
|
|
||||||
|
export const make = <R, ER>(
|
||||||
|
layer: Layer.Layer<R, ER>,
|
||||||
|
memoMap?: Layer.MemoMap,
|
||||||
|
): ReactRuntime<R, ER> => Object.setPrototypeOf(
|
||||||
|
Object.assign(function() {}, {
|
||||||
|
runtime: ManagedRuntime.make(layer, memoMap),
|
||||||
|
context: React.createContext<Runtime.Runtime<R>>(null!),
|
||||||
|
}),
|
||||||
|
ReactRuntimeProto,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
export namespace Provider {
|
||||||
|
export interface Props<R, ER> extends React.SuspenseProps {
|
||||||
|
readonly runtime: ReactRuntime<R, ER>
|
||||||
|
readonly children?: React.ReactNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Provider = <R, ER>(
|
||||||
|
{ runtime, children, ...suspenseProps }: Provider.Props<R, ER>
|
||||||
|
): React.ReactNode => {
|
||||||
|
const promise = React.useMemo(() => Effect.runPromise(runtime.runtime.runtimeEffect), [runtime])
|
||||||
|
|
||||||
|
return React.createElement(
|
||||||
|
React.Suspense,
|
||||||
|
suspenseProps,
|
||||||
|
React.createElement(ProviderInner<R, ER>, { runtime, promise, children }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ProviderInner {
|
||||||
|
export interface Props<R, ER> {
|
||||||
|
readonly runtime: ReactRuntime<R, ER>
|
||||||
|
readonly promise: Promise<Runtime.Runtime<R>>
|
||||||
|
readonly children?: React.ReactNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProviderInner = <R, ER>(
|
||||||
|
{ runtime, promise, children }: ProviderInner.Props<R, ER>
|
||||||
|
): React.ReactNode => {
|
||||||
|
const value = React.use(promise)
|
||||||
|
return React.createElement(runtime.context, { value }, children)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export * as Component from "./Component.js"
|
export * as Component from "./Component.js"
|
||||||
export * as Memo from "./Memo.js"
|
export * as Memo from "./Memo.js"
|
||||||
export * as ReactManagedRuntime from "./ReactManagedRuntime.js"
|
export * as ReactRuntime from "./ReactRuntime.js"
|
||||||
export * as Suspense from "./Suspense.js"
|
export * as Suspense from "./Suspense.js"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createRouter, RouterProvider } from "@tanstack/react-router"
|
import { createRouter, RouterProvider } from "@tanstack/react-router"
|
||||||
import { ReactManagedRuntime } from "effect-fc"
|
import { ReactRuntime } from "effect-fc"
|
||||||
import { StrictMode } from "react"
|
import { StrictMode } from "react"
|
||||||
import { createRoot } from "react-dom/client"
|
import { createRoot } from "react-dom/client"
|
||||||
import { routeTree } from "./routeTree.gen"
|
import { routeTree } from "./routeTree.gen"
|
||||||
@@ -16,8 +16,8 @@ declare module "@tanstack/react-router" {
|
|||||||
|
|
||||||
createRoot(document.getElementById("root")!).render(
|
createRoot(document.getElementById("root")!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<ReactManagedRuntime.Provider runtime={runtime}>
|
<ReactRuntime.Provider runtime={runtime}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</ReactManagedRuntime.Provider>
|
</ReactRuntime.Provider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FetchHttpClient } from "@effect/platform"
|
import { FetchHttpClient } from "@effect/platform"
|
||||||
import { Clipboard, Geolocation, Permissions } from "@effect/platform-browser"
|
import { Clipboard, Geolocation, Permissions } from "@effect/platform-browser"
|
||||||
import { DateTime, Layer } from "effect"
|
import { DateTime, Layer } from "effect"
|
||||||
import { ReactManagedRuntime } from "effect-fc"
|
import { ReactRuntime } from "effect-fc"
|
||||||
|
|
||||||
|
|
||||||
export const AppLive = Layer.empty.pipe(
|
export const AppLive = Layer.empty.pipe(
|
||||||
@@ -12,4 +12,4 @@ export const AppLive = Layer.empty.pipe(
|
|||||||
Layer.provideMerge(FetchHttpClient.layer),
|
Layer.provideMerge(FetchHttpClient.layer),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const runtime = ReactManagedRuntime.make(AppLive)
|
export const runtime = ReactRuntime.make(AppLive)
|
||||||
|
|||||||
Reference in New Issue
Block a user