diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts index d0b9861..db57638 100644 --- a/packages/effect-fc/src/Form.ts +++ b/packages/effect-fc/src/Form.ts @@ -1,4 +1,4 @@ -import { Cause, Chunk, type Context, type Duration, Effect, Equal, Exit, Fiber, identity, Option, type ParseResult, Pipeable, Predicate, Schema, type Scope, Stream } from "effect" +import { Array, Cause, Chunk, type Context, type Duration, Effect, Equal, Exit, Fiber, identity, Option, ParseResult, Pipeable, Predicate, Schema, type Scope, Stream } from "effect" import type * as React from "react" import * as Component from "./Component.js" import * as Lens from "./Lens.js" @@ -18,7 +18,7 @@ extends Pipeable.Pipeable { readonly path: P readonly value: Subscribable.Subscribable, ER, never> readonly encodedValue: Lens.Lens - readonly error: Subscribable.Subscribable, ER, never> + readonly issues: Subscribable.Subscribable readonly isValidating: Subscribable.Subscribable readonly canSubmit: Subscribable.Subscribable } @@ -31,7 +31,7 @@ extends Pipeable.Class() implements Form { readonly path: P, readonly value: Subscribable.Subscribable, ER, never>, readonly encodedValue: Lens.Lens, - readonly error: Subscribable.Subscribable, ER, never>, + readonly issues: Subscribable.Subscribable, readonly isValidating: Subscribable.Subscribable, readonly canSubmit: Subscribable.Subscribable, ) { @@ -77,7 +77,7 @@ extends Pipeable.Class() implements RootForm { readonly value: Lens.Lens, never, never, never, never>, readonly encodedValue: Lens.Lens, - readonly error: Lens.Lens, never, never, never, never>, + readonly issues: Lens.Lens, readonly validationFiber: Lens.Lens>, never, never, never, never>, readonly isValidating: Subscribable.Subscribable, readonly canSubmit: Subscribable.Subscribable, @@ -103,10 +103,13 @@ extends Pipeable.Class() implements RootForm { Exit.matchEffect(exit, { onSuccess: v => Effect.andThen( Lens.set(this.value, Option.some(v)), - Lens.set(this.error, Option.none()), + Lens.set(this.issues, Array.empty()), ), onFailure: c => Option.match(Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"), { - onSome: e => Lens.set(this.error, Option.some(e)), + onSome: e => Effect.flatMap( + ParseResult.ArrayFormatter.formatError(e), + v => Lens.set(this.issues, v), + ), onNone: () => Effect.void, }), }), @@ -145,7 +148,10 @@ extends Pipeable.Class() implements RootForm { e => e._tag === "ParseError", ), { - onSome: e => Lens.set(this.error, Option.some(e)), + onSome: e => Effect.flatMap( + ParseResult.ArrayFormatter.formatError(e), + v => Lens.set(this.issues, v), + ), onNone: () => Effect.void, }, ) @@ -183,7 +189,7 @@ export const make = Effect.fnUntraced(function* { const mutation = yield* Mutation.make(options) const valueLens = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Option.none())) - const errorLens = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Option.none())) + const issuesLens = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Array.empty())) const validationFiberLens = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Option.none>())) return new RootFormImpl( @@ -194,14 +200,14 @@ export const make = Effect.fnUntraced(function* ( + Subscribable.zipLatestAll(valueLens, issuesLens, validationFiberLens, mutation.result), + ([value, issues, validationFiber, result]) => ( Option.isSome(value) && - Option.isNone(error) && + Array.isEmptyReadonlyArray(issues) && Option.isNone(validationFiber) && !(Result.isRunning(result) || Result.hasRefreshingFlag(result)) ), @@ -238,7 +244,7 @@ export const focusObjectField =

a[key])), Lens.focusObjectField(form.encodedValue, key), - form.error, + form.issues, form.isValidating, form.canSubmit, )