/**
* @since 2.0.0
*/
import * as Effect from "./Effect.js"
import { dual } from "./Function.js"
import { pipeArguments } from "./Pipeable.js"
import { hasProperty } from "./Predicate.js"
import * as Readable from "./Readable.js"
import * as Stream from "./Stream.js"
import type { NoInfer } from "./Types.js"
/**
* @since 2.0.0
* @category type ids
*/
export const TypeId: unique symbol = Symbol.for("effect/Subscribable")
/**
* @since 2.0.0
* @category type ids
*/
export type TypeId = typeof TypeId
/**
* @since 2.0.0
* @category models
*/
export interface Subscribable extends Readable.Readable {
readonly [TypeId]: TypeId
readonly changes: Stream.Stream
}
/**
* @since 2.0.0
* @category refinements
*/
export const isSubscribable = (u: unknown): u is Subscribable => hasProperty(u, TypeId)
const Proto: Omit, "get" | "changes"> = {
[Readable.TypeId]: Readable.TypeId,
[TypeId]: TypeId,
pipe() {
return pipeArguments(this, arguments)
}
}
/**
* @since 2.0.0
* @category constructors
*/
export const make = (options: {
readonly get: Effect.Effect
readonly changes: Stream.Stream
}): Subscribable => Object.assign(Object.create(Proto), options)
/**
* @since 2.0.0
* @category combinators
*/
export const map: {
/**
* @since 2.0.0
* @category combinators
*/
(f: (a: NoInfer) => B): (fa: Subscribable) => Subscribable
/**
* @since 2.0.0
* @category combinators
*/
(self: Subscribable, f: (a: NoInfer) => B): Subscribable
} = dual(2, (self: Subscribable, f: (a: NoInfer) => B): Subscribable =>
make({
get: Effect.map(self.get, f),
changes: Stream.map(self.changes, f)
}))
/**
* @since 2.0.0
* @category combinators
*/
export const mapEffect: {
/**
* @since 2.0.0
* @category combinators
*/
(f: (a: NoInfer) => Effect.Effect): (fa: Subscribable) => Subscribable
/**
* @since 2.0.0
* @category combinators
*/
(
self: Subscribable,
f: (a: NoInfer) => Effect.Effect
): Subscribable
} = dual(2, (
self: Subscribable,
f: (a: NoInfer) => Effect.Effect
): Subscribable =>
make({
get: Effect.flatMap(self.get, f),
changes: Stream.mapEffect(self.changes, f)
}))
/**
* @since 2.0.0
* @category constructors
*/
export const unwrap = (
effect: Effect.Effect, E1, R1>
): Subscribable =>
make({
get: Effect.flatMap(effect, (s) => s.get),
changes: Stream.unwrap(Effect.map(effect, (s) => s.changes))
})