Refactor Form
All checks were successful
Lint / lint (push) Successful in 11s

This commit is contained in:
Julien Valverdé
2025-11-12 03:17:04 +01:00
parent da0847b3f9
commit d38e220df8
2 changed files with 26 additions and 13 deletions

View File

@@ -63,16 +63,20 @@ export namespace make {
readonly onSubmit: ( readonly onSubmit: (
this: Form<NoInfer<A>, NoInfer<I>, NoInfer<R>, unknown, unknown, unknown>, this: Form<NoInfer<A>, NoInfer<I>, NoInfer<R>, unknown, unknown, unknown>,
value: NoInfer<A>, value: NoInfer<A>,
) => Effect.Effect<SA, SE, SR> ) => Effect.Effect<SA, SE, Result.forkEffectPubSub.InputContext<SR, NoInfer<SP>>>
readonly initialSubmitProgress?: SP readonly initialSubmitProgress?: SP
readonly autosubmit?: boolean readonly autosubmit?: boolean
readonly debounce?: Duration.DurationInput readonly debounce?: Duration.DurationInput
} }
export type Success<A, I, R, SA = void, SE = A, SR = never, SP = never> = (
Form<A, I, R, SA, SE, Exclude<SR, Result.Progress<any> | Result.Progress<never>>, SP>
)
} }
export const make = Effect.fnUntraced(function* <A, I = A, R = never, SA = void, SE = A, SR = never, SP = never>( export const make = Effect.fnUntraced(function* <A, I = A, R = never, SA = void, SE = A, SR = never, SP = never>(
options: make.Options<A, I, R, SA, SE, SR, SP> options: make.Options<A, I, R, SA, SE, SR, SP>
): Effect.fn.Return<Form<A, I, R, SA, SE, SR, SP>> { ): Effect.fn.Return<make.Success<A, I, R, SA, SE, SR, SP>> {
const valueRef = yield* SubscriptionRef.make(Option.none<A>()) const valueRef = yield* SubscriptionRef.make(Option.none<A>())
const errorRef = yield* SubscriptionRef.make(Option.none<ParseResult.ParseError>()) const errorRef = yield* SubscriptionRef.make(Option.none<ParseResult.ParseError>())
const validationFiberRef = yield* SubscriptionRef.make(Option.none<Fiber.Fiber<A, ParseResult.ParseError>>()) const validationFiberRef = yield* SubscriptionRef.make(Option.none<Fiber.Fiber<A, ParseResult.ParseError>>())
@@ -80,7 +84,7 @@ export const make = Effect.fnUntraced(function* <A, I = A, R = never, SA = void,
return new FormImpl( return new FormImpl(
options.schema, options.schema,
options.onSubmit, options.onSubmit as any,
options.initialSubmitProgress as SP, options.initialSubmitProgress as SP,
options.autosubmit ?? false, options.autosubmit ?? false,
Option.fromNullable(options.debounce), Option.fromNullable(options.debounce),
@@ -149,7 +153,7 @@ export const submit = <A, I, R, SA, SE, SR, SP>(
): Effect.Effect< ): Effect.Effect<
Option.Option<Result.Result<SA, SE, SP>>, Option.Option<Result.Result<SA, SE, SP>>,
NoSuchElementException, NoSuchElementException,
Scope.Scope | Result.forkEffectPubSub.OutputContext<SR> Scope.Scope | SR
> => Effect.whenEffect( > => Effect.whenEffect(
self.valueRef.pipe( self.valueRef.pipe(
Effect.andThen(identity), Effect.andThen(identity),
@@ -185,11 +189,17 @@ export const submit = <A, I, R, SA, SE, SR, SP>(
export namespace service { export namespace service {
export interface Options<in out A, in out I, in out R, in out SA = void, in out SE = A, out SR = never, in out SP = never> export interface Options<in out A, in out I, in out R, in out SA = void, in out SE = A, out SR = never, in out SP = never>
extends make.Options<A, I, R, SA, SE, SR, SP> {} extends make.Options<A, I, R, SA, SE, SR, SP> {}
export type Return<A, I, R, SA = void, SE = A, SR = never, SP = never> = Effect.Effect<
Form<A, I, R, SA, SE, Exclude<SR, Result.Progress<any> | Result.Progress<never>>, SP>,
never,
Scope.Scope | R | Exclude<SR, Result.Progress<any> | Result.Progress<never>>
>
} }
export const service = <A, I = A, R = never, SA = void, SE = A, SR = never, SP = never>( export const service = <A, I = A, R = never, SA = void, SE = A, SR = never, SP = never>(
options: service.Options<A, I, R, SA, SE, SR, SP> options: service.Options<A, I, R, SA, SE, SR, SP>
): Effect.Effect<Form<A, I, R, SA, SE, SR, SP>, never, Scope.Scope | R | SR> => Effect.tap( ): service.Return<A, I, R, SA, SE, SR, SP> => Effect.tap(
make(options), make(options),
form => Effect.forkScoped(run(form)), form => Effect.forkScoped(run(form)),
) )

View File

@@ -186,7 +186,7 @@ export const makeProgressLayer = <A, E, P = never>(): Layer.Layer<
})) }))
export namespace forkEffect { export namespace forkEffectSubscriptionRef {
export type InputContext<R, P> = R extends Progress<infer X> ? [X] extends [P] ? R : never : R export type InputContext<R, P> = R extends Progress<infer X> ? [X] extends [P] ? R : never : R
export type OutputContext<R> = Scope.Scope | Exclude<R, Progress<any> | Progress<never>> export type OutputContext<R> = Scope.Scope | Exclude<R, Progress<any> | Progress<never>>
@@ -195,13 +195,13 @@ export namespace forkEffect {
} }
} }
export const forkEffect = <A, E, R, P = never>( export const forkEffectSubscriptionRef = <A, E, R, P = never>(
effect: Effect.Effect<A, E, forkEffect.InputContext<R, NoInfer<P>>>, effect: Effect.Effect<A, E, forkEffectSubscriptionRef.InputContext<R, NoInfer<P>>>,
options?: forkEffect.Options<P>, options?: forkEffectSubscriptionRef.Options<P>,
): Effect.Effect< ): Effect.Effect<
Subscribable.Subscribable<Result<A, E, P>>, Subscribable.Subscribable<Result<A, E, P>>,
never, never,
forkEffect.OutputContext<R> forkEffectSubscriptionRef.OutputContext<R>
> => Effect.tap( > => Effect.tap(
SubscriptionRef.make<Result<A, E, P>>(initial()), SubscriptionRef.make<Result<A, E, P>>(initial()),
ref => Effect.forkScoped(State<A, E, P>().pipe( ref => Effect.forkScoped(State<A, E, P>().pipe(
@@ -220,9 +220,12 @@ export const forkEffect = <A, E, R, P = never>(
) as Effect.Effect<Subscribable.Subscribable<Result<A, E, P>>, never, Scope.Scope> ) as Effect.Effect<Subscribable.Subscribable<Result<A, E, P>>, never, Scope.Scope>
export namespace forkEffectPubSub { export namespace forkEffectPubSub {
export type InputContext<R, P> = forkEffect.InputContext<R, P> export type InputContext<R, P> = R extends Progress<infer X> ? [X] extends [P] ? R : never : R
export type OutputContext<R> = forkEffect.OutputContext<R> export type OutputContext<R> = Scope.Scope | Exclude<R, Progress<any> | Progress<never>>
export interface Options<P> extends forkEffect.Options<P> {}
export interface Options<P> {
readonly initialProgress?: P
}
} }
export const forkEffectPubSub = <A, E, R, P = never>( export const forkEffectPubSub = <A, E, R, P = never>(