diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts
index 9aeefc7..2d00fb5 100644
--- a/packages/effect-fc/src/Form.ts
+++ b/packages/effect-fc/src/Form.ts
@@ -1,10 +1,10 @@
import * as AsyncData from "@typed/async-data"
-import { Array, Cause, Chunk, type Duration, Effect, Equal, Exit, Fiber, flow, identity, Option, ParseResult, Pipeable, Predicate, pipe, Ref, Schema, type Scope, Stream, type Subscribable, SubscriptionRef } from "effect"
+import { Array, Cause, Chunk, type Duration, Effect, Equal, Exit, Fiber, flow, identity, Option, ParseResult, Pipeable, Predicate, Ref, Schema, type Scope, Stream, SubscriptionRef } from "effect"
import type { NoSuchElementException } from "effect/Cause"
import * as React from "react"
import * as Hooks from "./Hooks/index.js"
import * as PropertyPath from "./PropertyPath.js"
-import * as SubscribableInternal from "./Subscribable.js"
+import * as Subscribable from "./Subscribable.js"
import * as SubscriptionSubRef from "./SubscriptionSubRef.js"
@@ -83,28 +83,14 @@ export const make: {
validationFiberRef,
submitStateRef,
- pipe(
- ([value, error, validationFiber, submitState]: readonly [
- Option.Option,
- Option.Option,
- Option.Option>,
- AsyncData.AsyncData,
- ]) => Option.isSome(value) && Option.isNone(error) && Option.isNone(validationFiber) && !AsyncData.isLoading(submitState),
-
- filter => SubscribableInternal.make({
- get: Effect.map(Effect.all([valueRef, errorRef, validationFiberRef, submitStateRef]), filter),
- get changes() {
- return Stream.map(
- Stream.zipLatestAll(
- valueRef.changes,
- errorRef.changes,
- validationFiberRef.changes,
- submitStateRef.changes,
- ),
- filter,
- )
- },
- }),
+ Subscribable.map(
+ Subscribable.zipLatestAll(valueRef, errorRef, validationFiberRef, submitStateRef),
+ ([value, error, validationFiber, submitState]) => (
+ Option.isSome(value) &&
+ Option.isNone(error) &&
+ Option.isNone(validationFiber) &&
+ !AsyncData.isLoading(submitState)
+ ),
),
)
})
@@ -186,42 +172,20 @@ export const field = ,
path: P,
): FormField, PropertyPath.ValueFromPath> => new FormFieldImpl(
- pipe(
- Option.match({
- onSome: (v: A) => Option.map(PropertyPath.get(v, path), Option.some),
- onNone: () => Option.some(Option.none()),
- }),
- filter => SubscribableInternal.make({
- get: Effect.flatMap(self.valueRef, filter),
- get changes() { return Stream.flatMap(self.valueRef.changes, filter) },
- }),
- ),
-
+ Subscribable.mapEffect(self.valueRef, Option.match({
+ onSome: v => Option.map(PropertyPath.get(v, path), Option.some),
+ onNone: () => Option.some(Option.none()),
+ })),
SubscriptionSubRef.makeFromPath(self.encodedValueRef, path),
-
- SubscribableInternal.flatMapSubscriptionRef(self.errorRef, Option.match({
+ Subscribable.mapEffect(self.errorRef, Option.match({
onSome: flow(
ParseResult.ArrayFormatter.formatError,
Effect.map(Array.filter(issue => PropertyPath.equivalence(issue.path, path))),
),
onNone: () => Effect.succeed([]),
})),
-
- pipe(
- Option.isSome,
- filter => SubscribableInternal.make({
- get: Effect.map(self.validationFiberRef.get, filter),
- get changes() { return Stream.map(self.validationFiberRef.changes, filter) },
- }),
- ),
-
- pipe(
- AsyncData.isLoading,
- filter => SubscribableInternal.make({
- get: Effect.map(self.submitStateRef, filter),
- get changes() { return Stream.map(self.submitStateRef.changes, filter) },
- }),
- ),
+ Subscribable.map(self.validationFiberRef, Option.isSome),
+ Subscribable.map(self.submitStateRef, AsyncData.isLoading)
)
diff --git a/packages/effect-fc/src/Subscribable.ts b/packages/effect-fc/src/Subscribable.ts
index 416c6ea..9ebba36 100644
--- a/packages/effect-fc/src/Subscribable.ts
+++ b/packages/effect-fc/src/Subscribable.ts
@@ -1,32 +1,17 @@
-import { Effect, Effectable, Readable, Stream, Subscribable, type SubscriptionRef } from "effect"
+import { Effect, Stream, Subscribable } from "effect"
-class SubscribableImpl
-extends Effectable.Class implements Subscribable.Subscribable {
- readonly [Readable.TypeId]: Readable.TypeId = Readable.TypeId
- readonly [Subscribable.TypeId]: Subscribable.TypeId = Subscribable.TypeId
+export const zipLatestAll = >>(
+ ...subscribables: T
+): Subscribable.Subscribable<
+ [T[number]] extends [never]
+ ? never
+ : { [K in keyof T]: T[K] extends Subscribable.Subscribable ? A : never },
+ [T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable ? _E : never,
+ [T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable ? _R : never
+> => Subscribable.make({
+ get: Effect.all(subscribables.map(v => v.get)),
+ changes: Stream.zipLatestAll(...subscribables.map(v => v.changes)),
+}) as any
- constructor(
- readonly get: Effect.Effect,
- readonly changes: Stream.Stream,
- ) {
- super()
- }
-
- commit() {
- return this.get
- }
-}
-
-export const make = (values: {
- readonly get: Effect.Effect
- readonly changes: Stream.Stream
-}): Subscribable.Subscribable => new SubscribableImpl(values.get, values.changes)
-
-export const flatMapSubscriptionRef = (
- ref: SubscriptionRef.SubscriptionRef,
- flatMap: (value: NoInfer) => Effect.Effect,
-): Subscribable.Subscribable => make({
- get: Effect.flatMap(ref, flatMap),
- get changes() { return Stream.flatMap(ref.changes, flatMap) },
-})
+export * from "effect/Subscribable"