0.2.6 #49

Merged
Thilawyn merged 48 commits from next into master 2026-05-04 02:10:53 +02:00
Showing only changes of commit 1ca8637bee - Show all commits

View File

@@ -1,4 +1,4 @@
import { Array, Cause, Chunk, type Context, Effect, Exit, Fiber, Option, ParseResult, Pipeable, Predicate, Schema, type Scope, Stream, SubscriptionRef } from "effect"
import { Array, Cause, Chunk, type Context, Effect, Exit, Fiber, Option, ParseResult, Pipeable, Predicate, Schema, type Scope, SubscriptionRef } from "effect"
import * as Form from "./Form.js"
import * as Lens from "./Lens.js"
import * as Subscribable from "./Subscribable.js"
@@ -39,6 +39,7 @@ export class SynchronizedFormImpl<
readonly [SynchronizedFormTypeId]: SynchronizedFormTypeId = SynchronizedFormTypeId
readonly path = [] as const
readonly encodedValue: Lens.Lens<I, never, never, never, never>
constructor(
readonly schema: Schema.Schema<A, I, R>,
@@ -46,7 +47,7 @@ export class SynchronizedFormImpl<
readonly target: Lens.Lens<A, TER, TEW, TRR, TRW>,
readonly value: Lens.Lens<Option.Option<A>, never, never, never, never>,
readonly encodedValue: Lens.Lens<I, never, never, never, never>,
readonly internalEncodedValue: Lens.Lens<I, never, never, never, never>,
readonly issues: Lens.Lens<readonly ParseResult.ArrayFormatterIssue[], never, never, never, never>,
readonly validationFiber: Lens.Lens<Option.Option<Fiber.Fiber<A, ParseResult.ParseError>>, never, never, never, never>,
readonly isValidating: Subscribable.Subscribable<boolean, never, never>,
@@ -57,15 +58,11 @@ export class SynchronizedFormImpl<
readonly runSemaphore: Effect.Semaphore,
) {
super()
this.encodedValue = makeEncodedValueLens(this)
}
get run(): Effect.Effect<void, TER> {
return this.runSemaphore.withPermits(1)(Effect.provide(
Effect.all([
Stream.runForEach(
this.encodedValue.changes,
encodedValue => Lens.get(this.validationFiber).pipe(
synchronizeEncodedValue(encodedValue: I): Effect.Effect<void, never, never> {
return Lens.get(this.validationFiber).pipe(
Effect.andThen(Option.match({
onSome: Fiber.interrupt,
onNone: () => Effect.void,
@@ -79,13 +76,16 @@ export class SynchronizedFormImpl<
Lens.set(this.value, Option.some(v)),
Lens.set(this.issues, Array.empty()),
),
onFailure: c => Option.match(Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"), {
onFailure: c => Option.match(
Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"),
{
onSome: e => Effect.flatMap(
ParseResult.ArrayFormatter.formatError(e),
v => Lens.set(this.issues, v),
),
onNone: () => Effect.void,
}),
},
),
}),
Lens.set(this.validationFiber, Option.none()),
),
@@ -100,31 +100,64 @@ export class SynchronizedFormImpl<
),
() => Lens.set(this.isCommitting, false),
)),
Effect.ignore,
),
),
Effect.ignore,
Effect.provide(this.context),
)
}
get run(): Effect.Effect<void, TER> {
return Effect.void
// return this.runSemaphore.withPermits(1)(Effect.provide(
// Effect.andThen(
// Effect.flatMap(
// Lens.get(this.internalEncodedValue),
// encodedValue => this.synchronizeEncodedValue(encodedValue),
// ),
// Stream.runForEach(
// Stream.drop(this.target.changes, 1),
// targetValue => Schema.encode(this.schema, { errors: "all" })(targetValue).pipe(
// Effect.flatMap(encodedValue => Effect.whenEffect(
// Lens.set(this.encodedValue, encodedValue),
// Effect.flatMap(encodedValue => Effect.andThen(
// Effect.whenEffect(
// Lens.set(this.internalEncodedValue, encodedValue),
// Effect.map(
// Lens.get(this.encodedValue),
// Lens.get(this.internalEncodedValue),
// currentEncodedValue => !Equal.equals(encodedValue, currentEncodedValue),
// ),
// ),
// Effect.andThen(
// Lens.set(this.value, Option.some(targetValue)),
// Lens.set(this.issues, Array.empty()),
// ),
// )),
// Effect.ignore,
// ),
// ),
], { concurrency: "unbounded" }),
// ),
this.context,
))
// this.context,
// ))
}
}
const makeEncodedValueLens = <A, I, R, TER, TEW, TRR, TRW>(
self: SynchronizedFormImpl<A, I, R, TER, TEW, TRR, TRW>
): Lens.Lens<I, never, never, never, never> => Lens.make({
get get() { return Lens.get(self.internalEncodedValue) },
get changes() { return self.internalEncodedValue.changes },
modify: f => Lens.get(self.internalEncodedValue).pipe(
Effect.flatMap(f),
Effect.flatMap(([b, nextEncodedValue]) => Effect.as(
Effect.andThen(
Lens.set(self.internalEncodedValue, nextEncodedValue),
self.synchronizeEncodedValue(nextEncodedValue),
),
b,
)),
),
})
export const isSynchronizedForm = (u: unknown): u is SynchronizedForm<unknown, unknown, unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, SynchronizedFormTypeId)