0.1.8 #11

Merged
Thilawyn merged 233 commits from next into master 2025-04-21 02:08:14 +02:00
6 changed files with 45 additions and 46 deletions
Showing only changes of commit 570fb93876 - Show all commits

View File

@@ -2,8 +2,7 @@ import { R } from "@/reffuse"
import { Button, Flex, Text } from "@radix-ui/themes" import { Button, Flex, Text } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router" import { createFileRoute } from "@tanstack/react-router"
import { GetRandomValues, makeUuid4 } from "@typed/id" import { GetRandomValues, makeUuid4 } from "@typed/id"
import { Console, Effect, Ref, Stream } from "effect" import { Console, Effect, Ref } from "effect"
import { useState } from "react"
export const Route = createFileRoute("/tests")({ export const Route = createFileRoute("/tests")({

View File

@@ -1,12 +1,12 @@
import * as LazyRef from "@typed/lazy-ref" import * as LazyRef from "@typed/lazy-ref"
import { Effect, Stream } from "effect" import { Effect, Stream } from "effect"
import * as React from "react" import * as React from "react"
import { ReffuseExtension, type ReffuseHelpers, SetStateAction } from "reffuse" import { ReffuseExtension, type ReffuseNamespace, SetStateAction } from "reffuse"
export const LazyRefExtension = ReffuseExtension.make(() => ({ export const LazyRefExtension = ReffuseExtension.make(() => ({
useLazyRefState<A, E, R>( useLazyRefState<A, E, R>(
this: ReffuseHelpers.ReffuseHelpers<R>, this: ReffuseNamespace.ReffuseNamespace<R>,
ref: LazyRef.LazyRef<A, E, R>, ref: LazyRef.LazyRef<A, E, R>,
): [A, React.Dispatch<React.SetStateAction<A>>] { ): [A, React.Dispatch<React.SetStateAction<A>>] {
const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true }) const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true })

View File

@@ -1,7 +1,7 @@
import type * as AsyncData from "@typed/async-data" import type * as AsyncData from "@typed/async-data"
import { type Cause, type Context, Effect, type Fiber, Layer, type Option, type Stream, type SubscriptionRef } from "effect" import { type Cause, type Context, Effect, type Fiber, Layer, type Option, type Stream, type SubscriptionRef } from "effect"
import * as React from "react" import * as React from "react"
import { ReffuseExtension, type ReffuseHelpers } from "reffuse" import { ReffuseExtension, type ReffuseNamespace } from "reffuse"
import type * as MutationService from "./MutationService.js" import type * as MutationService from "./MutationService.js"
import * as QueryClient from "./QueryClient.js" import * as QueryClient from "./QueryClient.js"
import type * as QueryProgress from "./QueryProgress.js" import type * as QueryProgress from "./QueryProgress.js"
@@ -59,7 +59,7 @@ export const QueryExtension = ReffuseExtension.make(() => ({
QR extends R, QR extends R,
R, R,
>( >(
this: ReffuseHelpers.ReffuseHelpers<R | QueryClient.TagClassShape<FallbackA, HandledE>>, this: ReffuseNamespace.ReffuseNamespace<R | QueryClient.TagClassShape<FallbackA, HandledE>>,
props: UseQueryProps<QK, QA, QE, QR>, props: UseQueryProps<QK, QA, QE, QR>,
): UseQueryResult<QK, QA | FallbackA, Exclude<QE, HandledE>> { ): UseQueryResult<QK, QA | FallbackA, Exclude<QE, HandledE>> {
const runner = this.useMemo(() => QueryRunner.make({ const runner = this.useMemo(() => QueryRunner.make({
@@ -98,7 +98,7 @@ export const QueryExtension = ReffuseExtension.make(() => ({
QR extends R, QR extends R,
R, R,
>( >(
this: ReffuseHelpers.ReffuseHelpers<R | QueryClient.TagClassShape<FallbackA, HandledE>>, this: ReffuseNamespace.ReffuseNamespace<R | QueryClient.TagClassShape<FallbackA, HandledE>>,
props: UseMutationProps<QK, QA, QE, QR>, props: UseMutationProps<QK, QA, QE, QR>,
): UseMutationResult<QK, QA | FallbackA, Exclude<QE, HandledE>> { ): UseMutationResult<QK, QA | FallbackA, Exclude<QE, HandledE>> {
const runner = this.useMemo(() => MutationRunner.make({ const runner = this.useMemo(() => MutationRunner.make({

View File

@@ -1,30 +1,30 @@
import type * as ReffuseContext from "./ReffuseContext.js" import type * as ReffuseContext from "./ReffuseContext.js"
import type * as ReffuseExtension from "./ReffuseExtension.js" import type * as ReffuseExtension from "./ReffuseExtension.js"
import * as ReffuseHelpers from "./ReffuseHelpers.js" import * as ReffuseNamespace from "./ReffuseNamespace.js"
import type { Merge, StaticType } from "./types.js" import type { Merge, StaticType } from "./types.js"
export class Reffuse extends ReffuseHelpers.make() {} export class Reffuse extends ReffuseNamespace.makeClass() {}
export const withContexts = <R2 extends Array<unknown>>( export const withContexts = <R2 extends Array<unknown>>(
...contexts: [...{ [K in keyof R2]: ReffuseContext.ReffuseContext<R2[K]> }] ...contexts: [...{ [K in keyof R2]: ReffuseContext.ReffuseContext<R2[K]> }]
) => ( ) => (
< <
BaseClass extends ReffuseHelpers.ReffuseHelpersClass<R1>, BaseClass extends ReffuseNamespace.ReffuseNamespaceClass<R1>,
R1 R1
>( >(
self: BaseClass & ReffuseHelpers.ReffuseHelpersClass<R1> self: BaseClass & ReffuseNamespace.ReffuseNamespaceClass<R1>
): ( ): (
{ {
new(): Merge< new(): Merge<
InstanceType<BaseClass>, InstanceType<BaseClass>,
{ constructor: ReffuseHelpers.ReffuseHelpersClass<R1 | R2[number]> } { constructor: ReffuseNamespace.ReffuseNamespaceClass<R1 | R2[number]> }
> >
} & } &
Merge< Merge<
StaticType<BaseClass>, StaticType<BaseClass>,
StaticType<ReffuseHelpers.ReffuseHelpersClass<R1 | R2[number]>> StaticType<ReffuseNamespace.ReffuseNamespaceClass<R1 | R2[number]>>
> >
) => class extends self { ) => class extends self {
static readonly contexts = [...self.contexts, ...contexts] static readonly contexts = [...self.contexts, ...contexts]
@@ -33,10 +33,10 @@ export const withContexts = <R2 extends Array<unknown>>(
export const withExtension = <A extends object>(extension: ReffuseExtension.ReffuseExtension<A>) => ( export const withExtension = <A extends object>(extension: ReffuseExtension.ReffuseExtension<A>) => (
< <
BaseClass extends ReffuseHelpers.ReffuseHelpersClass<R>, BaseClass extends ReffuseNamespace.ReffuseNamespaceClass<R>,
R R
>( >(
self: BaseClass & ReffuseHelpers.ReffuseHelpersClass<R> self: BaseClass & ReffuseNamespace.ReffuseNamespaceClass<R>
): ( ): (
{ new(): Merge<InstanceType<BaseClass>, A> } & { new(): Merge<InstanceType<BaseClass>, A> } &
StaticType<BaseClass> StaticType<BaseClass>

View File

@@ -15,8 +15,8 @@ export interface ScopeOptions {
} }
export abstract class ReffuseHelpers<R> { export abstract class ReffuseNamespace<R> {
declare ["constructor"]: ReffuseHelpersClass<R> declare ["constructor"]: ReffuseNamespaceClass<R>
constructor() { constructor() {
this.SubscribeRefs = this.SubscribeRefs.bind(this as any) as any this.SubscribeRefs = this.SubscribeRefs.bind(this as any) as any
@@ -24,16 +24,16 @@ export abstract class ReffuseHelpers<R> {
} }
useContext<R>(this: ReffuseHelpers<R>): Context.Context<R> { useContext<R>(this: ReffuseNamespace<R>): Context.Context<R> {
return ReffuseContext.useMergeAll(...this.constructor.contexts) return ReffuseContext.useMergeAll(...this.constructor.contexts)
} }
useLayer<R>(this: ReffuseHelpers<R>): Layer.Layer<R> { useLayer<R>(this: ReffuseNamespace<R>): Layer.Layer<R> {
return ReffuseContext.useMergeAllLayers(...this.constructor.contexts) return ReffuseContext.useMergeAllLayers(...this.constructor.contexts)
} }
useRunSync<R>(this: ReffuseHelpers<R>): <A, E>(effect: Effect.Effect<A, E, R>) => A { useRunSync<R>(this: ReffuseNamespace<R>): <A, E>(effect: Effect.Effect<A, E, R>) => A {
const runtime = ReffuseRuntime.useRuntime() const runtime = ReffuseRuntime.useRuntime()
const context = this.useContext() const context = this.useContext()
@@ -43,7 +43,7 @@ export abstract class ReffuseHelpers<R> {
), [runtime, context]) ), [runtime, context])
} }
useRunPromise<R>(this: ReffuseHelpers<R>): <A, E>( useRunPromise<R>(this: ReffuseNamespace<R>): <A, E>(
effect: Effect.Effect<A, E, R>, effect: Effect.Effect<A, E, R>,
options?: { readonly signal?: AbortSignal }, options?: { readonly signal?: AbortSignal },
) => Promise<A> { ) => Promise<A> {
@@ -56,7 +56,7 @@ export abstract class ReffuseHelpers<R> {
), [runtime, context]) ), [runtime, context])
} }
useRunFork<R>(this: ReffuseHelpers<R>): <A, E>( useRunFork<R>(this: ReffuseNamespace<R>): <A, E>(
effect: Effect.Effect<A, E, R>, effect: Effect.Effect<A, E, R>,
options?: Runtime.RunForkOptions, options?: Runtime.RunForkOptions,
) => Fiber.RuntimeFiber<A, E> { ) => Fiber.RuntimeFiber<A, E> {
@@ -69,7 +69,7 @@ export abstract class ReffuseHelpers<R> {
), [runtime, context]) ), [runtime, context])
} }
useRunCallback<R>(this: ReffuseHelpers<R>): <A, E>( useRunCallback<R>(this: ReffuseNamespace<R>): <A, E>(
effect: Effect.Effect<A, E, R>, effect: Effect.Effect<A, E, R>,
options?: Runtime.RunCallbackOptions<A, E>, options?: Runtime.RunCallbackOptions<A, E>,
) => Runtime.Cancel<A, E> { ) => Runtime.Cancel<A, E> {
@@ -92,7 +92,7 @@ export abstract class ReffuseHelpers<R> {
* You can disable this behavior by setting `doNotReExecuteOnRuntimeOrContextChange` to `true` in `options`. * You can disable this behavior by setting `doNotReExecuteOnRuntimeOrContextChange` to `true` in `options`.
*/ */
useMemo<A, E, R>( useMemo<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R>, effect: () => Effect.Effect<A, E, R>,
deps: React.DependencyList, deps: React.DependencyList,
options?: RenderOptions, options?: RenderOptions,
@@ -106,7 +106,7 @@ export abstract class ReffuseHelpers<R> {
} }
useMemoScoped<A, E, R>( useMemoScoped<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R | Scope.Scope>, effect: () => Effect.Effect<A, E, R | Scope.Scope>,
deps: React.DependencyList, deps: React.DependencyList,
options?: RenderOptions & ScopeOptions, options?: RenderOptions & ScopeOptions,
@@ -179,7 +179,7 @@ export abstract class ReffuseHelpers<R> {
* ``` * ```
*/ */
useEffect<A, E, R>( useEffect<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R | Scope.Scope>, effect: () => Effect.Effect<A, E, R | Scope.Scope>,
deps?: React.DependencyList, deps?: React.DependencyList,
options?: RenderOptions & ScopeOptions, options?: RenderOptions & ScopeOptions,
@@ -227,7 +227,7 @@ export abstract class ReffuseHelpers<R> {
* ``` * ```
*/ */
useLayoutEffect<A, E, R>( useLayoutEffect<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R | Scope.Scope>, effect: () => Effect.Effect<A, E, R | Scope.Scope>,
deps?: React.DependencyList, deps?: React.DependencyList,
options?: RenderOptions & ScopeOptions, options?: RenderOptions & ScopeOptions,
@@ -275,7 +275,7 @@ export abstract class ReffuseHelpers<R> {
* ``` * ```
*/ */
useFork<A, E, R>( useFork<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R | Scope.Scope>, effect: () => Effect.Effect<A, E, R | Scope.Scope>,
deps?: React.DependencyList, deps?: React.DependencyList,
options?: Runtime.RunForkOptions & RenderOptions & ScopeOptions, options?: Runtime.RunForkOptions & RenderOptions & ScopeOptions,
@@ -298,7 +298,7 @@ export abstract class ReffuseHelpers<R> {
} }
usePromise<A, E, R>( usePromise<A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
effect: () => Effect.Effect<A, E, R | Scope.Scope>, effect: () => Effect.Effect<A, E, R | Scope.Scope>,
deps?: React.DependencyList, deps?: React.DependencyList,
options?: { readonly signal?: AbortSignal } & Runtime.RunForkOptions & RenderOptions & ScopeOptions, options?: { readonly signal?: AbortSignal } & Runtime.RunForkOptions & RenderOptions & ScopeOptions,
@@ -345,7 +345,7 @@ export abstract class ReffuseHelpers<R> {
} }
useCallbackSync<Args extends unknown[], A, E, R>( useCallbackSync<Args extends unknown[], A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
callback: (...args: Args) => Effect.Effect<A, E, R>, callback: (...args: Args) => Effect.Effect<A, E, R>,
deps: React.DependencyList, deps: React.DependencyList,
options?: RenderOptions, options?: RenderOptions,
@@ -359,7 +359,7 @@ export abstract class ReffuseHelpers<R> {
} }
useCallbackPromise<Args extends unknown[], A, E, R>( useCallbackPromise<Args extends unknown[], A, E, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
callback: (...args: Args) => Effect.Effect<A, E, R>, callback: (...args: Args) => Effect.Effect<A, E, R>,
deps: React.DependencyList, deps: React.DependencyList,
options?: { readonly signal?: AbortSignal } & RenderOptions, options?: { readonly signal?: AbortSignal } & RenderOptions,
@@ -373,7 +373,7 @@ export abstract class ReffuseHelpers<R> {
} }
useRef<A, R>( useRef<A, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
value: A, value: A,
): SubscriptionRef.SubscriptionRef<A> { ): SubscriptionRef.SubscriptionRef<A> {
return this.useMemo( return this.useMemo(
@@ -387,7 +387,7 @@ export abstract class ReffuseHelpers<R> {
const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[], const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[],
R, R,
>( >(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
...refs: Refs ...refs: Refs
): [...{ [K in keyof Refs]: Effect.Effect.Success<Refs[K]> }] { ): [...{ [K in keyof Refs]: Effect.Effect.Success<Refs[K]> }] {
const [reactStateValue, setReactStateValue] = React.useState(this.useMemo( const [reactStateValue, setReactStateValue] = React.useState(this.useMemo(
@@ -415,7 +415,7 @@ export abstract class ReffuseHelpers<R> {
* Note that the rules of React's immutable state still apply: updating a ref with the same value will not trigger a re-render. * Note that the rules of React's immutable state still apply: updating a ref with the same value will not trigger a re-render.
*/ */
useRefState<A, R>( useRefState<A, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
ref: SubscriptionRef.SubscriptionRef<A>, ref: SubscriptionRef.SubscriptionRef<A>,
): [A, React.Dispatch<React.SetStateAction<A>>] { ): [A, React.Dispatch<React.SetStateAction<A>>] {
const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true }) const initialState = this.useMemo(() => ref, [], { doNotReExecuteOnRuntimeOrContextChange: true })
@@ -436,7 +436,7 @@ export abstract class ReffuseHelpers<R> {
} }
useStreamFromValues<const A extends React.DependencyList, R>( useStreamFromValues<const A extends React.DependencyList, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
values: A, values: A,
): Stream.Stream<A> { ): Stream.Stream<A> {
const [queue, stream] = this.useMemo(() => Queue.unbounded<A>().pipe( const [queue, stream] = this.useMemo(() => Queue.unbounded<A>().pipe(
@@ -453,7 +453,7 @@ export abstract class ReffuseHelpers<R> {
const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[], const Refs extends readonly SubscriptionRef.SubscriptionRef<any>[],
R, R,
>( >(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
props: { props: {
readonly refs: Refs readonly refs: Refs
readonly children: (...args: [...{ [K in keyof Refs]: Effect.Effect.Success<Refs[K]> }]) => React.ReactNode readonly children: (...args: [...{ [K in keyof Refs]: Effect.Effect.Success<Refs[K]> }]) => React.ReactNode
@@ -463,7 +463,7 @@ export abstract class ReffuseHelpers<R> {
} }
RefState<A, R>( RefState<A, R>(
this: ReffuseHelpers<R>, this: ReffuseNamespace<R>,
props: { props: {
readonly ref: SubscriptionRef.SubscriptionRef<A> readonly ref: SubscriptionRef.SubscriptionRef<A>
readonly children: (state: [A, React.Dispatch<React.SetStateAction<A>>]) => React.ReactNode readonly children: (state: [A, React.Dispatch<React.SetStateAction<A>>]) => React.ReactNode
@@ -474,30 +474,30 @@ export abstract class ReffuseHelpers<R> {
} }
export interface ReffuseHelpers<R> extends Pipeable.Pipeable {} export interface ReffuseNamespace<R> extends Pipeable.Pipeable {}
ReffuseHelpers.prototype.pipe = function pipe() { ReffuseNamespace.prototype.pipe = function pipe() {
return Pipeable.pipeArguments(this, arguments) return Pipeable.pipeArguments(this, arguments)
}; };
export interface ReffuseHelpersClass<R> extends Pipeable.Pipeable { export interface ReffuseNamespaceClass<R> extends Pipeable.Pipeable {
new(): ReffuseHelpers<R> new(): ReffuseNamespace<R>
make<Self>(this: new () => Self): Self make<Self>(this: new () => Self): Self
readonly contexts: readonly ReffuseContext.ReffuseContext<R>[] readonly contexts: readonly ReffuseContext.ReffuseContext<R>[]
} }
(ReffuseHelpers as ReffuseHelpersClass<any>).make = function make() { (ReffuseNamespace as ReffuseNamespaceClass<any>).make = function make() {
return new this() return new this()
}; };
(ReffuseHelpers as ReffuseHelpersClass<any>).pipe = function pipe() { (ReffuseNamespace as ReffuseNamespaceClass<any>).pipe = function pipe() {
return Pipeable.pipeArguments(this, arguments) return Pipeable.pipeArguments(this, arguments)
}; };
export const make = (): ReffuseHelpersClass<never> => ( export const makeClass = (): ReffuseNamespaceClass<never> => (
class extends (ReffuseHelpers<never> as ReffuseHelpersClass<never>) { class extends (ReffuseNamespace<never> as ReffuseNamespaceClass<never>) {
static readonly contexts = [] static readonly contexts = []
} }
) )

View File

@@ -1,6 +1,6 @@
export * as Reffuse from "./Reffuse.js" export * as Reffuse from "./Reffuse.js"
export * as ReffuseContext from "./ReffuseContext.js" export * as ReffuseContext from "./ReffuseContext.js"
export * as ReffuseExtension from "./ReffuseExtension.js" export * as ReffuseExtension from "./ReffuseExtension.js"
export * as ReffuseHelpers from "./ReffuseHelpers.js" export * as ReffuseNamespace from "./ReffuseNamespace.js"
export * as ReffuseRuntime from "./ReffuseRuntime.js" export * as ReffuseRuntime from "./ReffuseRuntime.js"
export * as SetStateAction from "./SetStateAction.js" export * as SetStateAction from "./SetStateAction.js"