This commit is contained in:
67
packages/effect-fc/src/Lens.ts
Normal file
67
packages/effect-fc/src/Lens.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Effect, Predicate, Stream, Subscribable, SubscriptionRef, type Types } from "effect"
|
||||
import * as Writable from "./Writable.js"
|
||||
|
||||
|
||||
export const LensTypeId: unique symbol = Symbol.for("@effect-fc/Lens/Lens")
|
||||
export type LensTypeId = typeof LensTypeId
|
||||
|
||||
export interface Lens<in out A, ER = unknown, RR = unknown, EW = unknown, RW = unknown>
|
||||
extends Lens.Variance<A, ER, RR, EW, RW>, Subscribable.Subscribable<A, ER, RR>, Writable.Writable<A, EW, RW> {}
|
||||
|
||||
export declare namespace Lens {
|
||||
export interface Variance<in out A, in out EGet, in out RGet, in out ESet, in out RSet> {
|
||||
readonly [LensTypeId]: {
|
||||
readonly _A: Types.Invariant<A>
|
||||
readonly _EG: Types.Invariant<EGet>
|
||||
readonly _RG: Types.Invariant<RGet>
|
||||
readonly _EW: Types.Invariant<ESet>
|
||||
readonly _RW: Types.Invariant<RSet>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const LensPrototype: Writable.WritablePrototype = Object.freeze({
|
||||
[LensTypeId]: LensTypeId,
|
||||
...Writable.WritablePrototype,
|
||||
} as const)
|
||||
|
||||
|
||||
export const isLens = (u: unknown): u is Lens<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, LensTypeId)
|
||||
|
||||
|
||||
/**
|
||||
* Construct a `Lens` from explicit get/changes/set implementations.
|
||||
*/
|
||||
export const makeFromGetSet = <A, ER, RR, EW, RW>(options: {
|
||||
readonly get: Effect.Effect<A, ER, RR>
|
||||
readonly changes: Stream.Stream<A, ER, RR>
|
||||
readonly set: (value: A) => Effect.Effect<void, EW, RW>
|
||||
}): Lens<A, ER, RR, EW, RW> => Object.setPrototypeOf({
|
||||
[Subscribable.TypeId]: Subscribable.TypeId,
|
||||
get: options.get,
|
||||
changes: options.changes,
|
||||
modify: <B>(f: (a: A) => readonly [B, A]) => Effect.flatMap(options.get, a => {
|
||||
const [b, next] = f(a)
|
||||
return Effect.map(options.set(next), () => b)
|
||||
}),
|
||||
}, LensPrototype) as any
|
||||
|
||||
|
||||
/**
|
||||
* Create a `Lens` that directly proxies an `effect` SubscriptionRef.
|
||||
*/
|
||||
export const makeFromSubscriptionRef = <A>(ref: SubscriptionRef.SubscriptionRef<A>): Lens<A, never, never, never, never> =>
|
||||
makeFromGetSet({
|
||||
get: ref,
|
||||
changes: ref.changes,
|
||||
set: (v: A) => SubscriptionRef.set(ref, v),
|
||||
})
|
||||
|
||||
|
||||
export const unwrap = <A, ER, RR, EW, RW, E1, R1>(
|
||||
effect: Effect.Effect<Lens<A, ER, RR, EW, RW>, E1, R1>,
|
||||
): Lens<A, ER | E1, RR | R1, EW | E1, RW | R1> => makeFromGetSet({
|
||||
get: Effect.flatMap(effect, p => p.get),
|
||||
changes: Stream.unwrap(Effect.map(effect, p => p.changes)),
|
||||
set: (v: A) => Effect.flatMap(effect, p => p.modify(() => [undefined as void as any, v]) as any),
|
||||
}) as any
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Effect, Predicate, Stream, Subscribable, SubscriptionRef, type Types } from "effect"
|
||||
import * as Writable from "./Writable.js"
|
||||
|
||||
|
||||
export const ProxyRefTypeId: unique symbol = Symbol.for("@effect-fc/ProxyRef/ProxyRef")
|
||||
export type ProxyRefTypeId = typeof ProxyRefTypeId
|
||||
|
||||
export interface ProxyRef<in out A, EGet = unknown, RGet = unknown, ESet = unknown, RSet = unknown>
|
||||
extends ProxyRef.Variance<A, EGet, RGet, ESet, RSet>, Subscribable.Subscribable<A, EGet, RGet>, Writable.Writable<A, ESet, RSet> {}
|
||||
|
||||
export declare namespace ProxyRef {
|
||||
export interface Variance<in out A, in out EGet, in out RGet, in out ESet, in out RSet> {
|
||||
readonly [ProxyRefTypeId]: {
|
||||
readonly _A: Types.Invariant<A>
|
||||
readonly _EG: Types.Invariant<EGet>
|
||||
readonly _RG: Types.Invariant<RGet>
|
||||
readonly _EW: Types.Invariant<ESet>
|
||||
readonly _RW: Types.Invariant<RSet>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const ProxyRefPrototype: Writable.WritablePrototype = Object.freeze({
|
||||
[ProxyRefTypeId]: ProxyRefTypeId,
|
||||
...Writable.WritablePrototype,
|
||||
} as const)
|
||||
|
||||
|
||||
export const isProxyRef = (u: unknown): u is ProxyRef<unknown, unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, ProxyRefTypeId)
|
||||
|
||||
|
||||
/**
|
||||
* Construct a `ProxyRef` from explicit get/changes/set implementations.
|
||||
*/
|
||||
export const makeFromGetSet = <A, EGet, RGet, ESet, RSet>(options: {
|
||||
readonly get: Effect.Effect<A, EGet, RGet>
|
||||
readonly changes: Stream.Stream<A, EGet, RGet>
|
||||
readonly set: (value: A) => Effect.Effect<void, ESet, RSet>
|
||||
}): ProxyRef<A, EGet, RGet, ESet, RSet> => Object.setPrototypeOf({
|
||||
[Subscribable.TypeId]: Subscribable.TypeId,
|
||||
get: options.get,
|
||||
changes: options.changes,
|
||||
modify: <B>(f: (a: A) => readonly [B, A]) => Effect.flatMap(options.get, a => {
|
||||
const [b, next] = f(a)
|
||||
return Effect.map(options.set(next), () => b)
|
||||
}),
|
||||
}, ProxyRefPrototype) as any
|
||||
|
||||
|
||||
/**
|
||||
* Create a `ProxyRef` that directly proxies an `effect` SubscriptionRef.
|
||||
*/
|
||||
export const makeFromSubscriptionRef = <A>(ref: SubscriptionRef.SubscriptionRef<A>): ProxyRef<A, never, never, never, never> =>
|
||||
makeFromGetSet({
|
||||
get: ref,
|
||||
changes: ref.changes,
|
||||
set: (v: A) => SubscriptionRef.set(ref, v),
|
||||
})
|
||||
|
||||
|
||||
export const unwrap = <A, EGet, RGet, ESet, RSet, E1, R1>(
|
||||
effect: Effect.Effect<ProxyRef<A, EGet, RGet, ESet, RSet>, E1, R1>,
|
||||
): ProxyRef<A, EGet | E1, RGet | R1, ESet | E1, RSet | R1> => makeFromGetSet({
|
||||
get: Effect.flatMap(effect, p => p.get),
|
||||
changes: Stream.unwrap(Effect.map(effect, p => p.changes)),
|
||||
set: (v: A) => Effect.flatMap(effect, p => p.modify(() => [undefined as void as any, v]) as any),
|
||||
}) as any
|
||||
@@ -2,10 +2,10 @@ export * as Async from "./Async.js"
|
||||
export * as Component from "./Component.js"
|
||||
export * as ErrorObserver from "./ErrorObserver.js"
|
||||
export * as Form from "./Form.js"
|
||||
export * as Lens from "./Lens.js"
|
||||
export * as Memoized from "./Memoized.js"
|
||||
export * as Mutation from "./Mutation.js"
|
||||
export * as PropertyPath from "./PropertyPath.js"
|
||||
export * as ProxyRef from "./ProxyRef.js"
|
||||
export * as PubSub from "./PubSub.js"
|
||||
export * as Query from "./Query.js"
|
||||
export * as QueryClient from "./QueryClient.js"
|
||||
|
||||
Reference in New Issue
Block a user