0.1.4 #5
@@ -1,5 +1,5 @@
|
|||||||
import * as AsyncData from "@typed/async-data"
|
import * as AsyncData from "@typed/async-data"
|
||||||
import { Array, Duration, Effect, Equal, Exit, flow, identity, Option, ParseResult, pipe, Pipeable, Ref, Schema, Scope, Stream, Subscribable, SubscriptionRef } from "effect"
|
import { Array, Cause, Chunk, Duration, Effect, Equal, Exit, Fiber, flow, identity, Option, ParseResult, pipe, Pipeable, Ref, Schema, Scope, Stream, Subscribable, SubscriptionRef } from "effect"
|
||||||
import type { NoSuchElementException } from "effect/Cause"
|
import type { NoSuchElementException } from "effect/Cause"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import { Hooks } from "./hooks/index.js"
|
import { Hooks } from "./hooks/index.js"
|
||||||
@@ -19,7 +19,7 @@ extends Pipeable.Pipeable {
|
|||||||
readonly valueRef: SubscriptionRef.SubscriptionRef<Option.Option<A>>,
|
readonly valueRef: SubscriptionRef.SubscriptionRef<Option.Option<A>>,
|
||||||
readonly encodedValueRef: SubscriptionRef.SubscriptionRef<I>,
|
readonly encodedValueRef: SubscriptionRef.SubscriptionRef<I>,
|
||||||
readonly errorRef: SubscriptionRef.SubscriptionRef<Option.Option<ParseResult.ParseError>>,
|
readonly errorRef: SubscriptionRef.SubscriptionRef<Option.Option<ParseResult.ParseError>>,
|
||||||
readonly isValidatingRef: SubscriptionRef.SubscriptionRef<boolean>
|
readonly validationFiberRef: SubscriptionRef.SubscriptionRef<Option.Option<Fiber.Fiber<void, never>>>
|
||||||
readonly submitStateRef: SubscriptionRef.SubscriptionRef<AsyncData.AsyncData<SA, SE>>,
|
readonly submitStateRef: SubscriptionRef.SubscriptionRef<AsyncData.AsyncData<SA, SE>>,
|
||||||
|
|
||||||
readonly canSubmitSubscribable: Subscribable.Subscribable<boolean>
|
readonly canSubmitSubscribable: Subscribable.Subscribable<boolean>
|
||||||
@@ -36,7 +36,7 @@ extends Pipeable.Class() implements Form<A, I, R, SA, SE, SR> {
|
|||||||
readonly valueRef: SubscriptionRef.SubscriptionRef<Option.Option<A>>,
|
readonly valueRef: SubscriptionRef.SubscriptionRef<Option.Option<A>>,
|
||||||
readonly encodedValueRef: SubscriptionRef.SubscriptionRef<I>,
|
readonly encodedValueRef: SubscriptionRef.SubscriptionRef<I>,
|
||||||
readonly errorRef: SubscriptionRef.SubscriptionRef<Option.Option<ParseResult.ParseError>>,
|
readonly errorRef: SubscriptionRef.SubscriptionRef<Option.Option<ParseResult.ParseError>>,
|
||||||
readonly isValidatingRef: SubscriptionRef.SubscriptionRef<boolean>,
|
readonly validationFiberRef: SubscriptionRef.SubscriptionRef<Option.Option<Fiber.Fiber<void, never>>>,
|
||||||
readonly submitStateRef: SubscriptionRef.SubscriptionRef<AsyncData.AsyncData<SA, SE>>,
|
readonly submitStateRef: SubscriptionRef.SubscriptionRef<AsyncData.AsyncData<SA, SE>>,
|
||||||
|
|
||||||
readonly canSubmitSubscribable: Subscribable.Subscribable<boolean>,
|
readonly canSubmitSubscribable: Subscribable.Subscribable<boolean>,
|
||||||
@@ -62,7 +62,7 @@ export const make: {
|
|||||||
) {
|
) {
|
||||||
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 isValidatingRef = yield* SubscriptionRef.make(false)
|
const validationFiberRef = yield* SubscriptionRef.make(Option.none<Fiber.Fiber<void, never>>())
|
||||||
const submitStateRef = yield* SubscriptionRef.make(AsyncData.noData<SA, SE>())
|
const submitStateRef = yield* SubscriptionRef.make(AsyncData.noData<SA, SE>())
|
||||||
|
|
||||||
return new FormImpl(
|
return new FormImpl(
|
||||||
@@ -72,25 +72,25 @@ export const make: {
|
|||||||
valueRef,
|
valueRef,
|
||||||
yield* SubscriptionRef.make(options.initialEncodedValue),
|
yield* SubscriptionRef.make(options.initialEncodedValue),
|
||||||
errorRef,
|
errorRef,
|
||||||
isValidatingRef,
|
validationFiberRef,
|
||||||
submitStateRef,
|
submitStateRef,
|
||||||
|
|
||||||
pipe(
|
pipe(
|
||||||
<A>([value, error, isValidating, submitState]: readonly [
|
<A>([value, error, validationFiber, submitState]: readonly [
|
||||||
Option.Option<A>,
|
Option.Option<A>,
|
||||||
Option.Option<ParseResult.ParseError>,
|
Option.Option<ParseResult.ParseError>,
|
||||||
boolean,
|
Option.Option<Fiber.Fiber<void, never>>,
|
||||||
AsyncData.AsyncData<SA, SE>,
|
AsyncData.AsyncData<SA, SE>,
|
||||||
]) => Option.isSome(value) && Option.isNone(error) && !isValidating && !AsyncData.isLoading(submitState),
|
]) => Option.isSome(value) && Option.isNone(error) && Option.isNone(validationFiber) && !AsyncData.isLoading(submitState),
|
||||||
|
|
||||||
filter => SubscribableInternal.make({
|
filter => SubscribableInternal.make({
|
||||||
get: Effect.map(Effect.all([valueRef, errorRef, isValidatingRef, submitStateRef]), filter),
|
get: Effect.map(Effect.all([valueRef, errorRef, validationFiberRef, submitStateRef]), filter),
|
||||||
get changes() {
|
get changes() {
|
||||||
return Stream.map(
|
return Stream.map(
|
||||||
Stream.zipLatestAll(
|
Stream.zipLatestAll(
|
||||||
valueRef.changes,
|
valueRef.changes,
|
||||||
errorRef.changes,
|
errorRef.changes,
|
||||||
isValidatingRef.changes,
|
validationFiberRef.changes,
|
||||||
submitStateRef.changes,
|
submitStateRef.changes,
|
||||||
),
|
),
|
||||||
filter,
|
filter,
|
||||||
@@ -103,14 +103,38 @@ export const make: {
|
|||||||
|
|
||||||
export const run = <A, I, R, SA, SE, SR>(
|
export const run = <A, I, R, SA, SE, SR>(
|
||||||
self: Form<A, I, R, SA, SE, SR>
|
self: Form<A, I, R, SA, SE, SR>
|
||||||
): Effect.Effect<void, never, R> => Stream.runForEach(
|
): Effect.Effect<void, never, Scope.Scope | R> => Stream.runForEach(
|
||||||
self.encodedValueRef.changes,
|
self.encodedValueRef.changes,
|
||||||
encodedValue => SubscriptionRef.set(self.isValidatingRef, true).pipe(
|
encodedValue => self.validationFiberRef.pipe(
|
||||||
|
Effect.andThen(Option.match({
|
||||||
|
onSome: Fiber.interrupt,
|
||||||
|
onNone: () => Effect.void,
|
||||||
|
})),
|
||||||
|
Effect.andThen(
|
||||||
|
Effect.addFinalizer(() => SubscriptionRef.set(self.validationFiberRef, Option.none())).pipe(
|
||||||
Effect.andThen(Schema.decode(self.schema, { errors: "all" })(encodedValue)),
|
Effect.andThen(Schema.decode(self.schema, { errors: "all" })(encodedValue)),
|
||||||
Effect.andThen(v => SubscriptionRef.set(self.valueRef, Option.some(v))),
|
Effect.exit,
|
||||||
Effect.andThen(SubscriptionRef.set(self.errorRef, Option.none())),
|
Effect.andThen(flow(
|
||||||
Effect.catchTag("ParseError", e => SubscriptionRef.set(self.errorRef, Option.some(e))),
|
Exit.matchEffect({
|
||||||
Effect.andThen(SubscriptionRef.set(self.isValidatingRef, false)),
|
onSuccess: v => Effect.andThen(
|
||||||
|
SubscriptionRef.set(self.valueRef, Option.some(v)),
|
||||||
|
SubscriptionRef.set(self.errorRef, Option.none()),
|
||||||
|
),
|
||||||
|
onFailure: c => Option.match(
|
||||||
|
Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"),
|
||||||
|
{
|
||||||
|
onSome: e => SubscriptionRef.set(self.errorRef, Option.some(e)),
|
||||||
|
onNone: () => Effect.void,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
Effect.uninterruptible,
|
||||||
|
)),
|
||||||
|
Effect.scoped,
|
||||||
|
Effect.forkScoped,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Effect.andThen(fiber => SubscriptionRef.set(self.validationFiberRef, Option.some(fiber)))
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -177,7 +201,13 @@ export const field = <A, I, R, SA, SE, SR, const P extends PropertyPath.Paths<No
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
||||||
self.isValidatingRef,
|
pipe(
|
||||||
|
Option.isSome,
|
||||||
|
filter => SubscribableInternal.make({
|
||||||
|
get: Effect.map(self.validationFiberRef.get, filter),
|
||||||
|
get changes() { return Stream.map(self.validationFiberRef.changes, filter) },
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
|
||||||
pipe(
|
pipe(
|
||||||
AsyncData.isLoading,
|
AsyncData.isLoading,
|
||||||
|
|||||||
Reference in New Issue
Block a user