0.2.1 + 2.0.0-beta.0 #6
@@ -126,12 +126,12 @@ yield* Lens.updateSomeEffect(lens, (value) =>
|
||||
Effect v4 removed its `Readable` and `Subscribable` modules. This package provides a small compatible abstraction with `get` and `changes` properties:
|
||||
|
||||
```ts
|
||||
import { Subscribable } from "effect-lens-next"
|
||||
import { Lens, Subscribable } from "effect-lens-next"
|
||||
|
||||
const users = Subscribable.fromSubscriptionRef(usersRef)
|
||||
const users = Lens.fromSubscriptionRef(usersRef)
|
||||
const count = Subscribable.focusArrayLength(users)
|
||||
|
||||
const current = yield* count.get
|
||||
```
|
||||
|
||||
The module includes `make`, `map`, `mapEffect`, `unwrap`, `fromSubscriptionRef`, and the same readonly focus helpers used by Lens.
|
||||
The module includes `make`, `map`, `mapEffect`, `unwrap`, and the same readonly focus helpers used by Lens. A `SubscriptionRef` can first be converted with `Lens.fromSubscriptionRef`, since every Lens is already a Subscribable.
|
||||
|
||||
@@ -66,7 +66,7 @@ export declare namespace LensImpl {
|
||||
|
||||
export abstract class LensImpl<in out A, in out ER = never, in out EW = never, in out RR = never, in out RW = never>
|
||||
extends Pipeable.Class implements Lens<A, ER, EW, RR, RW> {
|
||||
readonly [Subscribable.TypeId]: Subscribable.TypeId = Subscribable.TypeId
|
||||
readonly [Subscribable.SubscribableTypeId]: Subscribable.SubscribableTypeId = Subscribable.SubscribableTypeId
|
||||
readonly [LensTypeId]: LensTypeId = LensTypeId
|
||||
readonly [LensImplTypeId]: LensImplTypeId = LensImplTypeId
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Chunk, Effect, SubscriptionRef } from "effect"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as Subscribable from "./Subscribable.js"
|
||||
|
||||
|
||||
@@ -9,7 +10,7 @@ describe("Subscribable", () => {
|
||||
Effect.flatMap(
|
||||
SubscriptionRef.make([1, 2, 3]),
|
||||
parent => {
|
||||
const sizeSub = Subscribable.focusArrayLength(Subscribable.fromSubscriptionRef(parent))
|
||||
const sizeSub = Subscribable.focusArrayLength(Lens.fromSubscriptionRef(parent))
|
||||
return Effect.flatMap(
|
||||
sizeSub.get,
|
||||
initial => Effect.flatMap(
|
||||
@@ -29,7 +30,7 @@ describe("Subscribable", () => {
|
||||
Effect.flatMap(
|
||||
SubscriptionRef.make(Chunk.make(1, 2) as Chunk.Chunk<number>),
|
||||
parent => {
|
||||
const sizeSub = Subscribable.focusChunkSize(Subscribable.fromSubscriptionRef(parent))
|
||||
const sizeSub = Subscribable.focusChunkSize(Lens.fromSubscriptionRef(parent))
|
||||
return Effect.flatMap(
|
||||
sizeSub.get,
|
||||
initial => Effect.flatMap(
|
||||
@@ -49,7 +50,7 @@ describe("Subscribable", () => {
|
||||
Effect.flatMap(
|
||||
SubscriptionRef.make([1, 2, 3]),
|
||||
parent => {
|
||||
const sizeSub = Subscribable.focusIterableSize(Subscribable.fromSubscriptionRef(parent))
|
||||
const sizeSub = Subscribable.focusIterableSize(Lens.fromSubscriptionRef(parent))
|
||||
return Effect.flatMap(
|
||||
sizeSub.get,
|
||||
initial => Effect.flatMap(
|
||||
|
||||
@@ -9,43 +9,68 @@ import {
|
||||
Pipeable,
|
||||
Predicate,
|
||||
Stream,
|
||||
SubscriptionRef,
|
||||
} from "effect"
|
||||
|
||||
|
||||
export const TypeId: unique symbol = Symbol.for("@effect-fc/Lens/v4/Subscribable")
|
||||
export type TypeId = typeof TypeId
|
||||
export const SubscribableTypeId: unique symbol = Symbol.for("@effect-fc/Lens/v4/Subscribable")
|
||||
export type SubscribableTypeId = typeof SubscribableTypeId
|
||||
|
||||
export interface Subscribable<in out A, in out E = never, in out R = never> extends Pipeable.Pipeable {
|
||||
readonly [TypeId]: TypeId
|
||||
readonly [SubscribableTypeId]: SubscribableTypeId
|
||||
readonly get: Effect.Effect<A, E, R>
|
||||
readonly changes: Stream.Stream<A, E, R>
|
||||
}
|
||||
|
||||
class SubscribableImpl<in out A, in out E, in out R>
|
||||
extends Pipeable.Class implements Subscribable<A, E, R> {
|
||||
readonly [TypeId]: TypeId = TypeId
|
||||
export const isSubscribable = (u: unknown): u is Subscribable<unknown, unknown, unknown> => Predicate.hasProperty(u, SubscribableTypeId)
|
||||
|
||||
constructor(
|
||||
readonly get: Effect.Effect<A, E, R>,
|
||||
readonly changes: Stream.Stream<A, E, R>,
|
||||
) {
|
||||
super()
|
||||
|
||||
export const SubscribableImplTypeId: unique symbol = Symbol.for("@effect-fc/Lens/v4/SubscribableImpl")
|
||||
export type SubscribableImplTypeId = typeof SubscribableImplTypeId
|
||||
|
||||
export declare namespace SubscribableImpl {
|
||||
export interface Source<in out A, in out E = never, in out R = never> {
|
||||
readonly get: Effect.Effect<A, E, R>
|
||||
readonly changes: Stream.Stream<A, E, R>
|
||||
}
|
||||
}
|
||||
|
||||
export const isSubscribable = (u: unknown): u is Subscribable<unknown, unknown, unknown> => Predicate.hasProperty(u, TypeId)
|
||||
export class SubscribableImpl<in out A, in out E = never, in out R = never>
|
||||
extends Pipeable.Class implements Subscribable<A, E, R> {
|
||||
readonly [SubscribableTypeId]: SubscribableTypeId = SubscribableTypeId
|
||||
readonly [SubscribableImplTypeId]: SubscribableImplTypeId = SubscribableImplTypeId
|
||||
|
||||
export const make = <A, E, R>(options: {
|
||||
readonly get: Effect.Effect<A, E, R>
|
||||
readonly changes: Stream.Stream<A, E, R>
|
||||
}): Subscribable<A, E, R> => new SubscribableImpl(options.get, options.changes)
|
||||
constructor(
|
||||
readonly source: SubscribableImpl.Source<A, E, R>,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
export const fromSubscriptionRef = <A>(self: SubscriptionRef.SubscriptionRef<A>): Subscribable<A> => make({
|
||||
get: SubscriptionRef.get(self),
|
||||
changes: SubscriptionRef.changes(self),
|
||||
get get() { return this.source.get }
|
||||
get changes() { return this.source.changes }
|
||||
}
|
||||
|
||||
export const isSubscribableImpl = (u: unknown): u is SubscribableImpl<unknown, unknown, unknown> => Predicate.hasProperty(u, SubscribableImplTypeId)
|
||||
|
||||
export const asSubscribableImpl = <A, E, R>(
|
||||
subscribable: Subscribable<A, E, R>
|
||||
): SubscribableImpl<A, E, R> => {
|
||||
if (!isSubscribableImpl(subscribable))
|
||||
throw new Error("Not a 'SubscribableImpl'")
|
||||
return subscribable as SubscribableImpl<A, E, R>
|
||||
}
|
||||
|
||||
export const make = <A, E, R>(
|
||||
source: SubscribableImpl.Source<A, E, R>
|
||||
): Subscribable<A, E, R> => new SubscribableImpl(source)
|
||||
|
||||
export const unwrap = <A, E, R, E1, R1>(
|
||||
effect: Effect.Effect<Subscribable<A, E, R>, E1, R1>,
|
||||
): Subscribable<A, E | E1, R | R1> => make({
|
||||
get: Effect.flatMap(effect, self => self.get),
|
||||
changes: Stream.unwrap(Effect.map(effect, self => self.changes)),
|
||||
})
|
||||
|
||||
|
||||
export const map: {
|
||||
<A, B>(f: (a: NoInfer<A>) => B): <E, R>(self: Subscribable<A, E, R>) => Subscribable<B, E, R>
|
||||
<A, E, R, B>(self: Subscribable<A, E, R>, f: (a: NoInfer<A>) => B): Subscribable<B, E, R>
|
||||
@@ -65,13 +90,6 @@ export const mapEffect: {
|
||||
changes: Stream.mapEffect(self.changes, f),
|
||||
}))
|
||||
|
||||
export const unwrap = <A, E, R, E1, R1>(
|
||||
effect: Effect.Effect<Subscribable<A, E, R>, E1, R1>,
|
||||
): Subscribable<A, E | E1, R | R1> => make({
|
||||
get: Effect.flatMap(effect, self => self.get),
|
||||
changes: Stream.unwrap(Effect.map(effect, self => self.changes)),
|
||||
})
|
||||
|
||||
/** Maps over an `Option` value in the `Subscribable`. */
|
||||
export const mapOption: {
|
||||
<A, B>(f: (a: A) => B): <E, R>(self: Subscribable<Option.Option<A>, E, R>) => Subscribable<Option.Option<B>, E, R>
|
||||
|
||||
Reference in New Issue
Block a user