This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
import { Context, Effect, ExecutionStrategy, Function, Pipeable, Runtime, Scope, String, Tracer, type Types, type Utils } from "effect"
|
import { Context, Effect, ExecutionStrategy, Function, Pipeable, Runtime, Scope, String, Tracer, type Utils } from "effect"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import * as Hook from "./Hook.js"
|
import * as Hook from "./Hook.js"
|
||||||
|
import type { ExcludeKeys } from "./utils.js"
|
||||||
|
|
||||||
|
|
||||||
export interface Component<E, R, P extends {}> extends Pipeable.Pipeable {
|
export interface Component<E, R, P extends {}> extends Pipeable.Pipeable {
|
||||||
(props: P): Effect.Effect<React.ReactNode, E, R>
|
readonly body: (props: P) => Effect.Effect<React.ReactNode, E, R>
|
||||||
readonly displayName?: string
|
readonly displayName?: string
|
||||||
readonly options: Options
|
readonly options: Options
|
||||||
}
|
}
|
||||||
@@ -18,7 +19,12 @@ export type Error<T> = T extends Component<infer E, infer _R, infer _P> ? E : ne
|
|||||||
export type Context<T> = T extends Component<infer _E, infer R, infer _P> ? R : never
|
export type Context<T> = T extends Component<infer _E, infer R, infer _P> ? R : never
|
||||||
export type Props<T> = T extends Component<infer _E, infer _R, infer P> ? P : never
|
export type Props<T> = T extends Component<infer _E, infer _R, infer P> ? P : never
|
||||||
|
|
||||||
export const nonReactiveTags = [Tracer.ParentSpan] as const
|
|
||||||
|
const ComponentProto = {
|
||||||
|
pipe() { return Pipeable.pipeArguments(this, arguments) }
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const nonReactiveTags = [Tracer.ParentSpan] as const
|
||||||
|
|
||||||
|
|
||||||
export interface MakeOptions {
|
export interface MakeOptions {
|
||||||
@@ -40,21 +46,18 @@ export const make = <
|
|||||||
> => {
|
> => {
|
||||||
const displayName = !String.isEmpty(body.name) ? body.name : undefined
|
const displayName = !String.isEmpty(body.name) ? body.name : undefined
|
||||||
|
|
||||||
const f = ((options?.traced ?? true)
|
return Object.setPrototypeOf({
|
||||||
|
body: (options?.traced ?? true)
|
||||||
? displayName
|
? displayName
|
||||||
? Effect.fn(displayName)(body)
|
? Effect.fn(displayName)(body)
|
||||||
: Effect.fn(body)
|
: Effect.fn(body)
|
||||||
: Effect.fnUntraced(body)
|
: Effect.fnUntraced(body),
|
||||||
) as Component<any, any, any>
|
displayName,
|
||||||
|
options: {
|
||||||
f.pipe = function pipe() { return Pipeable.pipeArguments(this, arguments) };
|
|
||||||
(f as Types.Mutable<typeof f>).displayName = displayName;
|
|
||||||
(f as Types.Mutable<typeof f>).options = {
|
|
||||||
finalizerExecutionMode: options?.finalizerExecutionMode ?? "sync",
|
finalizerExecutionMode: options?.finalizerExecutionMode ?? "sync",
|
||||||
finalizerExecutionStrategy: options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential,
|
finalizerExecutionStrategy: options?.finalizerExecutionStrategy ?? ExecutionStrategy.sequential,
|
||||||
}
|
},
|
||||||
|
}, ComponentProto)
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -78,7 +81,7 @@ export const useFC: {
|
|||||||
|
|
||||||
const FC = React.useMemo(() => {
|
const FC = React.useMemo(() => {
|
||||||
const f = (props: P) => Runtime.runSync(runtimeRef.current)(
|
const f = (props: P) => Runtime.runSync(runtimeRef.current)(
|
||||||
Effect.provideService(self(props), Scope.Scope, scope)
|
Effect.provideService(self.body(props), Scope.Scope, scope)
|
||||||
)
|
)
|
||||||
f.displayName = self.displayName ?? "Anonymous"
|
f.displayName = self.displayName ?? "Anonymous"
|
||||||
return f
|
return f
|
||||||
@@ -89,7 +92,7 @@ export const useFC: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const useSuspenseFC: {
|
export const useSuspenseFC: {
|
||||||
<E, R, P extends {}>(
|
<E, R, P extends ExcludeKeys<{}, "suspenseProps">>(
|
||||||
self: Component<E, R, P>
|
self: Component<E, R, P>
|
||||||
): Effect.Effect<
|
): Effect.Effect<
|
||||||
React.FC<P & { readonly suspenseProps: React.SuspenseProps }>,
|
React.FC<P & { readonly suspenseProps: React.SuspenseProps }>,
|
||||||
@@ -115,7 +118,7 @@ export const useSuspenseFC: {
|
|||||||
|
|
||||||
const f = ({ suspenseProps, ...props }: P & { readonly suspenseProps: React.SuspenseProps }) => {
|
const f = ({ suspenseProps, ...props }: P & { readonly suspenseProps: React.SuspenseProps }) => {
|
||||||
const promise = Runtime.runPromise(runtimeRef.current)(
|
const promise = Runtime.runPromise(runtimeRef.current)(
|
||||||
Effect.provideService(self(props), Scope.Scope, scope)
|
Effect.provideService(self.body(props as P), Scope.Scope, scope)
|
||||||
)
|
)
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
|
|||||||
3
packages/effect-fc/src/utils.ts
Normal file
3
packages/effect-fc/src/utils.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export type ExcludeKeys<T, K extends PropertyKey> = K extends keyof T ? (
|
||||||
|
{ [P in K]?: never } & Omit<T, K>
|
||||||
|
) : T
|
||||||
Reference in New Issue
Block a user