>
export interface Options {
readonly displayName?: string
readonly finalizerExecutionStrategy: ExecutionStrategy.ExecutionStrategy
readonly finalizerExecutionDebounce: Duration.DurationInput
}
}
const ComponentProto = Object.freeze({
...Effectable.CommitPrototype,
[TypeId]: TypeId,
commit: Effect.fnUntraced(function* (
this: Component
) {
// biome-ignore lint/style/noNonNullAssertion: React ref initialization
const runtimeRef = React.useRef>>(null!)
runtimeRef.current = yield* Effect.runtime>()
return yield* React.useState(() => Runtime.runSync(runtimeRef.current)(Effect.cachedFunction(
(_services: readonly any[]) => Effect.sync(() => {
const f: React.FC = this.makeFunctionComponent(runtimeRef)
f.displayName = this.displayName ?? "Anonymous"
return Memoized.isMemoized(this)
? React.memo(f, this.propsAreEqual)
: f
}),
Equivalence.array(Equivalence.strict()),
)))[0](Array.from(
Context.omit(...nonReactiveTags)(runtimeRef.current.context).unsafeMap.values()
))
}),
makeFunctionComponent
(
this: Component
,
runtimeRef: React.RefObject>>,
) {
return (props: P) => Runtime.runSync(runtimeRef.current)(
Effect.andThen(
useScope([], this),
scope => Effect.provideService(this.body(props), Scope.Scope, scope),
)
)
},
} as const)
const defaultOptions: Component.Options = {
finalizerExecutionStrategy: ExecutionStrategy.sequential,
finalizerExecutionDebounce: "100 millis",
}
const nonReactiveTags = [Tracer.ParentSpan] as const
export const isComponent = (u: unknown): u is Component<{}, React.ReactNode, unknown, unknown> => Predicate.hasProperty(u, TypeId)
export namespace make {
export type Gen = {
>, A extends React.ReactNode, P extends {} = {}>(
body: (props: P) => Generator
): Component<
P, A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>
>, A, B extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E, F extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E, F, G extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E, F, G, H extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => H,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E, F, G, H, I extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => H,
h: (_: H, props: NoInfer
) => I,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
>, A, B, C, D, E, F, G, H, I, J extends Effect.Effect, P extends {} = {}>(
body: (props: P) => Generator,
a: (
_: Effect.Effect<
A,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? E : never,
[Eff] extends [never] ? never : [Eff] extends [Utils.YieldWrap>] ? R : never
>,
props: NoInfer,
) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => H,
h: (_: H, props: NoInfer
) => I,
i: (_: I, props: NoInfer
) => J,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
}
export type NonGen = {
, P extends {} = {}>(
body: (props: P) => Eff
): Component>, Effect.Effect.Error, Effect.Effect.Context>
, A, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, E, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, E, F, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, E, F, G, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, E, F, G, H, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => H,
h: (_: H, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
, A, B, C, D, E, F, G, H, I, P extends {} = {}>(
body: (props: P) => A,
a: (_: A, props: NoInfer) => B,
b: (_: B, props: NoInfer
) => C,
c: (_: C, props: NoInfer
) => D,
d: (_: D, props: NoInfer
) => E,
e: (_: E, props: NoInfer
) => F,
f: (_: F, props: NoInfer
) => G,
g: (_: G, props: NoInfer
) => H,
h: (_: H, props: NoInfer
) => I,
i: (_: I, props: NoInfer
) => Eff,
): Component
>, Effect.Effect.Error, Effect.Effect.Context>
}
}
export const make: (
& make.Gen
& make.NonGen
& ((
spanName: string,
spanOptions?: Tracer.SpanOptions,
) => make.Gen & make.NonGen)
) = (spanNameOrBody: Function | string, ...pipeables: any[]): any => {
if (typeof spanNameOrBody !== "string") {
return Object.setPrototypeOf(
Object.assign(function() {}, defaultOptions, {
body: Effect.fn(spanNameOrBody as any, ...pipeables),
}),
ComponentProto,
)
}
else {
const spanOptions = pipeables[0]
return (body: any, ...pipeables: any[]) => Object.setPrototypeOf(
Object.assign(function() {}, defaultOptions, {
body: Effect.fn(spanNameOrBody, spanOptions)(body, ...pipeables as []),
displayName: spanNameOrBody,
}),
ComponentProto,
)
}
}
export const makeUntraced: (
& make.Gen
& make.NonGen
& ((name: string) => make.Gen & make.NonGen)
) = (spanNameOrBody: Function | string, ...pipeables: any[]): any => (
typeof spanNameOrBody !== "string"
? Object.setPrototypeOf(
Object.assign(function() {}, defaultOptions, {
body: Effect.fnUntraced(spanNameOrBody as any, ...pipeables as []),
}),
ComponentProto,
)
: (body: any, ...pipeables: any[]) => Object.setPrototypeOf(
Object.assign(function() {}, defaultOptions, {
body: Effect.fnUntraced(body, ...pipeables as []),
displayName: spanNameOrBody,
}),
ComponentProto,
)
)
export const withOptions: {
>(
options: Partial
): (self: T) => T
>(
self: T,
options: Partial,
): T
} = Function.dual(2, >(
self: T,
options: Partial,
): T => Object.setPrototypeOf(
Object.assign(function() {}, self, options),
Object.getPrototypeOf(self),
))
export const withRuntime: {
(
context: React.Context>,
): (self: Component>) => (props: P) => A
(
self: Component
>,
context: React.Context>,
): (props: P) => A
} = Function.dual(2, (
self: Component
,
context: React.Context>,
) => function WithRuntime(props: P) {
return React.createElement(
Runtime.runSync(React.useContext(context))(self),
props,
)
})
export class ScopeMap extends Effect.Service()("effect-fc/Component/ScopeMap", {
effect: Effect.bind(Effect.Do, "ref", () => Ref.make(HashMap.empty