From 7b2e28451aa664260b2285437a19cf1ca0f84121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 16 Jan 2026 11:49:11 +0100 Subject: [PATCH] Refactor Form --- packages/effect-fc/src/Form.ts | 94 +++++++++++++++--------------- packages/effect-fc/src/Mutation.ts | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts index 14dde5c..87f26a8 100644 --- a/packages/effect-fc/src/Form.ts +++ b/packages/effect-fc/src/Form.ts @@ -35,6 +35,8 @@ extends Pipeable.Pipeable { field>( path: P ): Effect.Effect, PropertyPath.ValueFromPath>> + + readonly run: Effect.Effect readonly submit: Effect.Effect>, Cause.NoSuchElementException> } @@ -89,7 +91,49 @@ extends Pipeable.Class() implements Form { ) } - readonly canSubmit: Subscribable.Subscribable + readonly canSubmit: Subscribable.Subscribable + + get run(): Effect.Effect { + return this.runSemaphore.withPermits(1)(Stream.runForEach( + this.encodedValue.changes.pipe( + Option.isSome(this.debounce) ? Stream.debounce(this.debounce.value) : identity + ), + + encodedValue => this.validationFiber.pipe( + Effect.andThen(Option.match({ + onSome: Fiber.interrupt, + onNone: () => Effect.void, + })), + Effect.andThen( + Effect.forkScoped(Effect.onExit( + Schema.decode(this.schema, { errors: "all" })(encodedValue), + exit => Effect.andThen( + Exit.matchEffect(exit, { + onSuccess: v => Effect.andThen( + Ref.set(this.value, Option.some(v)), + Ref.set(this.error, Option.none()), + ), + onFailure: c => Option.match(Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"), { + onSome: e => Ref.set(this.error, Option.some(e)), + onNone: () => Effect.void, + }), + }), + Ref.set(this.validationFiber, Option.none()), + ), + )).pipe( + Effect.tap(fiber => Ref.set(this.validationFiber, Option.some(fiber))), + Effect.andThen(Fiber.join), + Effect.andThen(value => this.autosubmit + ? Effect.asVoid(Effect.forkScoped(this.submitValue(value))) + : Effect.void + ), + Effect.forkScoped, + ) + ), + Effect.provide(this.context), + ), + )) + } get submit(): Effect.Effect>, Cause.NoSuchElementException> { return this.value.pipe( @@ -97,6 +141,7 @@ extends Pipeable.Class() implements Form { Effect.andThen(value => this.submitValue(value)), ) } + submitValue(value: A): Effect.Effect>> { return Effect.whenEffect( Effect.tap( @@ -158,51 +203,6 @@ export const make = Effect.fnUntraced(function* ( - self: Form -): Effect.Effect => { - const _self = self as FormImpl - return _self.runSemaphore.withPermits(1)(Stream.runForEach( - _self.encodedValue.changes.pipe( - Option.isSome(_self.debounce) ? Stream.debounce(_self.debounce.value) : identity - ), - - encodedValue => _self.validationFiber.pipe( - Effect.andThen(Option.match({ - onSome: Fiber.interrupt, - onNone: () => Effect.void, - })), - Effect.andThen( - Effect.forkScoped(Effect.onExit( - Schema.decode(_self.schema, { errors: "all" })(encodedValue), - exit => Effect.andThen( - Exit.matchEffect(exit, { - onSuccess: v => Effect.andThen( - Ref.set(_self.value, Option.some(v)), - Ref.set(_self.error, Option.none()), - ), - onFailure: c => Option.match(Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"), { - onSome: e => Ref.set(_self.error, Option.some(e)), - onNone: () => Effect.void, - }), - }), - Ref.set(_self.validationFiber, Option.none()), - ), - )).pipe( - Effect.tap(fiber => Ref.set(_self.validationFiber, Option.some(fiber))), - Effect.andThen(Fiber.join), - Effect.andThen(value => _self.autosubmit - ? Effect.asVoid(Effect.forkScoped(_self.submitValue(value))) - : Effect.void - ), - Effect.forkScoped, - ) - ), - Effect.provide(_self.context), - ), - )) -} - export declare namespace service { export interface Options extends make.Options {} @@ -216,7 +216,7 @@ export const service = > => Effect.tap( make(options), - form => Effect.forkScoped(run(form)), + form => Effect.forkScoped(form.run), ) diff --git a/packages/effect-fc/src/Mutation.ts b/packages/effect-fc/src/Mutation.ts index 45dd11e..be4b71e 100644 --- a/packages/effect-fc/src/Mutation.ts +++ b/packages/effect-fc/src/Mutation.ts @@ -31,7 +31,7 @@ extends Pipeable.Class() implements Mutation { readonly [MutationTypeId]: MutationTypeId = MutationTypeId constructor( - readonly context: Context.Context>, + readonly context: Context.Context, readonly f: (key: K) => Effect.Effect, readonly initialProgress: P,