This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { Effect, Option, Pipeable, Schema, Subscribable, SubscriptionRef, type ParseResult } from "effect"
|
||||
import type * as PropertyPath from "./PropertyPath.js"
|
||||
import { Array, Effect, Option, ParseResult, Pipeable, Schema, Stream, Subscribable, SubscriptionRef } from "effect"
|
||||
import * as React from "react"
|
||||
import { SubscriptionSubRef } from "./index.js"
|
||||
import * as PropertyPath from "./PropertyPath.js"
|
||||
import * as InternalSubscribable from "./Subscribable.js"
|
||||
|
||||
|
||||
export const TypeId: unique symbol = Symbol.for("effect-fc/types/Form")
|
||||
export const TypeId: unique symbol = Symbol.for("effect-fc/Form")
|
||||
export type TypeId = typeof TypeId
|
||||
|
||||
export interface Form<in out A, in out I = A, out R = never>
|
||||
@@ -11,8 +14,8 @@ extends Pipeable.Pipeable {
|
||||
readonly valueRef: SubscriptionRef.SubscriptionRef<A>
|
||||
readonly errorSubscribable: Subscribable.Subscribable<Option.Option<ParseResult.ParseError>>
|
||||
|
||||
useRef<P extends PropertyPath.Paths<A>>(path: P): Effect.Effect<SubscriptionRef.SubscriptionRef<PropertyPath.ValueFromPath<A, P>>>
|
||||
useIssues(path: PropertyPath.Paths<A>): Effect.Effect<readonly ParseResult.ParseIssue[]>
|
||||
useRef<P extends PropertyPath.Paths<A>>(path: P): SubscriptionRef.SubscriptionRef<PropertyPath.ValueFromPath<A, P>>
|
||||
useIssuesSubscribable(path: PropertyPath.Paths<A>): Subscribable.Subscribable<readonly ParseResult.ArrayFormatterIssue[]>
|
||||
}
|
||||
|
||||
class FormImpl<in out A, in out I, out R>
|
||||
@@ -27,14 +30,26 @@ extends Pipeable.Class() implements Form<A, I, R> {
|
||||
super()
|
||||
}
|
||||
|
||||
useRef<P extends PropertyPath.Paths<A>>(
|
||||
path: P
|
||||
): Effect.Effect<SubscriptionRef.SubscriptionRef<PropertyPath.ValueFromPath<A, P>>, never, never> {
|
||||
throw new Error("Method not implemented.")
|
||||
useRef<P extends PropertyPath.Paths<A>>(path: P) {
|
||||
return React.useMemo(() => SubscriptionSubRef.makeFromPath(this.valueRef, path), [this.valueRef, ...path])
|
||||
}
|
||||
|
||||
useIssues(path: PropertyPath.Paths<A>): Effect.Effect<readonly ParseResult.ParseIssue[]> {
|
||||
throw new Error("Method not implemented.")
|
||||
useIssuesSubscribable(path: PropertyPath.Paths<A>) {
|
||||
return React.useMemo(() => {
|
||||
const filter = Option.match({
|
||||
onSome: (v: ParseResult.ParseError) => Effect.andThen(
|
||||
ParseResult.ArrayFormatter.formatError(v),
|
||||
Array.filter(issue => PropertyPath.equivalence(issue.path, path)),
|
||||
),
|
||||
onNone: () => Effect.succeed([]),
|
||||
})
|
||||
|
||||
const errorSubscribable = this.errorSubscribable
|
||||
return InternalSubscribable.make({
|
||||
get: Effect.andThen(errorSubscribable.get, filter),
|
||||
get changes() { return Stream.flatMap(errorSubscribable.changes, filter) },
|
||||
})
|
||||
}, [this.errorSubscribable, ...path])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Array, Function, Option, Predicate } from "effect"
|
||||
import { Array, Equivalence, Function, Option, Predicate } from "effect"
|
||||
|
||||
|
||||
export type PropertyPath = readonly PropertyKey[]
|
||||
|
||||
type Prev = readonly [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
export type Paths<T, D extends number = 5, Seen = never> = readonly [] | (
|
||||
@@ -36,8 +38,8 @@ export type ValueFromPath<T, P extends readonly any[]> = P extends [infer Head,
|
||||
: never
|
||||
: T
|
||||
|
||||
export type AnyPath = readonly PropertyKey[]
|
||||
|
||||
export const equivalence: Equivalence.Equivalence<PropertyPath> = Equivalence.array(Equivalence.strict())
|
||||
|
||||
export const unsafeGet: {
|
||||
<T, const P extends Paths<T>>(path: P): (self: T) => ValueFromPath<T, P>
|
||||
@@ -65,13 +67,13 @@ export const immutableSet: {
|
||||
<T, const P extends Paths<T>>(path: P, value: ValueFromPath<T, P>): (self: T) => ValueFromPath<T, P>
|
||||
<T, const P extends Paths<T>>(self: T, path: P, value: ValueFromPath<T, P>): Option.Option<T>
|
||||
} = Function.dual(3, <T, const P extends Paths<T>>(self: T, path: P, value: ValueFromPath<T, P>): Option.Option<T> => {
|
||||
const key = Array.head(path as AnyPath)
|
||||
const key = Array.head(path as PropertyPath)
|
||||
if (Option.isNone(key))
|
||||
return Option.some(value as T)
|
||||
if (!Predicate.hasProperty(self, key.value))
|
||||
return Option.none()
|
||||
|
||||
const child = immutableSet<any, any>(self[key.value], Option.getOrThrow(Array.tail(path as AnyPath)), value)
|
||||
const child = immutableSet<any, any>(self[key.value], Option.getOrThrow(Array.tail(path as PropertyPath)), value)
|
||||
if (Option.isNone(child))
|
||||
return child
|
||||
|
||||
|
||||
@@ -2,28 +2,6 @@ import { Array, Function, Option, Predicate, Schema } from "effect"
|
||||
import type { Simplify } from "effect/Types"
|
||||
|
||||
|
||||
type Prev = readonly [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
export type Paths<S, D extends number = 5, Seen = never> = readonly [] | (
|
||||
D extends never ? readonly [] :
|
||||
S extends Seen ? readonly [] :
|
||||
S extends Schema.Union<infer Members> ? UnionPaths<Members, D, Seen | S> :
|
||||
S extends Schema.TupleType<infer Elements, infer Rest> ? FormField.TupleFormField<S, Elements, Rest> :
|
||||
S extends Schema.Array$<infer Value> ? FormField.ArrayFormField<S, Value> :
|
||||
S extends Schema.Struct<infer Fields> ? FormField.StructFormField<S, Fields> :
|
||||
S extends Schema.Schema.Any ? FormField.GenericFormField<S> :
|
||||
S extends Schema.PropertySignature<
|
||||
infer TypeToken,
|
||||
infer Type,
|
||||
infer Key,
|
||||
infer EncodedToken,
|
||||
infer Encoded,
|
||||
infer HasDefault,
|
||||
infer R
|
||||
> ? FormField.PropertySignatureFormField<S, TypeToken, Type, Key, EncodedToken, Encoded, HasDefault, R> :
|
||||
never
|
||||
)
|
||||
|
||||
export type SchemaFromPath<S, P extends readonly any[]> = S extends Schema.Schema.Any
|
||||
? P extends [infer Head, ...infer Tail]
|
||||
? Head extends keyof S["Type"]
|
||||
|
||||
Reference in New Issue
Block a user