0.2.2 #31
@@ -35,6 +35,8 @@ extends Pipeable.Pipeable {
|
||||
field<const P extends PropertyPath.Paths<I>>(
|
||||
path: P
|
||||
): Effect.Effect<FormField<PropertyPath.ValueFromPath<A, P>, PropertyPath.ValueFromPath<I, P>>>
|
||||
|
||||
readonly run: Effect.Effect<void>
|
||||
readonly submit: Effect.Effect<Option.Option<Result.Final<MA, ME, MP>>, Cause.NoSuchElementException>
|
||||
}
|
||||
|
||||
@@ -89,7 +91,49 @@ extends Pipeable.Class() implements Form<A, I, R, MA, ME, MR, MP> {
|
||||
)
|
||||
}
|
||||
|
||||
readonly canSubmit: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly canSubmit: Subscribable.Subscribable<boolean>
|
||||
|
||||
get run(): Effect.Effect<void> {
|
||||
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<Option.Option<Result.Final<MA, ME, MP>>, Cause.NoSuchElementException> {
|
||||
return this.value.pipe(
|
||||
@@ -97,6 +141,7 @@ extends Pipeable.Class() implements Form<A, I, R, MA, ME, MR, MP> {
|
||||
Effect.andThen(value => this.submitValue(value)),
|
||||
)
|
||||
}
|
||||
|
||||
submitValue(value: A): Effect.Effect<Option.Option<Result.Final<MA, ME, MP>>> {
|
||||
return Effect.whenEffect(
|
||||
Effect.tap(
|
||||
@@ -158,51 +203,6 @@ export const make = Effect.fnUntraced(function* <A, I = A, R = never, MA = void,
|
||||
)
|
||||
})
|
||||
|
||||
export const run = <A, I, R, MA, ME, MR, MP>(
|
||||
self: Form<A, I, R, MA, ME, MR, MP>
|
||||
): Effect.Effect<void> => {
|
||||
const _self = self as FormImpl<A, I, R, MA, ME, MR, MP>
|
||||
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<in out A, in out I = A, in out R = never, in out MA = void, in out ME = never, in out MR = never, in out MP = never>
|
||||
extends make.Options<A, I, R, MA, ME, MR, MP> {}
|
||||
@@ -216,7 +216,7 @@ export const service = <A, I = A, R = never, MA = void, ME = never, MR = never,
|
||||
Scope.Scope | R | Result.forkEffect.OutputContext<MA, ME, MR, MP>
|
||||
> => Effect.tap(
|
||||
make(options),
|
||||
form => Effect.forkScoped(run(form)),
|
||||
form => Effect.forkScoped(form.run),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ extends Pipeable.Class() implements Mutation<K, A, E, R, P> {
|
||||
readonly [MutationTypeId]: MutationTypeId = MutationTypeId
|
||||
|
||||
constructor(
|
||||
readonly context: Context.Context<Scope.Scope | NoInfer<R>>,
|
||||
readonly context: Context.Context<Scope.Scope | R>,
|
||||
readonly f: (key: K) => Effect.Effect<A, E, R>,
|
||||
readonly initialProgress: P,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user