| /** | |
| * Provides low-level building blocks for streaming data through Effect. | |
| * | |
| * A `Channel` can read input elements, write output elements, fail with a typed | |
| * error, and finish with a typed result while managing resources safely. | |
| * Streams and sinks are built on channels, so most application code uses those | |
| * higher-level modules instead. This module is useful when implementing stream | |
| * operators or specialized streaming workflows. | |
| * | |
| * @since 2.0.0 | |
| */ | |
| // @effect-diagnostics returnEffectInGen:off | |
| import * as Arr from "./Array.ts" | |
| import * as Cause from "./Cause.ts" | |
| import * as Chunk from "./Chunk.ts" | |
| import * as Context from "./Context.ts" | |
| import * as Effect from "./Effect.ts" | |
| import * as Exit from "./Exit.ts" | |
| import * as Fiber from "./Fiber.ts" | |
| import type * as Filter from "./Filter.ts" | |
| import type { LazyArg } from "./Function.ts" | |
| import { constant, constTrue, constVoid, dual, identity as identity_ } from "./Function.ts" | |
| import { ClockRef, endSpan } from "./internal/effect.ts" | |
| import { addSpanStackTrace } from "./internal/tracer.ts" | |
| import * as Iterable from "./Iterable.ts" | |
| import * as Latch from "./Latch.ts" | |
| import * as Layer from "./Layer.ts" | |
| import type { Severity } from "./LogLevel.ts" | |
| import * as Option from "./Option.ts" | |
| import type { Pipeable } from "./Pipeable.ts" | |
| import { pipeArguments } from "./Pipeable.ts" | |
| import type * as Predicate from "./Predicate.ts" | |
| import { hasProperty, isTagged } from "./Predicate.ts" | |
| import * as PubSub from "./PubSub.ts" | |
| import * as Pull from "./Pull.ts" | |
| import * as Queue from "./Queue.ts" | |
| import { TracerTimingEnabled } from "./References.ts" | |
| import * as Result from "./Result.ts" | |
| import * as Schedule from "./Schedule.ts" | |
| import * as Scope from "./Scope.ts" | |
| import * as Semaphore from "./Semaphore.ts" | |
| import * as String from "./String.ts" | |
| import * as Take from "./Take.ts" | |
| import { ParentSpan, type SpanOptions } from "./Tracer.ts" | |
| import type * as Types from "./Types.ts" | |
| import type * as Unify from "./Unify.ts" | |
| /** | |
| * String literal type used as the unique brand for `Channel` values. | |
| * | |
| * @category type IDs | |
| * @since 4.0.0 | |
| */ | |
| export type TypeId = "~effect/Channel" | |
| /** | |
| * Runtime identifier stored on `Channel` values and used by `isChannel` to | |
| * recognize them. | |
| * | |
| * @category type IDs | |
| * @since 4.0.0 | |
| */ | |
| export const TypeId: TypeId = "~effect/Channel" | |
| /** | |
| * Checks whether a value is a `Channel`. | |
| * | |
| * **Example** (Checking for channels) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.succeed(42) | |
| * console.log(Channel.isChannel(channel)) // true | |
| * console.log(Channel.isChannel("not a channel")) // false | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 3.5.4 | |
| */ | |
| export const isChannel = ( | |
| u: unknown | |
| ): u is Channel<unknown, unknown, unknown, unknown, unknown, unknown, unknown> => hasProperty(u, TypeId) | |
| /** | |
| * A `Channel` is a nexus of I/O operations, which supports both reading and | |
| * writing. A channel may read values of type `InElem` and write values of type | |
| * `OutElem`. When the channel finishes, it yields a value of type `OutDone`. A | |
| * channel may fail with a value of type `OutErr`. | |
| * | |
| * **Details** | |
| * | |
| * Channels are the foundation of Streams: both streams and sinks are built on | |
| * channels. Most users shouldn't have to use channels directly, as streams and | |
| * sinks are much more convenient and cover all common use cases. However, when | |
| * adding new stream and sink operators, or doing something highly specialized, | |
| * it may be useful to use channels directly. | |
| * | |
| * Channels compose in a variety of ways: | |
| * | |
| * - **Piping**: One channel can be piped to another channel, assuming the | |
| * input type of the second is the same as the output type of the first. | |
| * - **Sequencing**: The terminal value of one channel can be used to create | |
| * another channel, and both the first channel and the function that makes | |
| * the second channel can be composed into a channel. | |
| * - **Concatenating**: The output of one channel can be used to create other | |
| * channels, which are all concatenated together. The first channel and the | |
| * function that makes the other channels can be composed into a channel. | |
| * | |
| * **Example** (Typing channels) | |
| * | |
| * ```ts | |
| * import type { Channel } from "effect" | |
| * | |
| * // A channel that outputs numbers and requires no environment | |
| * type NumberChannel = Channel.Channel<number> | |
| * | |
| * // A channel that outputs strings, can fail with Error, completes with boolean | |
| * type StringChannel = Channel.Channel<string, Error, boolean> | |
| * | |
| * // A channel with all type parameters specified | |
| * type FullChannel = Channel.Channel< | |
| * string, // OutElem - output elements | |
| * Error, // OutErr - output errors | |
| * number, // OutDone - completion value | |
| * number, // InElem - input elements | |
| * string, // InErr - input errors | |
| * boolean, // InDone - input completion | |
| * { db: string } // Env - required environment | |
| * > | |
| * ``` | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface Channel< | |
| out OutElem, | |
| out OutErr = never, | |
| out OutDone = void, | |
| in InElem = unknown, | |
| in InErr = unknown, | |
| in InDone = unknown, | |
| out Env = never | |
| > extends Variance<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, Pipeable { | |
| [Unify.typeSymbol]?: unknown | |
| [Unify.unifySymbol]?: ChannelUnify<this> | |
| [Unify.ignoreSymbol]?: ChannelUnifyIgnore | |
| } | |
| /** | |
| * Type-level unification support for `Channel` values. | |
| * | |
| * **Details** | |
| * | |
| * This preserves all `Channel` type parameters when `Unify` normalizes unions | |
| * or generic return types that include channels. Users normally do not need to | |
| * reference this interface directly. | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface ChannelUnify<A extends { [Unify.typeSymbol]?: any }> extends Effect.EffectUnify<A> { | |
| Channel?: () => A[Unify.typeSymbol] extends | |
| | Channel<infer OutElem, infer OutErr, infer OutDone, infer InElem, infer InErr, infer InDone, infer Env> | |
| | infer _ ? Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| : never | |
| } | |
| /** | |
| * Marker used by `Unify` while resolving `Channel` values. | |
| * | |
| * **Details** | |
| * | |
| * It prevents the inherited `Effect` unifier from being selected when the | |
| * channel-specific unifier should preserve `Channel` input, output, and | |
| * environment type parameters. Users normally do not need to reference this | |
| * interface directly. | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface ChannelUnifyIgnore { | |
| Effect?: true | |
| } | |
| type TagsWithReason<E> = { | |
| [T in Types.Tags<E>]: Types.ReasonTags<Types.ExtractTag<E, T>> extends never ? never : T | |
| }[Types.Tags<E>] | |
| /** | |
| * Phantom variance marker for the type parameters of `Channel`. | |
| * | |
| * **Details** | |
| * | |
| * Output element, output error, output done, and environment types are | |
| * covariant. Input element, input error, and input done types are | |
| * contravariant. This is type-level machinery and is not used directly at | |
| * runtime. | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface Variance< | |
| out OutElem, | |
| out OutErr, | |
| out OutDone, | |
| in InElem, | |
| in InErr, | |
| in InDone, | |
| out Env | |
| > { | |
| readonly [TypeId]: VarianceStruct<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } | |
| /** | |
| * Structural encoding used by `Variance` to record each `Channel` type | |
| * parameter's variance. | |
| * | |
| * **Details** | |
| * | |
| * The `_OutElem`, `_OutErr`, `_OutDone`, and `_Env` fields are covariant; the | |
| * `_InElem`, `_InErr`, and `_InDone` fields are contravariant. Users normally | |
| * do not need to reference this interface directly. | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface VarianceStruct< | |
| out OutElem, | |
| out OutErr, | |
| out OutDone, | |
| in InElem, | |
| in InErr, | |
| in InDone, | |
| out Env | |
| > { | |
| _Env: Types.Covariant<Env> | |
| _InErr: Types.Contravariant<InErr> | |
| _InElem: Types.Contravariant<InElem> | |
| _InDone: Types.Contravariant<InDone> | |
| _OutErr: Types.Covariant<OutErr> | |
| _OutElem: Types.Covariant<OutElem> | |
| _OutDone: Types.Covariant<OutDone> | |
| } | |
| const ChannelProto = { | |
| [TypeId]: { | |
| _Env: identity_, | |
| _InErr: identity_, | |
| _InElem: identity_, | |
| _OutErr: identity_, | |
| _OutElem: identity_ | |
| }, | |
| pipe() { | |
| return pipeArguments(this, arguments) | |
| } | |
| } | |
| // ----------------------------------------------------------------------------- | |
| // Constructors | |
| // ----------------------------------------------------------------------------- | |
| /** | |
| * Creates a `Channel` from a transformation function that operates on upstream pulls. | |
| * | |
| * **Example** (Creating channels from transforms) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.fromTransform((upstream, scope) => | |
| * Effect.succeed(upstream) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromTransform = <OutElem, OutErr, OutDone, InElem, InErr, InDone, EX, EnvX, Env>( | |
| transform: ( | |
| upstream: Pull.Pull<InElem, InErr, InDone>, | |
| scope: Scope.Scope | |
| ) => Effect.Effect<Pull.Pull<OutElem, OutErr, OutDone, EnvX>, EX, Env> | |
| ): Channel< | |
| OutElem, | |
| Pull.ExcludeDone<OutErr> | EX, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | EnvX | |
| > => { | |
| const self = Object.create(ChannelProto) | |
| self.transform = (upstream: any, scope: Scope.Scope) => | |
| Effect.catchCause(transform(upstream, scope), (cause) => Effect.succeed(Effect.failCause(cause))) | |
| return self | |
| } | |
| /** | |
| * Transforms a Channel by applying a function to its Pull implementation. | |
| * | |
| * **Example** (Transforming pull behavior) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Transform a channel by modifying its pull behavior | |
| * const originalChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * const transformedChannel = Channel.transformPull( | |
| * originalChannel, | |
| * (pull, scope) => | |
| * Effect.succeed( | |
| * Effect.map(pull, (value) => value * 2) | |
| * ) | |
| * ) | |
| * // Outputs: 2, 4, 6 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const transformPull = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem2, | |
| OutErr2, | |
| OutDone2, | |
| Env2, | |
| OutErrX, | |
| EnvX | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: ( | |
| pull: Pull.Pull<OutElem, OutErr, OutDone>, | |
| scope: Scope.Scope | |
| ) => Effect.Effect<Pull.Pull<OutElem2, OutErr2, OutDone2, Env2>, OutErrX, EnvX> | |
| ): Channel< | |
| OutElem2, | |
| Pull.ExcludeDone<OutErr2> | OutErrX, | |
| OutDone2, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | Env2 | EnvX | |
| > => fromTransform((upstream, scope) => Effect.flatMap(toTransform(self)(upstream, scope), (pull) => f(pull, scope))) | |
| /** | |
| * Creates a `Channel` from an `Effect` that produces a `Pull`. | |
| * | |
| * **Example** (Creating channels from pulls) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.fromPull( | |
| * Effect.succeed(Effect.succeed(42)) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromPull = <OutElem, OutErr, OutDone, EX, EnvX, Env>( | |
| effect: Effect.Effect<Pull.Pull<OutElem, OutErr, OutDone, EnvX>, EX, Env> | |
| ): Channel<OutElem, Pull.ExcludeDone<OutErr> | EX, OutDone, unknown, unknown, unknown, Env | EnvX> => | |
| fromTransform((_, __) => effect) as any | |
| /** | |
| * Creates a `Channel` from a transformation function that operates on upstream | |
| * pulls, but also provides a forked scope that closes when the resulting | |
| * Channel completes. | |
| * | |
| * **When to use** | |
| * | |
| * Use when building channels that require scoped resource lifecycle management, | |
| * providing both the channel scope and a forked scope that automatically closes | |
| * when the channel completes. | |
| * | |
| * @see {@link fromTransform} for a simpler transformation without a forked scope | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromTransformBracket = <OutElem, OutErr, OutDone, InElem, InErr, InDone, EX, EnvX, Env>( | |
| f: ( | |
| upstream: Pull.Pull<InElem, InErr, InDone>, | |
| scope: Scope.Scope, | |
| forkedScope: Scope.Scope | |
| ) => Effect.Effect<Pull.Pull<OutElem, OutErr, OutDone, EnvX>, EX, Env> | |
| ): Channel<OutElem, Pull.ExcludeDone<OutErr> | EX, OutDone, InElem, InErr, InDone, Env | EnvX> => | |
| fromTransform( | |
| Effect.fnUntraced(function*(upstream, scope) { | |
| const closableScope = Scope.forkUnsafe(scope) | |
| const onCause = (cause: Cause.Cause<EX | OutErr | Cause.Done<OutDone>>) => | |
| Scope.close(closableScope, Pull.doneExitFromCause(cause)) | |
| const pull = yield* Effect.onError( | |
| f(upstream, scope, closableScope), | |
| onCause | |
| ) | |
| return Effect.onError(pull, onCause) | |
| }) | |
| ) | |
| /** | |
| * Converts a `Channel` back to its underlying transformation function. | |
| * | |
| * **Example** (Extracting channel transforms) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.succeed(42) | |
| * const transform = Channel.toTransform(channel) | |
| * // transform can now be used directly | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const toTransform = <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| channel: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): ( | |
| upstream: Pull.Pull<InElem, InErr, InDone>, | |
| scope: Scope.Scope | |
| ) => Effect.Effect<Pull.Pull<OutElem, OutErr, OutDone>, never, Env> => (channel as any).transform | |
| /** | |
| * The default chunk size used by channels for batching operations. | |
| * | |
| * **Example** (Reading the default chunk size) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * console.log(Channel.DefaultChunkSize) // 4096 | |
| * ``` | |
| * | |
| * @category constants | |
| * @since 4.0.0 | |
| */ | |
| export const DefaultChunkSize: number = 4096 | |
| const asyncQueue = <A, E = never, R = never>( | |
| scope: Scope.Scope, | |
| f: (queue: Queue.Queue<A, E | Cause.Done>) => Effect.Effect<unknown, E, R | Scope.Scope>, | |
| options?: { | |
| readonly bufferSize?: number | undefined | |
| readonly strategy?: "sliding" | "dropping" | "suspend" | undefined | |
| } | |
| ) => | |
| Queue.make<A, E | Cause.Done>({ | |
| capacity: options?.bufferSize, | |
| strategy: options?.strategy | |
| }).pipe( | |
| Effect.tap((queue) => Scope.addFinalizer(scope, Queue.shutdown(queue))), | |
| Effect.tap((queue) => Effect.forkIn(Scope.provide(f(queue), scope), scope)) | |
| ) | |
| /** | |
| * Creates a `Channel` that interacts with a callback function using a queue. | |
| * | |
| * **Example** (Creating channels from callbacks) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, Queue } from "effect" | |
| * | |
| * const channel = Channel.callback<number>((queue) => | |
| * Effect.gen(function*() { | |
| * yield* Queue.offer(queue, 1) | |
| * yield* Queue.offer(queue, 2) | |
| * yield* Queue.offer(queue, 3) | |
| * }) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const callback = <A, E = never, R = never>( | |
| f: (queue: Queue.Queue<A, E | Cause.Done>) => Effect.Effect<unknown, E, R | Scope.Scope>, | |
| options?: { | |
| readonly bufferSize?: number | undefined | |
| readonly strategy?: "sliding" | "dropping" | "suspend" | undefined | |
| } | |
| ): Channel<A, E, void, unknown, unknown, unknown, Exclude<R, Scope.Scope>> => | |
| fromTransform((_, scope) => Effect.map(asyncQueue(scope, f, options), Queue.take)) | |
| /** | |
| * Creates a `Channel` that interacts with a callback function using a queue, emitting arrays. | |
| * | |
| * **Example** (Creating array channels from callbacks) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, Queue } from "effect" | |
| * | |
| * const channel = Channel.callbackArray<number>(Effect.fn(function*(queue) { | |
| * yield* Queue.offer(queue, 1) | |
| * yield* Queue.offer(queue, 2) | |
| * })) | |
| * // Emits arrays of numbers instead of individual numbers | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const callbackArray = <A, E = never, R = never>( | |
| f: (queue: Queue.Queue<A, E | Cause.Done>) => Effect.Effect<unknown, E, R | Scope.Scope>, | |
| options?: { | |
| readonly bufferSize?: number | undefined | |
| readonly strategy?: "sliding" | "dropping" | "suspend" | undefined | |
| } | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, E, void, unknown, unknown, unknown, Exclude<R, Scope.Scope>> => | |
| fromTransform((_, scope) => Effect.map(asyncQueue(scope, f, options), Queue.takeAll)) | |
| /** | |
| * Creates a `Channel` that lazily evaluates to another channel. | |
| * | |
| * **Example** (Suspending channel creation) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.suspend(() => Channel.succeed(42)) | |
| * // The inner channel is not created until the suspended channel is run | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const suspend = <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| evaluate: LazyArg<Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| fromTransform((upstream, scope) => Effect.suspend(() => toTransform(evaluate())(upstream, scope))) | |
| /** | |
| * Acquires a resource, uses it to build a `Channel`, and guarantees that | |
| * `release` runs with the channel's `Exit` when the channel completes, fails, | |
| * or is interrupted. | |
| * | |
| * **Details** | |
| * | |
| * Acquisition is uninterruptible. If acquisition fails, `use` is not run and | |
| * `release` is not registered. | |
| * | |
| * **Example** (Managing resources with acquire-use-release) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.acquireUseRelease( | |
| * Effect.succeed("resource"), | |
| * (resource) => Channel.succeed(resource.toUpperCase()), | |
| * (resource, exit) => Effect.log(`Released: ${resource}`) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const acquireUseRelease = <A, E, R, OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| acquire: Effect.Effect<A, E, R>, | |
| use: (a: A) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| release: (a: A, exit: Exit.Exit<OutDone, OutErr>) => Effect.Effect<unknown> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| fromTransformBracket( | |
| Effect.fnUntraced(function*(upstream, scope, forkedScope) { | |
| let option = Option.none<A>() | |
| yield* Scope.addFinalizerExit(forkedScope, (exit) => | |
| Option.isSome(option) | |
| ? release(option.value, exit as any) | |
| : Effect.void) | |
| const value = yield* Effect.uninterruptible(acquire) | |
| option = Option.some(value) | |
| return yield* toTransform(use(value))(upstream, scope) | |
| }) | |
| ) | |
| /** | |
| * Acquires a resource, emits the acquired value as a single channel element, | |
| * and registers `release` in the channel scope. | |
| * | |
| * **Details** | |
| * | |
| * The release action runs when the channel scope closes and receives the scope | |
| * exit. If acquisition fails, no element is emitted and `release` is not | |
| * registered. | |
| * | |
| * **Example** (Managing resources with acquire-release) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.acquireRelease( | |
| * Effect.succeed("resource"), | |
| * (resource, exit) => Effect.log(`Released: ${resource}`) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const acquireRelease: { | |
| /** | |
| * Acquires a resource, emits the acquired value as a single channel element, | |
| * and registers `release` in the channel scope. | |
| * | |
| * **Details** | |
| * | |
| * The release action runs when the channel scope closes and receives the scope | |
| * exit. If acquisition fails, no element is emitted and `release` is not | |
| * registered. | |
| * | |
| * **Example** (Managing resources with acquire-release) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.acquireRelease( | |
| * Effect.succeed("resource"), | |
| * (resource, exit) => Effect.log(`Released: ${resource}`) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| <Z>(release: (z: Z, e: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown>): <E, R>(self: Effect.Effect<Z, E, R>) => Channel<Z, E, void, unknown, unknown, unknown, R> | |
| /** | |
| * Acquires a resource, emits the acquired value as a single channel element, | |
| * and registers `release` in the channel scope. | |
| * | |
| * **Details** | |
| * | |
| * The release action runs when the channel scope closes and receives the scope | |
| * exit. If acquisition fails, no element is emitted and `release` is not | |
| * registered. | |
| * | |
| * **Example** (Managing resources with acquire-release) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * const channel = Channel.acquireRelease( | |
| * Effect.succeed("resource"), | |
| * (resource, exit) => Effect.log(`Released: ${resource}`) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| <Z, E, R>( | |
| self: Effect.Effect<Z, E, R>, | |
| release: (z: Z, e: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown> | |
| ): Channel<Z, E, void, unknown, unknown, unknown, R> | |
| } = dual(2, <Z, E, R>( | |
| self: Effect.Effect<Z, E, R>, | |
| release: (z: Z, e: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown> | |
| ): Channel<Z, E, void, unknown, unknown, unknown, R> => | |
| unwrap(Effect.map( | |
| Effect.acquireRelease(self, release), | |
| succeed | |
| ))) | |
| /** | |
| * Creates a `Channel` from an iterator. | |
| * | |
| * **Example** (Creating channels from iterators) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const numbers = [1, 2, 3, 4, 5] | |
| * const channel = Channel.fromIterator(() => numbers[Symbol.iterator]()) | |
| * // Emits: 1, 2, 3, 4, 5 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromIterator = <A, L>(iterator: LazyArg<Iterator<A, L>>): Channel<A, never, L> => | |
| fromPull( | |
| Effect.sync(() => { | |
| const iter = iterator() | |
| return Effect.suspend(() => { | |
| const state = iter.next() | |
| return state.done ? Cause.done(state.value) : Effect.succeed(state.value) | |
| }) | |
| }) | |
| ) | |
| /** | |
| * Creates a `Channel` that emits all elements from an array. | |
| * | |
| * **Example** (Creating channels from arrays) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.fromArray([1, 2, 3, 4, 5]) | |
| * // Emits: 1, 2, 3, 4, 5 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromArray = <A>(array: ReadonlyArray<A>): Channel<A> => | |
| fromPull(Effect.sync(() => { | |
| let index = 0 | |
| return Effect.suspend(() => index >= array.length ? Cause.done() : Effect.succeed(array[index++])) | |
| })) | |
| /** | |
| * Creates a `Channel` that emits all elements from a chunk. | |
| * | |
| * **Example** (Creating channels from chunks) | |
| * | |
| * ```ts | |
| * import { Channel, Chunk } from "effect" | |
| * | |
| * const chunk = Chunk.make(1, 2, 3) | |
| * const channel = Channel.fromChunk(chunk) | |
| * // Emits: 1, 2, 3 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromChunk = <A>(chunk: Chunk.Chunk<A>): Channel<A> => fromArray(Chunk.toReadonlyArray(chunk)) | |
| /** | |
| * Creates a `Channel` from an iterator that emits arrays of elements. | |
| * | |
| * **Example** (Batching iterator output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel from a simple iterator | |
| * const numberIterator = (): Iterator<number, string> => { | |
| * let count = 0 | |
| * return { | |
| * next: () => { | |
| * if (count < 3) { | |
| * return { value: count++, done: false } | |
| * } | |
| * return { value: "finished", done: true } | |
| * } | |
| * } | |
| * } | |
| * | |
| * const channel = Channel.fromIteratorArray(() => numberIterator(), 2) | |
| * // This will emit arrays: [0, 1], [2], then complete with "finished" | |
| * ``` | |
| * | |
| * **Example** (Batching generator output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create channel from a generator function | |
| * function* fibonacci(): Generator<number, void, unknown> { | |
| * let a = 0, b = 1 | |
| * for (let i = 0; i < 5; i++) { | |
| * yield a | |
| * ;[a, b] = [b, a + b] | |
| * } | |
| * } | |
| * | |
| * const fibChannel = Channel.fromIteratorArray(() => fibonacci(), 3) | |
| * // Emits: [0, 1, 1], [2, 3], then completes | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromIteratorArray = <A, L>( | |
| iterator: LazyArg<Iterator<A, L>>, | |
| chunkSize = DefaultChunkSize | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, never, L> => | |
| fromPull( | |
| Effect.sync(() => { | |
| const iter = iterator() | |
| let done = Option.none<L>() | |
| return Effect.suspend(() => { | |
| if (done._tag === "Some") return Cause.done(done.value) | |
| const buffer: Array<A> = [] | |
| while (buffer.length < chunkSize) { | |
| const state = iter.next() | |
| if (state.done) { | |
| if (buffer.length === 0) { | |
| return Cause.done(state.value) | |
| } | |
| done = Option.some(state.value) | |
| break | |
| } | |
| buffer.push(state.value) | |
| } | |
| return Effect.succeed(buffer as any as Arr.NonEmptyReadonlyArray<A>) | |
| }) | |
| }) | |
| ) | |
| /** | |
| * Creates a `Channel` that emits all elements from an iterable. | |
| * | |
| * **Example** (Creating channels from iterables) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const set = new Set([1, 2, 3]) | |
| * const channel = Channel.fromIterable(set) | |
| * // Emits: 1, 2, 3 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromIterable = <A, L>(iterable: Iterable<A, L>): Channel<A, never, L> => | |
| fromIterator(() => iterable[Symbol.iterator]()) | |
| /** | |
| * Creates a `Channel` that emits arrays of elements from an iterable. | |
| * | |
| * **Example** (Batching iterable output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const numbers = [1, 2, 3, 4, 5] | |
| * const channel = Channel.fromIterableArray(numbers) | |
| * // Emits arrays like: [1, 2, 3, 4], [5] (based on chunk size) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromIterableArray = <A, L>( | |
| iterable: Iterable<A, L>, | |
| chunkSize = DefaultChunkSize | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, never, L> => fromIteratorArray(() => iterable[Symbol.iterator](), chunkSize) | |
| /** | |
| * Creates a `Channel` that emits a single value and then ends. | |
| * | |
| * **Example** (Creating channels that succeed) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.succeed(42) | |
| * // Emits: 42 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const succeed = <A>(value: A): Channel<A> => fromEffect(Effect.succeed(value)) | |
| /** | |
| * Creates a `Channel` that immediately ends with the specified value. | |
| * | |
| * **Example** (Ending with a value) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * const channel = Channel.end("done") | |
| * // Ends immediately with "done", emits nothing | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const end = <A>(value: A): Channel<never, never, A> => fromPull(Effect.succeed(Cause.done(value))) | |
| /** | |
| * Creates a `Channel` that immediately ends with the lazily evaluated value. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const endSync = <A>(evaluate: LazyArg<A>): Channel<never, never, A> => | |
| fromPull(Effect.sync(() => Cause.done(evaluate()))) | |
| /** | |
| * Creates a `Channel` that emits a single value computed by a lazy evaluation. | |
| * | |
| * **Example** (Computing values lazily) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * let requests = 0 | |
| * | |
| * const channel = Channel.sync(() => { | |
| * requests += 1 | |
| * return `request-${requests}` | |
| * }) | |
| * // Emits "request-1" when the channel runs for the first time | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const sync = <A>(evaluate: LazyArg<A>): Channel<A> => fromEffect(Effect.sync(evaluate)) | |
| /** | |
| * Represents a `Channel` that emits no elements. | |
| * | |
| * **Example** (Using empty channels) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create an empty channel | |
| * const emptyChannel = Channel.empty | |
| * | |
| * // Use empty channel in composition | |
| * const combined = Channel.concatWith(emptyChannel, () => Channel.succeed(42)) | |
| * // Will immediately provide the second channel's output | |
| * | |
| * // Empty channel can be used as a no-op in conditional logic | |
| * const conditionalChannel = (shouldEmit: boolean) => | |
| * shouldEmit ? Channel.succeed("data") : Channel.empty | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const empty: Channel<never> = fromPull(Effect.succeed(Cause.done())) | |
| /** | |
| * Represents a `Channel` that never completes. | |
| * | |
| * **Example** (Using non-terminating channels) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel that never completes | |
| * const neverChannel = Channel.never | |
| * | |
| * // Use in conditional logic | |
| * const withFallback = Channel.concatWith( | |
| * neverChannel, | |
| * () => Channel.succeed("fallback") | |
| * ) | |
| * | |
| * // Never channel is useful for testing or as a placeholder | |
| * const conditionalChannel = (shouldComplete: boolean) => | |
| * shouldComplete ? Channel.succeed("done") : Channel.never | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const never: Channel<never, never, never> = fromPull(Effect.succeed(Effect.never)) | |
| /** | |
| * Constructs a channel that fails immediately with the specified error. | |
| * | |
| * **Example** (Failing with an error) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel that fails with a string error | |
| * const failedChannel = Channel.fail("Something went wrong") | |
| * | |
| * // Create a channel that fails with a custom error | |
| * class CustomError extends Error { | |
| * constructor(message: string) { | |
| * super(message) | |
| * this.name = "CustomError" | |
| * } | |
| * } | |
| * const customErrorChannel = Channel.fail(new CustomError("Custom error")) | |
| * | |
| * // Use in error handling by piping to another channel | |
| * const channelWithFallback = Channel.concatWith( | |
| * failedChannel, | |
| * () => Channel.succeed("fallback value") | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const fail = <E>(error: E): Channel<never, E, never> => fromPull(Effect.succeed(Effect.fail(error))) | |
| /** | |
| * Constructs a channel that fails immediately with the specified lazily | |
| * evaluated error. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the error value should be computed each time the channel runs instead | |
| * of when the channel is constructed. | |
| * | |
| * **Example** (Failing with a lazy error) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel that fails with a lazily computed error | |
| * const failedChannel = Channel.failSync(() => { | |
| * console.log("Computing error...") | |
| * return new Error("Computed at runtime") | |
| * }) | |
| * | |
| * // The error computation is deferred until the channel runs | |
| * let attempts = 0 | |
| * const conditionalError = Channel.failSync(() => { | |
| * attempts += 1 | |
| * return `Error after attempt ${attempts}` | |
| * }) | |
| * | |
| * // Use with expensive error construction | |
| * const expensiveError = Channel.failSync(() => { | |
| * const requestId = "request-123" | |
| * return new Error(`Failed while processing ${requestId}`) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const failSync = <E>(evaluate: LazyArg<E>): Channel<never, E, never> => fromPull(Effect.failSync(evaluate)) | |
| /** | |
| * Constructs a channel that fails immediately with the specified `Cause`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the channel failure must preserve a full `Cause`, such as defects, | |
| * interruptions, or combined failures. | |
| * | |
| * **Example** (Failing with causes) | |
| * | |
| * ```ts | |
| * import { Cause, Channel } from "effect" | |
| * | |
| * // Create a channel that fails with a simple cause | |
| * const simpleCause = Cause.fail("Simple error") | |
| * const failedChannel = Channel.failCause(simpleCause) | |
| * | |
| * // Create a channel with a die cause | |
| * const dieCause = Cause.die(new Error("System error")) | |
| * const dieFailure = Channel.failCause(dieCause) | |
| * | |
| * // Create a channel with a simple fail cause | |
| * const failCause = Cause.fail("Simple error") | |
| * const simpleFail = Channel.failCause(failCause) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const failCause = <E>(cause: Cause.Cause<E>): Channel<never, E, never> => fromPull(Effect.failCause(cause)) | |
| /** | |
| * Constructs a channel that fails immediately with the specified lazily | |
| * evaluated `Cause`. | |
| * | |
| * **Example** (Failing with lazy causes) | |
| * | |
| * ```ts | |
| * import { Cause, Channel } from "effect" | |
| * | |
| * // Create a channel that fails with a lazily computed cause | |
| * let attempts = 0 | |
| * const failedChannel = Channel.failCauseSync(() => { | |
| * attempts += 1 | |
| * return Cause.fail(`Runtime error after attempt ${attempts}`) | |
| * }) | |
| * | |
| * // Create a channel with die cause computation | |
| * const dieCauseChannel = Channel.failCauseSync(() => { | |
| * const operation = "load-profile" | |
| * return Cause.die(`Unexpected defect during ${operation}`) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const failCauseSync = <E>( | |
| evaluate: LazyArg<Cause.Cause<E>> | |
| ): Channel<never, E, never> => fromPull(Effect.failCauseSync(evaluate)) | |
| /** | |
| * Constructs a channel that fails immediately with the specified defect. | |
| * | |
| * **Example** (Dying with defects) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel that dies with a string defect | |
| * const diedChannel = Channel.die("Unrecoverable error") | |
| * | |
| * // Create a channel that dies with an Error object | |
| * const errorDefect = Channel.die(new Error("System failure")) | |
| * | |
| * // Die with any value as a defect | |
| * const objectDefect = Channel.die({ | |
| * code: "SYSTEM_FAILURE", | |
| * details: "Critical system component failed" | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const die = (defect: unknown): Channel<never, never, never> => failCause(Cause.die(defect)) | |
| /** | |
| * Uses an effect to write a single value to the channel. | |
| * | |
| * **Example** (Creating channels from effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class DatabaseError extends Data.TaggedError("DatabaseError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a channel from a successful effect | |
| * const successChannel = Channel.fromEffect( | |
| * Effect.succeed("Hello from effect!") | |
| * ) | |
| * | |
| * // Create a channel from an effect that might fail | |
| * const fetchUserChannel = Channel.fromEffect( | |
| * Effect.tryPromise({ | |
| * try: () => fetch("/api/user").then((res) => res.json()), | |
| * catch: (error) => new DatabaseError({ message: String(error) }) | |
| * }) | |
| * ) | |
| * | |
| * // Channel from effect with async computation | |
| * const asyncChannel = Channel.fromEffect( | |
| * Effect.gen(function*() { | |
| * yield* Effect.sleep("100 millis") | |
| * return "Async result" | |
| * }) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const fromEffect = <A, E, R>( | |
| effect: Effect.Effect<A, E, R> | |
| ): Channel<A, Pull.ExcludeDone<E>, void, unknown, unknown, unknown, R> => | |
| fromPull( | |
| Effect.sync(() => { | |
| let done = false | |
| return Effect.suspend((): Pull.Pull<A, E, void, R> => { | |
| if (done) return Cause.done() | |
| done = true | |
| return effect | |
| }) | |
| }) | |
| ) | |
| /** | |
| * Creates a channel that evaluates an effect and uses its successful value as | |
| * the channel's done value without emitting any output elements. | |
| * | |
| * **Details** | |
| * | |
| * If the effect fails, the channel fails with the effect's error. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromEffectDone = <A, E, R>( | |
| effect: Effect.Effect<A, E, R> | |
| ): Channel<never, Pull.ExcludeDone<E>, A, unknown, unknown, unknown, R> => | |
| fromPull(Effect.succeed(Effect.flatMap(effect, Cause.done))) | |
| /** | |
| * Uses an effect and discards its result. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromEffectDrain = <A, E, R>( | |
| effect: Effect.Effect<A, E, R> | |
| ): Channel<never, E, void, unknown, unknown, unknown, R> => fromPull(Effect.flatMap(effect, () => Cause.done())) as any | |
| /** | |
| * Creates a channel from an effect that produces a `Take`. | |
| * | |
| * **Details** | |
| * | |
| * A successful `Take` emits a non-empty array of output elements. A failed | |
| * `Take` fails the channel. A done `Take` completes the channel with its done | |
| * value. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromEffectTake = <A, E, Done, E2, R>( | |
| effect: Effect.Effect<Take.Take<A, E, Done>, E2, R> | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, E | E2, Done, unknown, unknown, unknown, R> => | |
| fromPull(Effect.succeed(Effect.flatMap(effect, Take.toPull))) | |
| /** | |
| * Creates a channel from a queue. | |
| * | |
| * **Example** (Creating channels from queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, Queue } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * // Create a bounded queue | |
| * const queue = yield* Queue.bounded<string, QueueError>(10) | |
| * | |
| * // Add some items to the queue | |
| * yield* Queue.offer(queue, "item1") | |
| * yield* Queue.offer(queue, "item2") | |
| * yield* Queue.offer(queue, "item3") | |
| * | |
| * // Create a channel from the queue | |
| * const channel = Channel.fromQueue(queue) | |
| * | |
| * // The channel will read items from the queue one by one | |
| * return channel | |
| * }) | |
| * | |
| * // Sliding queue example | |
| * const slidingProgram = Effect.gen(function*() { | |
| * const slidingQueue = yield* Queue.sliding<number, QueueError>(5) | |
| * yield* Queue.offerAll(slidingQueue, [1, 2, 3, 4, 5, 6]) | |
| * return Channel.fromQueue(slidingQueue) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const fromQueue = <A, E>( | |
| queue: Queue.Dequeue<A, E> | |
| ): Channel<A, Exclude<E, Cause.Done>> => fromPull(Effect.succeed(Queue.take(queue))) | |
| /** | |
| * Creates a channel from a queue that emits arrays of elements. | |
| * | |
| * **Example** (Creating batched channels from queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, Queue } from "effect" | |
| * | |
| * class ProcessingError extends Data.TaggedError("ProcessingError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * // Create a queue for batch processing | |
| * const queue = yield* Queue.bounded<number, ProcessingError>(100) | |
| * | |
| * // Fill queue with data | |
| * yield* Queue.offerAll(queue, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) | |
| * | |
| * // Create a channel that reads arrays from the queue | |
| * const arrayChannel = Channel.fromQueueArray(queue) | |
| * | |
| * // This will emit non-empty arrays of elements instead of individual items | |
| * // Useful for batch processing scenarios | |
| * return arrayChannel | |
| * }) | |
| * | |
| * // High-throughput processing example | |
| * const batchProcessor = Effect.gen(function*() { | |
| * const dataQueue = yield* Queue.dropping<string, ProcessingError>(1000) | |
| * const batchChannel = Channel.fromQueueArray(dataQueue) | |
| * | |
| * // Process data in batches for better performance | |
| * return Channel.map( | |
| * batchChannel, | |
| * (batch) => batch.map((item) => item.toUpperCase()) | |
| * ) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromQueueArray = <A, E>( | |
| queue: Queue.Dequeue<A, E> | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, Exclude<E, Cause.Done>> => fromPull(Effect.succeed(Queue.takeAll(queue))) | |
| /** | |
| * Creates a channel that forwards upstream input elements, input errors, and | |
| * the upstream done value unchanged. | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const identity = <Elem, Err, Done>(): Channel<Elem, Err, Done, Elem, Err, Done> => | |
| fromTransform((upstream, _scope) => Effect.succeed(upstream)) | |
| /** | |
| * Creates a channel from a PubSub subscription. | |
| * | |
| * **Example** (Creating channels from subscriptions) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, PubSub } from "effect" | |
| * | |
| * class SubscriptionError extends Data.TaggedError("SubscriptionError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * // Create a PubSub | |
| * const pubsub = yield* PubSub.bounded<string>(32) | |
| * | |
| * // Create a subscription | |
| * const subscription = yield* PubSub.subscribe(pubsub) | |
| * | |
| * // Publish some messages | |
| * yield* PubSub.publish(pubsub, "Hello") | |
| * yield* PubSub.publish(pubsub, "World") | |
| * yield* PubSub.publish(pubsub, "from") | |
| * yield* PubSub.publish(pubsub, "PubSub") | |
| * | |
| * // Create a channel from the subscription | |
| * const channel = Channel.fromSubscription(subscription) | |
| * | |
| * // The channel will receive all published messages | |
| * return channel | |
| * }) | |
| * | |
| * // Real-time notifications example | |
| * const notificationChannel = Effect.gen(function*() { | |
| * const eventBus = yield* PubSub.unbounded<{ type: string; payload: any }>() | |
| * const userSubscription = yield* PubSub.subscribe(eventBus) | |
| * | |
| * return Channel.fromSubscription(userSubscription) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromSubscription = <A>( | |
| subscription: PubSub.Subscription<A> | |
| ): Channel<A> => fromPull(Effect.succeed(Effect.onInterrupt(PubSub.take(subscription), () => Cause.done()))) | |
| /** | |
| * Creates a channel from a PubSub subscription that outputs arrays of values. | |
| * | |
| * **Details** | |
| * | |
| * This constructor creates a channel that reads from a PubSub subscription and outputs | |
| * arrays of values in chunks. It's useful when you want to process multiple values at once | |
| * for better performance. | |
| * | |
| * **Example** (Batching subscription values) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, PubSub } from "effect" | |
| * | |
| * class StreamError extends Data.TaggedError("StreamError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * const pubsub = yield* PubSub.bounded<number>(16) | |
| * const subscription = yield* PubSub.subscribe(pubsub) | |
| * | |
| * // Create a channel that reads arrays of values | |
| * const channel = Channel.fromSubscriptionArray(subscription) | |
| * | |
| * // Publish some values | |
| * yield* PubSub.publish(pubsub, 1) | |
| * yield* PubSub.publish(pubsub, 2) | |
| * yield* PubSub.publish(pubsub, 3) | |
| * yield* PubSub.publish(pubsub, 4) | |
| * | |
| * // The channel will output arrays like [1, 2, 3] and [4] | |
| * return channel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Processing subscription values in batches) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, PubSub } from "effect" | |
| * | |
| * class BatchProcessingError extends Data.TaggedError("BatchProcessingError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * const batchProcessor = Effect.gen(function*() { | |
| * const pubsub = yield* PubSub.bounded<string>(32) | |
| * const subscription = yield* PubSub.subscribe(pubsub) | |
| * | |
| * // Create a channel that processes items in batches | |
| * const batchChannel = Channel.fromSubscriptionArray(subscription) | |
| * | |
| * // Transform to process each batch | |
| * const processedChannel = Channel.map(batchChannel, (batch) => { | |
| * console.log(`Processing batch of ${batch.length} items:`, batch) | |
| * return batch.map((item) => item.toUpperCase()) | |
| * }) | |
| * | |
| * return processedChannel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Aggregating subscription metrics) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, PubSub } from "effect" | |
| * | |
| * const metricsAggregator = Effect.gen(function*() { | |
| * const metricsPubSub = yield* PubSub.bounded< | |
| * { timestamp: number; value: number } | |
| * >(100) | |
| * const subscription = yield* PubSub.subscribe(metricsPubSub) | |
| * | |
| * // Create a channel that collects metrics in chunks | |
| * const metricsChannel = Channel.fromSubscriptionArray(subscription) | |
| * | |
| * // Transform to calculate aggregate statistics | |
| * const aggregatedChannel = Channel.map(metricsChannel, (metrics) => { | |
| * const values = metrics.map((m) => m.value) | |
| * const sum = values.reduce((a, b) => a + b, 0) | |
| * const avg = sum / values.length | |
| * const min = Math.min(...values) | |
| * const max = Math.max(...values) | |
| * | |
| * return { | |
| * count: values.length, | |
| * sum, | |
| * average: avg, | |
| * min, | |
| * max, | |
| * firstTimestamp: Math.min(...metrics.map((m) => m.timestamp)), | |
| * lastTimestamp: Math.max(...metrics.map((m) => m.timestamp)) | |
| * } | |
| * }) | |
| * | |
| * return aggregatedChannel | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromSubscriptionArray = <A>( | |
| subscription: PubSub.Subscription<A> | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>> => | |
| fromPull(Effect.succeed(Effect.onInterrupt(PubSub.takeAll(subscription), () => Cause.done()))) | |
| /** | |
| * Creates a channel from a PubSub that outputs individual values. | |
| * | |
| * **Details** | |
| * | |
| * This constructor creates a channel that reads from a PubSub by automatically | |
| * subscribing to it. The channel outputs individual values as they are published | |
| * to the PubSub, making it ideal for real-time streaming scenarios. | |
| * | |
| * **Example** (Creating channels from PubSubs) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, PubSub } from "effect" | |
| * | |
| * class StreamError extends Data.TaggedError("StreamError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * const pubsub = yield* PubSub.bounded<number>(16) | |
| * | |
| * // Create a channel that reads individual values | |
| * const channel = Channel.fromPubSub(pubsub) | |
| * | |
| * // Publish some values | |
| * yield* PubSub.publish(pubsub, 1) | |
| * yield* PubSub.publish(pubsub, 2) | |
| * yield* PubSub.publish(pubsub, 3) | |
| * | |
| * // The channel will output: 1, 2, 3 (individual values) | |
| * return channel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Streaming PubSub notifications) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, PubSub } from "effect" | |
| * | |
| * const notificationService = Effect.gen(function*() { | |
| * const notificationPubSub = yield* PubSub.bounded<string>(50) | |
| * | |
| * // Create a channel for real-time notifications | |
| * const notificationChannel = Channel.fromPubSub(notificationPubSub) | |
| * | |
| * // Transform notifications to add timestamps | |
| * const receivedAt = "2024-01-01T00:00:00.000Z" | |
| * const timestampedChannel = Channel.map(notificationChannel, (message) => ({ | |
| * message, | |
| * receivedAt, | |
| * id: `notification:${message}` | |
| * })) | |
| * | |
| * return timestampedChannel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Processing PubSub events) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, PubSub } from "effect" | |
| * | |
| * interface DomainEvent { | |
| * readonly type: string | |
| * readonly payload: unknown | |
| * readonly timestamp: number | |
| * } | |
| * | |
| * const eventProcessor = Effect.gen(function*() { | |
| * const eventPubSub = yield* PubSub.bounded<DomainEvent>(100) | |
| * | |
| * // Create a channel for processing domain events | |
| * const eventChannel = Channel.fromPubSub(eventPubSub) | |
| * | |
| * // Filter and transform events | |
| * const processedChannel = Channel.map(eventChannel, (event) => { | |
| * if (event.type === "user.created") { | |
| * return { | |
| * ...event, | |
| * processed: true, | |
| * processedAt: event.timestamp + 1 | |
| * } | |
| * } | |
| * return event | |
| * }) | |
| * | |
| * return processedChannel | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const fromPubSub = <A>( | |
| pubsub: PubSub.PubSub<A> | |
| ): Channel<A> => unwrap(Effect.map(PubSub.subscribe(pubsub), fromSubscription)) | |
| /** | |
| * Creates a channel from a PubSub that outputs arrays of values. | |
| * | |
| * **Details** | |
| * | |
| * This constructor creates a channel that reads from a PubSub by automatically | |
| * subscribing to it and collecting values into arrays. The channel outputs | |
| * arrays of values in chunks, making it ideal for batch processing scenarios. | |
| * | |
| * **Example** (Batching PubSub values) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, PubSub } from "effect" | |
| * | |
| * class BatchError extends Data.TaggedError("BatchError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * const program = Effect.gen(function*() { | |
| * const pubsub = yield* PubSub.bounded<number>(16) | |
| * | |
| * // Create a channel that reads arrays of values | |
| * const channel = Channel.fromPubSubArray(pubsub) | |
| * | |
| * // Publish some values | |
| * yield* PubSub.publish(pubsub, 1) | |
| * yield* PubSub.publish(pubsub, 2) | |
| * yield* PubSub.publish(pubsub, 3) | |
| * yield* PubSub.publish(pubsub, 4) | |
| * | |
| * // The channel will output arrays like [1, 2, 3] and [4] | |
| * return channel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Processing PubSub orders in batches) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, PubSub } from "effect" | |
| * | |
| * interface Order { | |
| * readonly id: string | |
| * readonly customerId: string | |
| * readonly items: ReadonlyArray<string> | |
| * readonly total: number | |
| * readonly submittedAt: number | |
| * } | |
| * | |
| * const orderBatchProcessor = Effect.gen(function*() { | |
| * const orderPubSub = yield* PubSub.bounded<Order>(100) | |
| * | |
| * // Create a channel that processes orders in batches | |
| * const orderChannel = Channel.fromPubSubArray(orderPubSub) | |
| * | |
| * // Transform to process each batch of orders | |
| * const processedChannel = Channel.map(orderChannel, (orderBatch) => { | |
| * const totalRevenue = orderBatch.reduce((sum, order) => sum + order.total, 0) | |
| * const customerCount = new Set(orderBatch.map((order) => | |
| * order.customerId | |
| * )).size | |
| * | |
| * return { | |
| * batchSize: orderBatch.length, | |
| * totalRevenue, | |
| * uniqueCustomers: customerCount, | |
| * firstSubmittedAt: Math.min(...orderBatch.map((order) => order.submittedAt)), | |
| * orders: orderBatch | |
| * } | |
| * }) | |
| * | |
| * return processedChannel | |
| * }) | |
| * ``` | |
| * | |
| * **Example** (Processing PubSub logs in batches) | |
| * | |
| * ```ts | |
| * import { Channel, Effect, PubSub } from "effect" | |
| * | |
| * interface LogEntry { | |
| * readonly timestamp: number | |
| * readonly level: "info" | "warn" | "error" | |
| * readonly message: string | |
| * readonly source: string | |
| * } | |
| * | |
| * const logAggregator = Effect.gen(function*() { | |
| * const logPubSub = yield* PubSub.bounded<LogEntry>(500) | |
| * | |
| * // Create a channel that collects logs in batches | |
| * const logChannel = Channel.fromPubSubArray(logPubSub) | |
| * | |
| * // Transform to analyze log batches | |
| * const analysisChannel = Channel.map(logChannel, (logBatch) => { | |
| * const errorCount = logBatch.filter((log) => log.level === "error").length | |
| * const warnCount = logBatch.filter((log) => log.level === "warn").length | |
| * const infoCount = logBatch.filter((log) => log.level === "info").length | |
| * | |
| * const timeRange = { | |
| * start: Math.min(...logBatch.map((log) => log.timestamp)), | |
| * end: Math.max(...logBatch.map((log) => log.timestamp)) | |
| * } | |
| * | |
| * return { | |
| * batchId: `${timeRange.start}-${timeRange.end}`, | |
| * totalEntries: logBatch.length, | |
| * errorCount, | |
| * warnCount, | |
| * infoCount, | |
| * timeRange, | |
| * sources: [...new Set(logBatch.map((log) => log.source))] | |
| * } | |
| * }) | |
| * | |
| * return analysisChannel | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromPubSubArray = <A>(pubsub: PubSub.PubSub<A>): Channel<Arr.NonEmptyReadonlyArray<A>> => | |
| unwrap(Effect.map(PubSub.subscribe(pubsub), fromSubscriptionArray)) | |
| /** | |
| * Subscribes to a `PubSub` of `Take` values and exposes them as a channel. | |
| * | |
| * **Details** | |
| * | |
| * Output `Take` values are emitted as non-empty arrays. Failed `Take` values | |
| * fail the channel. Done `Take` values complete the channel. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromPubSubTake = <A, E, Done>( | |
| pubsub: PubSub.PubSub<Take.Take<A, E, Done>> | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, E, Done> => | |
| unwrap(Effect.map(PubSub.subscribe(pubsub), (sub) => fromEffectTake(PubSub.take(sub)))) | |
| /** | |
| * Creates a Channel from a Schedule. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromSchedule = <O, E, R>( | |
| schedule: Schedule.Schedule<O, unknown, E, R> | |
| ): Channel<O, E, O, unknown, unknown, unknown, R> => | |
| fromPull(Effect.map(Schedule.toStepWithSleep(schedule), (step) => step(void 0))) | |
| /** | |
| * Creates a channel that pulls values from an `AsyncIterable`. | |
| * | |
| * **Details** | |
| * | |
| * Each yielded value is emitted as an output element. The iterator's return | |
| * value becomes the channel's done value. Thrown or rejected iterator errors | |
| * are converted with `onError`. If the channel scope closes early and the | |
| * iterator has a `return` method, that method is called. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromAsyncIterable = <A, D, E>( | |
| iterable: AsyncIterable<A, D>, | |
| onError: (error: unknown) => E | |
| ): Channel<A, E, D> => | |
| fromTransform(Effect.fnUntraced(function*(_, scope) { | |
| const iter = iterable[Symbol.asyncIterator]() | |
| if (iter.return) { | |
| yield* Scope.addFinalizer(scope, Effect.promise(() => iter.return!())) | |
| } | |
| return Effect.flatMap( | |
| Effect.tryPromise({ | |
| try: () => iter.next(), | |
| catch: onError | |
| }), | |
| (result) => result.done ? Cause.done(result.value) : Effect.succeed(result.value) | |
| ) | |
| })) | |
| /** | |
| * Creates a channel from an `AsyncIterable`, emitting each yielded value as a | |
| * single-element non-empty array. | |
| * | |
| * **Details** | |
| * | |
| * The iterator's return value becomes the channel's done value. Thrown or | |
| * rejected iterator errors are converted with `onError`. If the channel scope | |
| * closes early and the iterator has a `return` method, that method is called. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromAsyncIterableArray = <A, D, E>( | |
| iterable: AsyncIterable<A, D>, | |
| onError: (error: unknown) => E | |
| ): Channel<Arr.NonEmptyReadonlyArray<A>, E, D> => map(fromAsyncIterable(iterable, onError), Arr.of) | |
| /** | |
| * Maps the output of this channel using the specified function. | |
| * | |
| * **Example** (Mapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class TransformError extends Data.TaggedError("TransformError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Basic mapping of channel values | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const doubledChannel = Channel.map(numbersChannel, (n) => n * 2) | |
| * // Outputs: 2, 4, 6, 8, 10 | |
| * | |
| * // Transform string data | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "effect"]) | |
| * const upperCaseChannel = Channel.map(wordsChannel, (word) => word.toUpperCase()) | |
| * // Outputs: "HELLO", "WORLD", "EFFECT" | |
| * | |
| * // Complex object transformation | |
| * type User = { id: number; name: string } | |
| * type UserDisplay = { displayName: string; isActive: boolean } | |
| * | |
| * const usersChannel = Channel.fromIterable([ | |
| * { id: 1, name: "Alice" }, | |
| * { id: 2, name: "Bob" } | |
| * ]) | |
| * const displayChannel = Channel.map(usersChannel, (user): UserDisplay => ({ | |
| * displayName: `User: ${user.name}`, | |
| * isActive: true | |
| * })) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const map: { | |
| /** | |
| * Maps the output of this channel using the specified function. | |
| * | |
| * **Example** (Mapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class TransformError extends Data.TaggedError("TransformError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Basic mapping of channel values | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const doubledChannel = Channel.map(numbersChannel, (n) => n * 2) | |
| * // Outputs: 2, 4, 6, 8, 10 | |
| * | |
| * // Transform string data | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "effect"]) | |
| * const upperCaseChannel = Channel.map(wordsChannel, (word) => word.toUpperCase()) | |
| * // Outputs: "HELLO", "WORLD", "EFFECT" | |
| * | |
| * // Complex object transformation | |
| * type User = { id: number; name: string } | |
| * type UserDisplay = { displayName: string; isActive: boolean } | |
| * | |
| * const usersChannel = Channel.fromIterable([ | |
| * { id: 1, name: "Alice" }, | |
| * { id: 2, name: "Bob" } | |
| * ]) | |
| * const displayChannel = Channel.map(usersChannel, (user): UserDisplay => ({ | |
| * displayName: `User: ${user.name}`, | |
| * isActive: true | |
| * })) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutElem2>(f: (o: OutElem, i: number) => OutElem2): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem2, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Maps the output of this channel using the specified function. | |
| * | |
| * **Example** (Mapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class TransformError extends Data.TaggedError("TransformError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Basic mapping of channel values | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const doubledChannel = Channel.map(numbersChannel, (n) => n * 2) | |
| * // Outputs: 2, 4, 6, 8, 10 | |
| * | |
| * // Transform string data | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "effect"]) | |
| * const upperCaseChannel = Channel.map(wordsChannel, (word) => word.toUpperCase()) | |
| * // Outputs: "HELLO", "WORLD", "EFFECT" | |
| * | |
| * // Complex object transformation | |
| * type User = { id: number; name: string } | |
| * type UserDisplay = { displayName: string; isActive: boolean } | |
| * | |
| * const usersChannel = Channel.fromIterable([ | |
| * { id: 1, name: "Alice" }, | |
| * { id: 2, name: "Bob" } | |
| * ]) | |
| * const displayChannel = Channel.map(usersChannel, (user): UserDisplay => ({ | |
| * displayName: `User: ${user.name}`, | |
| * isActive: true | |
| * })) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutElem, i: number) => OutElem2 | |
| ): Channel<OutElem2, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutElem, i: number) => OutElem2 | |
| ): Channel<OutElem2, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| transformPull(self, (pull) => | |
| Effect.sync(() => { | |
| let i = 0 | |
| return Effect.map(pull, (o) => f(o, i++)) | |
| })) | |
| ) | |
| /** | |
| * Maps the done value of this channel using the specified function. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const mapDone: { | |
| /** | |
| * Maps the done value of this channel using the specified function. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutDone2>(f: (o: OutDone) => OutDone2): <OutElem, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone2, InElem, InErr, InDone, Env> | |
| /** | |
| * Maps the done value of this channel using the specified function. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutDone) => OutDone2 | |
| ): Channel<OutElem, OutErr, OutDone2, InElem, InErr, InDone, Env> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutDone) => OutDone2 | |
| ): Channel<OutElem, OutErr, OutDone2, InElem, InErr, InDone, Env> => mapDoneEffect(self, (o) => Effect.succeed(f(o))) | |
| ) | |
| /** | |
| * Maps the done value of this channel using the specified effectful function. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the terminal done value transformation needs services or can fail, | |
| * while emitted elements should pass through unchanged. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const mapDoneEffect: { | |
| /** | |
| * Maps the done value of this channel using the specified effectful function. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the terminal done value transformation needs services or can fail, | |
| * while emitted elements should pass through unchanged. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutDone2, E, R>(f: (o: OutDone) => Effect.Effect<OutDone2, E, R>): <OutElem, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone2, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Maps the done value of this channel using the specified effectful function. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the terminal done value transformation needs services or can fail, | |
| * while emitted elements should pass through unchanged. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutDone) => Effect.Effect<OutDone2, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone2, InElem, InErr, InDone, Env | R> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutDone) => Effect.Effect<OutDone2, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone2, InElem, InErr, InDone, Env | R> => | |
| transformPull(self, (pull) => | |
| Effect.succeed(Pull.catchDone( | |
| pull, | |
| (done) => Effect.flatMap(f(done as OutDone), Cause.done) | |
| ))) | |
| ) | |
| const concurrencyIsSequential = ( | |
| concurrency: number | "unbounded" | undefined | |
| ) => concurrency === undefined || (concurrency !== "unbounded" && concurrency <= 1) | |
| /** | |
| * Maps each output element with an effectful function, preserving the source | |
| * channel's done value. | |
| * | |
| * **When to use** | |
| * | |
| * Use when transforming each channel output needs an Effect, service | |
| * dependency, failure channel, or configured concurrency. | |
| * | |
| * **Details** | |
| * | |
| * The mapping function receives the output element and its zero-based index. | |
| * By default elements are mapped sequentially. Use `options.concurrency` to | |
| * map multiple elements concurrently, and `options.unordered` to allow | |
| * concurrently mapped outputs to be emitted as soon as they complete. | |
| * | |
| * **Example** (Mapping channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class NetworkError extends Data.TaggedError("NetworkError")<{ | |
| * readonly url: string | |
| * }> {} | |
| * | |
| * // Transform values using effectful operations | |
| * const urlsChannel = Channel.fromIterable([ | |
| * "/api/users/1", | |
| * "/api/users/2", | |
| * "/api/users/3" | |
| * ]) | |
| * | |
| * const fetchDataChannel = Channel.mapEffect( | |
| * urlsChannel, | |
| * (url) => | |
| * Effect.tryPromise({ | |
| * try: () => fetch(url).then((res) => res.json()), | |
| * catch: () => new NetworkError({ url }) | |
| * }) | |
| * ) | |
| * | |
| * // Concurrent processing with options | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const processedChannel = Channel.mapEffect( | |
| * numbersChannel, | |
| * (n) => | |
| * Effect.gen(function*() { | |
| * yield* Effect.sleep("100 millis") // Simulate async work | |
| * return n * n | |
| * }), | |
| * { concurrency: 3, unordered: true } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const mapEffect: { | |
| /** | |
| * Maps each output element with an effectful function, preserving the source | |
| * channel's done value. | |
| * | |
| * **When to use** | |
| * | |
| * Use when transforming each channel output needs an Effect, service | |
| * dependency, failure channel, or configured concurrency. | |
| * | |
| * **Details** | |
| * | |
| * The mapping function receives the output element and its zero-based index. | |
| * By default elements are mapped sequentially. Use `options.concurrency` to | |
| * map multiple elements concurrently, and `options.unordered` to allow | |
| * concurrently mapped outputs to be emitted as soon as they complete. | |
| * | |
| * **Example** (Mapping channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class NetworkError extends Data.TaggedError("NetworkError")<{ | |
| * readonly url: string | |
| * }> {} | |
| * | |
| * // Transform values using effectful operations | |
| * const urlsChannel = Channel.fromIterable([ | |
| * "/api/users/1", | |
| * "/api/users/2", | |
| * "/api/users/3" | |
| * ]) | |
| * | |
| * const fetchDataChannel = Channel.mapEffect( | |
| * urlsChannel, | |
| * (url) => | |
| * Effect.tryPromise({ | |
| * try: () => fetch(url).then((res) => res.json()), | |
| * catch: () => new NetworkError({ url }) | |
| * }) | |
| * ) | |
| * | |
| * // Concurrent processing with options | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const processedChannel = Channel.mapEffect( | |
| * numbersChannel, | |
| * (n) => | |
| * Effect.gen(function*() { | |
| * yield* Effect.sleep("100 millis") // Simulate async work | |
| * return n * n | |
| * }), | |
| * { concurrency: 3, unordered: true } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutElem1, OutErr1, Env1>( | |
| f: (d: OutElem, i: number) => Effect.Effect<OutElem1, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly unordered?: boolean | undefined | |
| } | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem1, OutErr1 | OutErr, OutDone, InElem, InErr, InDone, Env1 | Env> | |
| /** | |
| * Maps each output element with an effectful function, preserving the source | |
| * channel's done value. | |
| * | |
| * **When to use** | |
| * | |
| * Use when transforming each channel output needs an Effect, service | |
| * dependency, failure channel, or configured concurrency. | |
| * | |
| * **Details** | |
| * | |
| * The mapping function receives the output element and its zero-based index. | |
| * By default elements are mapped sequentially. Use `options.concurrency` to | |
| * map multiple elements concurrently, and `options.unordered` to allow | |
| * concurrently mapped outputs to be emitted as soon as they complete. | |
| * | |
| * **Example** (Mapping channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class NetworkError extends Data.TaggedError("NetworkError")<{ | |
| * readonly url: string | |
| * }> {} | |
| * | |
| * // Transform values using effectful operations | |
| * const urlsChannel = Channel.fromIterable([ | |
| * "/api/users/1", | |
| * "/api/users/2", | |
| * "/api/users/3" | |
| * ]) | |
| * | |
| * const fetchDataChannel = Channel.mapEffect( | |
| * urlsChannel, | |
| * (url) => | |
| * Effect.tryPromise({ | |
| * try: () => fetch(url).then((res) => res.json()), | |
| * catch: () => new NetworkError({ url }) | |
| * }) | |
| * ) | |
| * | |
| * // Concurrent processing with options | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * const processedChannel = Channel.mapEffect( | |
| * numbersChannel, | |
| * (n) => | |
| * Effect.gen(function*() { | |
| * yield* Effect.sleep("100 millis") // Simulate async work | |
| * return n * n | |
| * }), | |
| * { concurrency: 3, unordered: true } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem1, OutErr1, Env1>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem, i: number) => Effect.Effect<OutElem1, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly unordered?: boolean | undefined | |
| } | |
| ): Channel<OutElem1, OutErr | OutErr1, OutDone, InElem, InErr, InDone, Env | Env1> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem1, OutErr1, Env1>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem, i: number) => Effect.Effect<OutElem1, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly unordered?: boolean | undefined | |
| } | |
| ): Channel<OutElem1, OutErr | OutErr1, OutDone, InElem, InErr, InDone, Env | Env1> => | |
| concurrencyIsSequential(options?.concurrency) | |
| ? mapEffectSequential(self, f) | |
| : mapEffectConcurrent(self, f, options as any) | |
| ) | |
| const mapEffectSequential = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem2, | |
| EX, | |
| RX | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutElem, i: number) => Effect.Effect<OutElem2, EX, RX> | |
| ): Channel<OutElem2, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> => | |
| fromTransform((upstream, scope) => { | |
| let i = 0 | |
| return Effect.map(toTransform(self)(upstream, scope), Effect.flatMap((o) => f(o, i++))) | |
| }) | |
| const mapEffectConcurrent = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem2, | |
| EX, | |
| RX | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (o: OutElem, i: number) => Effect.Effect<OutElem2, EX, RX>, | |
| options: { | |
| readonly concurrency: number | "unbounded" | |
| readonly unordered?: boolean | undefined | |
| } | |
| ): Channel<OutElem2, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> => | |
| fromTransformBracket( | |
| Effect.fnUntraced(function*(upstream, scope, forkedScope) { | |
| let i = 0 | |
| const pull = yield* toTransform(self)(upstream, scope) | |
| const concurrencyN = options.concurrency === "unbounded" | |
| ? Number.MAX_SAFE_INTEGER | |
| : options.concurrency | |
| const queue = yield* Queue.bounded<OutElem2, OutErr | EX | Cause.Done<OutDone>>(0) | |
| yield* Scope.addFinalizer(forkedScope, Queue.shutdown(queue)) | |
| const runFork = Effect.runForkWith(yield* Effect.context<RX>()) | |
| const trackFiber = Fiber.runIn(forkedScope) | |
| if (options.unordered) { | |
| const semaphore = Semaphore.makeUnsafe(concurrencyN) | |
| const release = constant(semaphore.release(1)) | |
| const handle = Effect.matchCauseEffect({ | |
| onFailure: (cause: Cause.Cause<EX>) => Effect.flatMap(Queue.failCause(queue, cause), release), | |
| onSuccess: (value: OutElem2) => Effect.flatMap(Queue.offer(queue, value), release) | |
| }) | |
| yield* semaphore.take(1).pipe( | |
| Effect.flatMap(() => pull), | |
| Effect.flatMap((value) => { | |
| trackFiber(runFork(handle(f(value, i++)))) | |
| return Effect.void | |
| }), | |
| Effect.forever({ disableYield: true }), | |
| Effect.catchCause((cause) => | |
| semaphore.withPermits(concurrencyN - 1)( | |
| Queue.failCause(queue, cause) | |
| ) | |
| ), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| } else { | |
| // capacity is n - 2 because | |
| // - 1 for the offer *after* starting a fiber | |
| // - 1 for the current processing fiber | |
| const effects = yield* Queue.bounded< | |
| Effect.Effect<OutElem2, OutErr | EX | Cause.Done<OutDone>>, | |
| OutErr | EX | Cause.Done<OutDone> | |
| >(concurrencyN - 2) | |
| yield* Scope.addFinalizer(forkedScope, Queue.shutdown(queue)) | |
| yield* Queue.take(effects).pipe( | |
| Effect.flatten, | |
| Effect.flatMap((value) => Queue.offer(queue, value)), | |
| Effect.forever({ disableYield: true }), | |
| Effect.catchCause((cause) => Queue.failCause(queue, cause)), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| let errorCause: Cause.Cause<EX> | undefined | |
| const onExit = (exit: Exit.Exit<OutElem2, EX>) => { | |
| if (exit._tag === "Success") return | |
| errorCause = exit.cause | |
| Queue.failCauseUnsafe(queue, exit.cause) | |
| } | |
| yield* pull.pipe( | |
| Effect.flatMap((value) => { | |
| if (errorCause) return Effect.failCause(errorCause) | |
| const fiber = runFork(f(value, i++)) | |
| trackFiber(fiber) | |
| fiber.addObserver(onExit) | |
| return Queue.offer(effects, Fiber.join(fiber)) | |
| }), | |
| Effect.forever({ disableYield: true }), | |
| Effect.catchCause((cause) => | |
| Queue.offer(effects, Exit.failCause(cause)).pipe( | |
| Effect.andThen(Queue.failCause(effects, cause)) | |
| ) | |
| ), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| } | |
| return Queue.take(queue) | |
| }) | |
| ) | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input channel’s input elements. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const mapInput: { | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input channel’s input elements. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <InElem, InElem2, InErr, R = never>(f: (i: InElem2) => Effect.Effect<InElem, InErr, R>): <OutElem, OutErr, OutDone, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | R> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem2, InErr, InDone, Env> | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input channel’s input elements. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, InElem2, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (i: InElem2) => Effect.Effect<InElem, InErr, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem2, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, InElem2, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (i: InElem2) => Effect.Effect<InElem, InErr, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem2, InErr, InDone, Env | R> => | |
| fromTransform((upstream, scope) => | |
| toTransform(self)( | |
| Effect.flatMap(upstream, (el) => f(el)) as Pull.Pull<InElem, InErr, InDone>, | |
| scope | |
| ) | |
| )) | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input errors. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const mapInputError: { | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input errors. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <InErr, InErr2, R = never>(f: (i: InErr2) => Effect.Effect<InErr, InErr, R>): <OutElem, OutErr, OutDone, InElem, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | R> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr2, InDone, Env> | |
| /** | |
| * Returns a new channel which is the same as this one but applies the given | |
| * function to the input errors. | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, InErr2, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (i: InErr2) => Effect.Effect<InErr, InErr, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr2, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, InErr2, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (i: InErr2) => Effect.Effect<InErr, InErr, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr2, InDone, Env | R> => | |
| fromTransform((upstream, scope) => | |
| toTransform(self)( | |
| Effect.catch(upstream, (err): Pull.Pull<never, InErr, InDone> => { | |
| if (Cause.isDone(err)) return Effect.fail(err) | |
| return Effect.flatMap(f(err), Effect.fail) as Pull.Pull<never, InErr, InDone> | |
| }), | |
| scope | |
| ) | |
| )) | |
| /** | |
| * Applies a side effect function to each output element of the channel, | |
| * returning a new channel that emits the same elements. | |
| * | |
| * **Details** | |
| * | |
| * The `tap` function allows you to perform side effects (like logging or | |
| * debugging) on each element emitted by a channel without modifying the | |
| * elements themselves. | |
| * | |
| * **Example** (Tapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class LogError extends Data.TaggedError("LogError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Tap into each output element to perform side effects | |
| * const tappedChannel = Channel.tap( | |
| * numberChannel, | |
| * (n) => Console.log(`Processing number: ${n}`) | |
| * ) | |
| * | |
| * // The channel still outputs the same elements but logs each one | |
| * // Outputs: 1, 2, 3 (while logging each) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const tap: { | |
| /** | |
| * Applies a side effect function to each output element of the channel, | |
| * returning a new channel that emits the same elements. | |
| * | |
| * **Details** | |
| * | |
| * The `tap` function allows you to perform side effects (like logging or | |
| * debugging) on each element emitted by a channel without modifying the | |
| * elements themselves. | |
| * | |
| * **Example** (Tapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class LogError extends Data.TaggedError("LogError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Tap into each output element to perform side effects | |
| * const tappedChannel = Channel.tap( | |
| * numberChannel, | |
| * (n) => Console.log(`Processing number: ${n}`) | |
| * ) | |
| * | |
| * // The channel still outputs the same elements but logs each one | |
| * // Outputs: 1, 2, 3 (while logging each) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, X, OutErr1, Env1>( | |
| f: (d: Types.NoInfer<OutElem>) => Effect.Effect<X, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| } | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr1 | OutErr, OutDone, InElem, InErr, InDone, Env1 | Env> | |
| /** | |
| * Applies a side effect function to each output element of the channel, | |
| * returning a new channel that emits the same elements. | |
| * | |
| * **Details** | |
| * | |
| * The `tap` function allows you to perform side effects (like logging or | |
| * debugging) on each element emitted by a channel without modifying the | |
| * elements themselves. | |
| * | |
| * **Example** (Tapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class LogError extends Data.TaggedError("LogError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Tap into each output element to perform side effects | |
| * const tappedChannel = Channel.tap( | |
| * numberChannel, | |
| * (n) => Console.log(`Processing number: ${n}`) | |
| * ) | |
| * | |
| * // The channel still outputs the same elements but logs each one | |
| * // Outputs: 1, 2, 3 (while logging each) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, X, OutErr1, Env1>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Types.NoInfer<OutElem>) => Effect.Effect<X, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| } | |
| ): Channel<OutElem, OutErr | OutErr1, OutDone, InElem, InErr, InDone, Env | Env1> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, X, OutErr1, Env1>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Types.NoInfer<OutElem>) => Effect.Effect<X, OutErr1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| } | |
| ): Channel<OutElem, OutErr | OutErr1, OutDone, InElem, InErr, InDone, Env | Env1> => | |
| mapEffect(self, (a) => Effect.as(f(a), a), options) | |
| ) | |
| /** | |
| * Maps each output element to a channel and flattens the child channel | |
| * outputs. | |
| * | |
| * **Details** | |
| * | |
| * The source channel's done value is preserved. Child channel done values are | |
| * used only for child-channel completion. By default child channels are run | |
| * sequentially. Use `options.concurrency` and `options.bufferSize` to run child | |
| * channels concurrently. | |
| * | |
| * **Example** (FlatMapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly cause: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // FlatMap each number to create new channels | |
| * const flatMappedChannel = Channel.flatMap( | |
| * numberChannel, | |
| * (n) => | |
| * Channel.fromIterable(Array.from({ length: n }, (_, i) => `item-${n}-${i}`)) | |
| * ) | |
| * | |
| * // Flattens nested channels into a single stream | |
| * // Outputs: "item-1-0", "item-2-0", "item-2-1", "item-3-0", "item-3-1", "item-3-2" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const flatMap: { | |
| /** | |
| * Maps each output element to a channel and flattens the child channel | |
| * outputs. | |
| * | |
| * **Details** | |
| * | |
| * The source channel's done value is preserved. Child channel done values are | |
| * used only for child-channel completion. By default child channels are run | |
| * sequentially. Use `options.concurrency` and `options.bufferSize` to run child | |
| * channels concurrently. | |
| * | |
| * **Example** (FlatMapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly cause: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // FlatMap each number to create new channels | |
| * const flatMappedChannel = Channel.flatMap( | |
| * numberChannel, | |
| * (n) => | |
| * Channel.fromIterable(Array.from({ length: n }, (_, i) => `item-${n}-${i}`)) | |
| * ) | |
| * | |
| * // Flattens nested channels into a single stream | |
| * // Outputs: "item-1-0", "item-2-0", "item-2-1", "item-3-0", "item-3-1", "item-3-2" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Maps each output element to a channel and flattens the child channel | |
| * outputs. | |
| * | |
| * **Details** | |
| * | |
| * The source channel's done value is preserved. Child channel done values are | |
| * used only for child-channel completion. By default child channels are run | |
| * sequentially. Use `options.concurrency` and `options.bufferSize` to run child | |
| * channels concurrently. | |
| * | |
| * **Example** (FlatMapping channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly cause: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // FlatMap each number to create new channels | |
| * const flatMappedChannel = Channel.flatMap( | |
| * numberChannel, | |
| * (n) => | |
| * Channel.fromIterable(Array.from({ length: n }, (_, i) => `item-${n}-${i}`)) | |
| * ) | |
| * | |
| * // Flattens nested channels into a single stream | |
| * // Outputs: "item-1-0", "item-2-0", "item-2-1", "item-3-0", "item-3-1", "item-3-2" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| concurrencyIsSequential(options?.concurrency) | |
| ? flatMapSequential(self, f) | |
| : flatMapConcurrent(self, f, options as any) | |
| ) | |
| const flatMapSequential = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| fromTransform((upstream, scope) => | |
| Effect.map(toTransform(self)(upstream, scope), (pull) => { | |
| let childPull: Effect.Effect<OutElem1, OutErr1, Env1> | undefined | |
| let childScope: Scope.Closeable | undefined | |
| const makePull: Pull.Pull< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| Env1 | |
| > = Effect.flatMap(pull, (value) => { | |
| childScope ??= Scope.forkUnsafe(scope) | |
| return Effect.flatMapEager(toTransform(f(value))(upstream, childScope), (pull) => { | |
| childPull = catchHalt(pull) as any | |
| return childPull! | |
| }) | |
| }) | |
| const catchHalt = Pull.catchDone((_) => { | |
| childPull = undefined | |
| // we can reuse the scope if the only finalizer is the "fork" one | |
| if (childScope!.state._tag === "Open" && childScope!.state.finalizers.size === 1) { | |
| return makePull | |
| } | |
| const close = Scope.close(childScope!, Exit.void) | |
| childScope = undefined | |
| return Effect.flatMap(close, () => makePull) | |
| }) | |
| return Effect.suspend(() => childPull ?? makePull) | |
| }) | |
| ) | |
| const flatMapConcurrent = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options: { | |
| readonly concurrency: number | "unbounded" | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => self.pipe(map(f), mergeAll(options)) | |
| /** | |
| * Concatenates this channel with another channel created from the terminal value | |
| * of this channel. The new channel is created using the provided function. | |
| * | |
| * **Example** (Concatenating with completion values) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers and terminates with sum | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]).pipe( | |
| * Channel.concatWith((sum: void) => Channel.succeed(`Completed processing`)) | |
| * ) | |
| * | |
| * // Concatenates additional channel based on completion value | |
| * // Outputs: 1, 2, 3, then "Completed processing" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const concatWith: { | |
| /** | |
| * Concatenates this channel with another channel created from the terminal value | |
| * of this channel. The new channel is created using the provided function. | |
| * | |
| * **Example** (Concatenating with completion values) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers and terminates with sum | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]).pipe( | |
| * Channel.concatWith((sum: void) => Channel.succeed(`Completed processing`)) | |
| * ) | |
| * | |
| * // Concatenates additional channel based on completion value | |
| * // Outputs: 1, 2, 3, then "Completed processing" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): <OutElem, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Concatenates this channel with another channel created from the terminal value | |
| * of this channel. The new channel is created using the provided function. | |
| * | |
| * **Example** (Concatenating with completion values) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers and terminates with sum | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]).pipe( | |
| * Channel.concatWith((sum: void) => Channel.succeed(`Completed processing`)) | |
| * ) | |
| * | |
| * // Concatenates additional channel based on completion value | |
| * // Outputs: 1, 2, 3, then "Completed processing" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > => | |
| fromTransform((upstream, scope) => | |
| Effect.sync(() => { | |
| let currentPull: Pull.Pull<OutElem | OutElem1, OutErr1 | OutErr, OutDone1, Env1 | Env> | undefined | |
| const forkedScope = Scope.forkUnsafe(scope) | |
| const makePull = Effect.flatMap(toTransform(self)(upstream, forkedScope), (pull) => { | |
| currentPull = Pull.catchDone(pull, (leftover) => { | |
| return Scope.close(forkedScope, Exit.void).pipe( | |
| Effect.flatMap(() => toTransform(f(leftover as OutDone))(upstream, scope)), | |
| Effect.flatMap((pull) => { | |
| currentPull = pull | |
| return pull | |
| }) | |
| ) | |
| }) | |
| return currentPull | |
| }) | |
| return Effect.suspend(() => currentPull ?? makePull) | |
| }) | |
| )) | |
| /** | |
| * Concatenates this channel with another channel, so that the second channel | |
| * starts emitting values after the first channel has completed. | |
| * | |
| * **Example** (Concatenating channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const firstChannel = Channel.fromIterable([1, 2, 3]) | |
| * const secondChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Concatenate them | |
| * const concatenatedChannel = Channel.concat(firstChannel, secondChannel) | |
| * | |
| * // Outputs: 1, 2, 3, "a", "b", "c" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const concat: { | |
| /** | |
| * Concatenates this channel with another channel, so that the second channel | |
| * starts emitting values after the first channel has completed. | |
| * | |
| * **Example** (Concatenating channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const firstChannel = Channel.fromIterable([1, 2, 3]) | |
| * const secondChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Concatenate them | |
| * const concatenatedChannel = Channel.concat(firstChannel, secondChannel) | |
| * | |
| * // Outputs: 1, 2, 3, "a", "b", "c" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>(that: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Concatenates this channel with another channel, so that the second channel | |
| * starts emitting values after the first channel has completed. | |
| * | |
| * **Example** (Concatenating channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ConcatError extends Data.TaggedError("ConcatError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const firstChannel = Channel.fromIterable([1, 2, 3]) | |
| * const secondChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Concatenate them | |
| * const concatenatedChannel = Channel.concat(firstChannel, secondChannel) | |
| * | |
| * // Outputs: 1, 2, 3, "a", "b", "c" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > => concatWith(self, (_) => that)) | |
| /** | |
| * Combines two channels with a stateful pull function. | |
| * | |
| * **When to use** | |
| * | |
| * Use to coordinate pulling from two channels when each output element depends | |
| * on both sides and local state. | |
| * | |
| * **Details** | |
| * | |
| * The combining function receives the current state and pull functions for the | |
| * left and right channels. It returns the next output element together with the | |
| * next state. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const combine: { | |
| /** | |
| * Combines two channels with a stateful pull function. | |
| * | |
| * **When to use** | |
| * | |
| * Use to coordinate pulling from two channels when each output element depends | |
| * on both sides and local state. | |
| * | |
| * **Details** | |
| * | |
| * The combining function receives the current state and pull functions for the | |
| * left and right channels. It returns the next output element together with the | |
| * next state. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2, S, OutElem, OutErr, OutDone, A, E, R>( | |
| that: Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| s: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| pullLeft: Pull.Pull<OutElem, OutErr, OutDone>, | |
| pullRight: Pull.Pull<OutElem2, OutErr2, OutDone2> | |
| ) => Effect.Effect<readonly [A, S], E, R> | |
| ): <InElem, InErr, InDone, Env>(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| A, | |
| Pull.ExcludeDone<E>, | |
| Cause.Done.Extract<E>, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env | Env2 | R | |
| > | |
| /** | |
| * Combines two channels with a stateful pull function. | |
| * | |
| * **When to use** | |
| * | |
| * Use to coordinate pulling from two channels when each output element depends | |
| * on both sides and local state. | |
| * | |
| * **Details** | |
| * | |
| * The combining function receives the current state and pull functions for the | |
| * left and right channels. It returns the next output element together with the | |
| * next state. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem2, | |
| OutErr2, | |
| OutDone2, | |
| InElem2, | |
| InErr2, | |
| InDone2, | |
| Env2, | |
| S, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| s: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| pullLeft: Pull.Pull<OutElem, OutErr, OutDone>, | |
| pullRight: Pull.Pull<OutElem2, OutErr2, OutDone2> | |
| ) => Effect.Effect<readonly [A, S], E, R> | |
| ): Channel< | |
| A, | |
| Pull.ExcludeDone<E>, | |
| Cause.Done.Extract<E>, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env | Env2 | R | |
| > | |
| } = dual(4, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem2, | |
| OutErr2, | |
| OutDone2, | |
| InElem2, | |
| InErr2, | |
| InDone2, | |
| Env2, | |
| S, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| s: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| pullLeft: Pull.Pull<OutElem, OutErr, OutDone>, | |
| pullRight: Pull.Pull<OutElem2, OutErr2, OutDone2> | |
| ) => Effect.Effect<readonly [A, S], E, R> | |
| ): Channel< | |
| A, | |
| Pull.ExcludeDone<E>, | |
| Cause.Done.Extract<E>, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env | Env2 | R | |
| > => | |
| fromTransform(Effect.fnUntraced(function*(upstream, scope) { | |
| const leftPull = yield* toTransform(self)(upstream, scope) | |
| const rightPull = yield* toTransform(that)(upstream, scope) | |
| let state = s() | |
| return Effect.suspend(() => { | |
| const combinedPull = f(state, leftPull, rightPull) | |
| return Effect.map(combinedPull, ([a, s1]) => { | |
| state = s1 | |
| return a | |
| }) | |
| }) | |
| }))) | |
| /** | |
| * Runs a fallback channel if this channel completes without emitting any | |
| * output elements. | |
| * | |
| * **Details** | |
| * | |
| * If the source emits at least one element, the source is used unchanged. If | |
| * the source completes before emitting an element, the fallback function | |
| * receives the source done value and returns the replacement channel. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const orElseIfEmpty: { | |
| /** | |
| * Runs a fallback channel if this channel completes without emitting any | |
| * output elements. | |
| * | |
| * **Details** | |
| * | |
| * If the source emits at least one element, the source is used unchanged. If | |
| * the source completes before emitting an element, the fallback function | |
| * receives the source done value and returns the replacement channel. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): <OutElem, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Runs a fallback channel if this channel completes without emitting any | |
| * output elements. | |
| * | |
| * **Details** | |
| * | |
| * If the source emits at least one element, the source is used unchanged. If | |
| * the source completes before emitting an element, the fallback function | |
| * receives the source done value and returns the replacement channel. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (leftover: Types.NoInfer<OutDone>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > => | |
| fromTransform((upstream, scope) => | |
| Effect.sync(() => { | |
| let currentPull: Pull.Pull<OutElem | OutElem1, OutErr1 | OutErr, OutDone | OutDone1, Env1 | Env> | undefined | |
| const forkedScope = Scope.forkUnsafe(scope) | |
| const makePull = Effect.flatMap(toTransform(self)(upstream, forkedScope), (pull) => { | |
| const next = pull.pipe( | |
| Effect.tap(() => { | |
| currentPull = pull | |
| return Effect.void | |
| }), | |
| Pull.catchDone((leftover) => | |
| Scope.close(forkedScope, Exit.succeed(leftover)).pipe( | |
| Effect.andThen(toTransform(f(leftover as OutDone))(upstream, scope)), | |
| Effect.flatMap((pull) => { | |
| currentPull = pull | |
| return pull | |
| }) | |
| ) | |
| ) | |
| ) | |
| currentPull = next | |
| return next | |
| }) | |
| return Effect.suspend(() => currentPull ?? makePull) | |
| }) | |
| )) | |
| /** | |
| * Flattens a channel of channels. | |
| * | |
| * **Example** (Flattening nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class FlattenError extends Data.TaggedError("FlattenError")<{ | |
| * readonly cause: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Flatten the nested channels | |
| * const flattenedChannel = Channel.flatten(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const flatten = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| channels: Channel< | |
| Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| > | |
| ): Channel<OutElem, OutErr | OutErr1, OutDone1, InElem & InElem1, InErr & InErr1, InDone & InDone1, Env | Env1> => | |
| flatMap(channels, identity_) | |
| /** | |
| * Flattens a channel that outputs arrays into a channel that outputs individual elements. | |
| * | |
| * **Example** (Flattening arrays of channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class FlattenError extends Data.TaggedError("FlattenError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs arrays | |
| * const arrayChannel = Channel.fromIterable([ | |
| * [1, 2, 3], | |
| * [4, 5], | |
| * [6, 7, 8, 9] | |
| * ]) | |
| * | |
| * // Flatten the arrays into individual elements | |
| * const flattenedChannel = Channel.flattenArray(arrayChannel) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6, 7, 8, 9 | |
| * ``` | |
| * | |
| * @category transforming | |
| * @since 4.0.0 | |
| */ | |
| export const flattenArray = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel<ReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| transformPull(self, (pull) => { | |
| let array: ReadonlyArray<OutElem> | undefined | |
| let index = 0 | |
| const pump = Effect.suspend(function loop(): Pull.Pull<OutElem, OutErr, OutDone> { | |
| if (array === undefined) { | |
| return Effect.flatMap(pull, (array_) => { | |
| switch (array_.length) { | |
| case 0: | |
| return loop() | |
| case 1: | |
| return Effect.succeed(array_[0]) | |
| default: { | |
| array = array_ | |
| return Effect.succeed(array_[index++]) | |
| } | |
| } | |
| }) | |
| } | |
| const next = array[index++] | |
| if (index >= array.length) { | |
| array = undefined | |
| index = 0 | |
| } | |
| return Effect.succeed(next) | |
| }) | |
| return Effect.succeed(pump) | |
| }) | |
| /** | |
| * Flattens a channel that emits `Take` values into a channel that emits the | |
| * `Take` outputs directly. | |
| * | |
| * **Details** | |
| * | |
| * Output `Take` values are emitted as non-empty arrays. Failed `Take` values | |
| * fail the returned channel. Done `Take` values complete the returned channel. | |
| * | |
| * @category transforming | |
| * @since 4.0.0 | |
| */ | |
| export const flattenTake = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| OutErr2, | |
| OutDone2, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel<Take.Take<OutElem, OutErr, OutDone>, OutErr2, OutDone2, InElem, InErr, InDone, Env> | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr | OutErr2, OutDone, InElem, InErr, InDone, Env> => | |
| mapEffectSequential(self, Take.toPull) as any | |
| /** | |
| * Creates a new channel that consumes all output from the source channel | |
| * but emits nothing, preserving only the completion value. | |
| * | |
| * **Example** (Draining channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel that outputs values | |
| * const sourceChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Drain all output, keeping only the completion | |
| * const drainedChannel = Channel.drain(sourceChannel) | |
| * | |
| * // The channel completes but emits no values | |
| * // Useful for consuming side effects without collecting output | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const drain = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel< | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| ): Channel<never, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| transformPull(self, (pull) => Effect.succeed(Effect.forever(pull, { disableYield: true }))) | |
| /** | |
| * Repeats this channel according to the provided schedule. | |
| * | |
| * @category repetition | |
| * @since 4.0.0 | |
| */ | |
| export const repeat: { | |
| /** | |
| * Repeats this channel according to the provided schedule. | |
| * | |
| * @category repetition | |
| * @since 4.0.0 | |
| */ | |
| <SO, OutDone, SE, SR>( | |
| schedule: | |
| | Schedule.Schedule<SO, Types.NoInfer<OutDone>, SE, SR> | |
| | (( | |
| $: <SO, SE, SR>(_: Schedule.Schedule<SO, NoInfer<OutDone>, SE, SR>) => Schedule.Schedule<SO, OutDone, SE, SR> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutDone>, SE, SR>) | |
| ): <OutElem, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| ) => Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| /** | |
| * Repeats this channel according to the provided schedule. | |
| * | |
| * @category repetition | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: | |
| | Schedule.Schedule<SO, OutDone, SE, SR> | |
| | (( | |
| $: <SO, SE, SR>(_: Schedule.Schedule<SO, NoInfer<OutDone>, SE, SR>) => Schedule.Schedule<SO, OutDone, SE, SR> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutDone>, SE, SR>) | |
| ): Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: | |
| | Schedule.Schedule<SO, OutDone, SE, SR> | |
| | (( | |
| $: <SO, SE, SR>(_: Schedule.Schedule<SO, NoInfer<OutDone>, SE, SR>) => Schedule.Schedule<SO, OutDone, SE, SR> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutDone>, SE, SR>) | |
| ): Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> => | |
| Schedule.toStepWithMetadata(typeof schedule === "function" ? schedule(identity_) : schedule).pipe( | |
| Effect.map((step) => { | |
| let meta = Schedule.CurrentMetadata.defaultValue() | |
| const loop: Channel< | |
| OutElem, | |
| OutErr | SE, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | SR | |
| > = concatWith( | |
| provideServiceEffect(self, Schedule.CurrentMetadata, Effect.sync(() => meta)), | |
| (done) => | |
| step(done).pipe( | |
| Effect.map((meta_) => { | |
| meta = meta_ | |
| return loop | |
| }), | |
| Pull.catchDone(() => Effect.succeed(end(done))), | |
| unwrap | |
| ) | |
| ) | |
| return loop | |
| }), | |
| unwrap | |
| )) | |
| /** | |
| * Repeats this channel forever. | |
| * | |
| * @category repetition | |
| * @since 4.0.0 | |
| */ | |
| export const forever = <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): Channel<OutElem, OutErr, never, InElem, InErr, InDone, Env> => concatWith(self, () => forever(self)) | |
| /** | |
| * Runs a schedule step for each output element while preserving the emitted | |
| * elements. | |
| * | |
| * **Details** | |
| * | |
| * The schedule receives each output element as input. Schedule delays are | |
| * applied between emitted elements. If the schedule fails, the returned channel | |
| * fails. If the schedule finishes, the returned channel completes with the | |
| * schedule output. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const schedule: { | |
| /** | |
| * Runs a schedule step for each output element while preserving the emitted | |
| * elements. | |
| * | |
| * **Details** | |
| * | |
| * The schedule receives each output element as input. Schedule delays are | |
| * applied between emitted elements. If the schedule fails, the returned channel | |
| * fails. If the schedule finishes, the returned channel completes with the | |
| * schedule output. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <SO, OutElem, SE, SR>(schedule: Schedule.Schedule<SO, Types.NoInfer<OutElem>, SE, SR>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| ) => Channel<OutElem, OutErr | SE, OutDone | SO, InElem, InErr, InDone, Env | SR> | |
| /** | |
| * Runs a schedule step for each output element while preserving the emitted | |
| * elements. | |
| * | |
| * **Details** | |
| * | |
| * The schedule receives each output element as input. Schedule delays are | |
| * applied between emitted elements. If the schedule fails, the returned channel | |
| * fails. If the schedule finishes, the returned channel completes with the | |
| * schedule output. | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: Schedule.Schedule<SO, OutElem, SE, SR> | |
| ): Channel<OutElem, OutErr | SE, OutDone | SO, InElem, InErr, InDone, Env | SR> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: Schedule.Schedule<SO, OutElem, SE, SR> | |
| ): Channel<OutElem, OutErr | SE, OutDone | SO, InElem, InErr, InDone, Env | SR> => | |
| transformPull( | |
| self, | |
| (pull, _scope) => | |
| Effect.map( | |
| Schedule.toStepWithSleep(schedule), | |
| (step) => { | |
| const pullWithStep: Pull.Pull< | |
| OutElem, | |
| OutErr | SE, | |
| OutDone | SO, | |
| SR | |
| > = Effect.tap(pull, step) | |
| return pullWithStep | |
| } | |
| ) | |
| )) | |
| /** | |
| * Filters the output elements of a channel using a predicate function. | |
| * Elements that don't match the predicate are discarded. | |
| * | |
| * **Example** (Filtering channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with mixed numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5, 6, 7, 8]) | |
| * | |
| * // Filter to keep only even numbers | |
| * const evenChannel = Channel.filter(numbersChannel, (n) => n % 2 === 0) | |
| * // Outputs: 2, 4, 6, 8 | |
| * | |
| * // Filter with type refinement | |
| * const mixedChannel = Channel.fromIterable([1, "hello", 2, "world", 3]) | |
| * const numbersOnlyChannel = Channel.filter( | |
| * mixedChannel, | |
| * (value): value is number => typeof value === "number" | |
| * ) | |
| * // Outputs: 1, 2, 3 (all typed as numbers) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filter: { | |
| /** | |
| * Filters the output elements of a channel using a predicate function. | |
| * Elements that don't match the predicate are discarded. | |
| * | |
| * **Example** (Filtering channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with mixed numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5, 6, 7, 8]) | |
| * | |
| * // Filter to keep only even numbers | |
| * const evenChannel = Channel.filter(numbersChannel, (n) => n % 2 === 0) | |
| * // Outputs: 2, 4, 6, 8 | |
| * | |
| * // Filter with type refinement | |
| * const mixedChannel = Channel.fromIterable([1, "hello", 2, "world", 3]) | |
| * const numbersOnlyChannel = Channel.filter( | |
| * mixedChannel, | |
| * (value): value is number => typeof value === "number" | |
| * ) | |
| * // Outputs: 1, 2, 3 (all typed as numbers) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B extends OutElem>(refinement: Predicate.Refinement<OutElem, B>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<B, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters the output elements of a channel using a predicate function. | |
| * Elements that don't match the predicate are discarded. | |
| * | |
| * **Example** (Filtering channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with mixed numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5, 6, 7, 8]) | |
| * | |
| * // Filter to keep only even numbers | |
| * const evenChannel = Channel.filter(numbersChannel, (n) => n % 2 === 0) | |
| * // Outputs: 2, 4, 6, 8 | |
| * | |
| * // Filter with type refinement | |
| * const mixedChannel = Channel.fromIterable([1, "hello", 2, "world", 3]) | |
| * const numbersOnlyChannel = Channel.filter( | |
| * mixedChannel, | |
| * (value): value is number => typeof value === "number" | |
| * ) | |
| * // Outputs: 1, 2, 3 (all typed as numbers) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem>(predicate: Predicate.Predicate<OutElem>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters the output elements of a channel using a predicate function. | |
| * Elements that don't match the predicate are discarded. | |
| * | |
| * **Example** (Filtering channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with mixed numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5, 6, 7, 8]) | |
| * | |
| * // Filter to keep only even numbers | |
| * const evenChannel = Channel.filter(numbersChannel, (n) => n % 2 === 0) | |
| * // Outputs: 2, 4, 6, 8 | |
| * | |
| * // Filter with type refinement | |
| * const mixedChannel = Channel.fromIterable([1, "hello", 2, "world", 3]) | |
| * const numbersOnlyChannel = Channel.filter( | |
| * mixedChannel, | |
| * (value): value is number => typeof value === "number" | |
| * ) | |
| * // Outputs: 1, 2, 3 (all typed as numbers) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B extends OutElem>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| refinement: Predicate.Refinement<OutElem, B> | |
| ): Channel<B, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters the output elements of a channel using a predicate function. | |
| * Elements that don't match the predicate are discarded. | |
| * | |
| * **Example** (Filtering channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with mixed numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5, 6, 7, 8]) | |
| * | |
| * // Filter to keep only even numbers | |
| * const evenChannel = Channel.filter(numbersChannel, (n) => n % 2 === 0) | |
| * // Outputs: 2, 4, 6, 8 | |
| * | |
| * // Filter with type refinement | |
| * const mixedChannel = Channel.fromIterable([1, "hello", 2, "world", 3]) | |
| * const numbersOnlyChannel = Channel.filter( | |
| * mixedChannel, | |
| * (value): value is number => typeof value === "number" | |
| * ) | |
| * // Outputs: 1, 2, 3 (all typed as numbers) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<OutElem> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<OutElem> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| toTransform(self)(upstream, scope), | |
| (pull) => | |
| Effect.flatMap(pull, function loop(elem): Pull.Pull<OutElem, OutErr, OutDone> { | |
| return predicate(elem) | |
| ? Effect.succeed(elem) | |
| : Effect.flatMap(pull, loop) | |
| }) | |
| ) | |
| )) | |
| /** | |
| * Filters and maps output elements using a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to keep only channel output elements accepted by a `Filter` and emit | |
| * each filter success value. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. The source channel's errors and done value are | |
| * preserved. | |
| * | |
| * @see {@link filter} for keeping original output elements with a predicate | |
| * @see {@link filterMapEffect} for using an effectful `Filter` | |
| * @see {@link filterMapArray} for filtering arrays of output elements | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterMap: { | |
| /** | |
| * Filters and maps output elements using a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to keep only channel output elements accepted by a `Filter` and emit | |
| * each filter success value. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. The source channel's errors and done value are | |
| * preserved. | |
| * | |
| * @see {@link filter} for keeping original output elements with a predicate | |
| * @see {@link filterMapEffect} for using an effectful `Filter` | |
| * @see {@link filterMapArray} for filtering arrays of output elements | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B, X>(filter: Filter.Filter<OutElem, B, X>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<B, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters and maps output elements using a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to keep only channel output elements accepted by a `Filter` and emit | |
| * each filter success value. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. The source channel's errors and done value are | |
| * preserved. | |
| * | |
| * @see {@link filter} for keeping original output elements with a predicate | |
| * @see {@link filterMapEffect} for using an effectful `Filter` | |
| * @see {@link filterMapArray} for filtering arrays of output elements | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutElem, B, X> | |
| ): Channel<B, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutElem, B, X> | |
| ): Channel<B, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| toTransform(self)(upstream, scope), | |
| (pull) => | |
| Effect.flatMap(pull, function loop(elem): Pull.Pull<B, OutErr, OutDone> { | |
| const result = filter(elem) | |
| return Result.isFailure(result) | |
| ? Effect.flatMap(pull, loop) | |
| : Effect.succeed(result.success) | |
| }) | |
| ) | |
| )) | |
| /** | |
| * Filters output elements with an effectful predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the keep/discard decision depends on an Effect or service and | |
| * predicate failures should fail the returned channel. | |
| * | |
| * **Details** | |
| * | |
| * Elements for which the predicate succeeds with `true` are emitted. Elements | |
| * for which the predicate succeeds with `false` are discarded. Predicate | |
| * failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterEffect: { | |
| /** | |
| * Filters output elements with an effectful predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the keep/discard decision depends on an Effect or service and | |
| * predicate failures should fail the returned channel. | |
| * | |
| * **Details** | |
| * | |
| * Elements for which the predicate succeeds with `true` are emitted. Elements | |
| * for which the predicate succeeds with `false` are discarded. Predicate | |
| * failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, E, R>(predicate: (a: OutElem) => Effect.Effect<boolean, E, R>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Filters output elements with an effectful predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the keep/discard decision depends on an Effect or service and | |
| * predicate failures should fail the returned channel. | |
| * | |
| * **Details** | |
| * | |
| * Elements for which the predicate succeeds with `true` are emitted. Elements | |
| * for which the predicate succeeds with `false` are discarded. Predicate | |
| * failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: (a: OutElem) => Effect.Effect<boolean, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: (a: OutElem) => Effect.Effect<boolean, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| toTransform(self)(upstream, scope), | |
| (pull) => | |
| Effect.flatMap(pull, function loop(elem): Pull.Pull<OutElem, OutErr | E, OutDone, R> { | |
| return Effect.flatMap( | |
| predicate(elem), | |
| (passes) => | |
| passes | |
| ? Effect.succeed(elem) | |
| : Effect.flatMap(pull, loop) | |
| ) | |
| }) | |
| ) | |
| )) | |
| /** | |
| * Filters and maps output elements using an effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to apply effectful logic that can discard channel output elements and | |
| * emit transformed values for the elements that pass. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. Failures from the effectful filter fail the returned | |
| * channel. | |
| * | |
| * @see {@link filterMap} for using a synchronous `Filter` | |
| * @see {@link filterEffect} for effectfully keeping original output elements | |
| * @see {@link mapEffect} for effectfully transforming every output element | |
| * @see {@link filterMapArrayEffect} for effectful filtering of array outputs | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterMapEffect: { | |
| /** | |
| * Filters and maps output elements using an effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to apply effectful logic that can discard channel output elements and | |
| * emit transformed values for the elements that pass. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. Failures from the effectful filter fail the returned | |
| * channel. | |
| * | |
| * @see {@link filterMap} for using a synchronous `Filter` | |
| * @see {@link filterEffect} for effectfully keeping original output elements | |
| * @see {@link mapEffect} for effectfully transforming every output element | |
| * @see {@link filterMapArrayEffect} for effectful filtering of array outputs | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B, X, EX, RX>(filter: Filter.FilterEffect<OutElem, B, X, EX, RX>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<B, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> | |
| /** | |
| * Filters and maps output elements using an effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to apply effectful logic that can discard channel output elements and | |
| * emit transformed values for the elements that pass. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are emitted as mapped values. Failed filter | |
| * results are discarded. Failures from the effectful filter fail the returned | |
| * channel. | |
| * | |
| * @see {@link filterMap} for using a synchronous `Filter` | |
| * @see {@link filterEffect} for effectfully keeping original output elements | |
| * @see {@link mapEffect} for effectfully transforming every output element | |
| * @see {@link filterMapArrayEffect} for effectful filtering of array outputs | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.FilterEffect<OutElem, B, X, EX, RX> | |
| ): Channel<B, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.FilterEffect<OutElem, B, X, EX, RX> | |
| ): Channel<B, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| toTransform(self)(upstream, scope), | |
| (pull) => | |
| Effect.flatMap(pull, function loop(elem): Pull.Pull<B, OutErr | EX, OutDone, RX> { | |
| return Effect.flatMap( | |
| filter(elem), | |
| (result) => | |
| Result.isFailure(result) | |
| ? Effect.flatMap(pull, loop) | |
| : Effect.succeed(result.success) | |
| ) | |
| }) | |
| ) | |
| )) | |
| /** | |
| * Filters arrays of elements emitted by a channel, applying the filter | |
| * to each element within the arrays and only emitting non-empty filtered arrays. | |
| * | |
| * **Example** (Filtering array output) | |
| * | |
| * ```ts | |
| * import { Array, Channel } from "effect" | |
| * | |
| * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty | |
| * | |
| * // Create a channel that outputs arrays of mixed data | |
| * const arrayChannel = Channel.fromIterable([ | |
| * Array.make(1, 2, 3, 4, 5), | |
| * Array.make(6, 7, 8, 9, 10), | |
| * Array.make(11, 12, 13, 14, 15) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * | |
| * // Filter arrays to keep only even numbers | |
| * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4], [6, 8, 10], [12, 14] | |
| * // Note: Only non-empty filtered arrays are emitted | |
| * | |
| * // Arrays that would become empty after filtering are discarded entirely | |
| * const oddChannel = Channel.fromIterable([ | |
| * Array.make(1, 3, 5), | |
| * Array.make(2, 4), | |
| * Array.make(7, 9) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterArray: { | |
| /** | |
| * Filters arrays of elements emitted by a channel, applying the filter | |
| * to each element within the arrays and only emitting non-empty filtered arrays. | |
| * | |
| * **Example** (Filtering array output) | |
| * | |
| * ```ts | |
| * import { Array, Channel } from "effect" | |
| * | |
| * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty | |
| * | |
| * // Create a channel that outputs arrays of mixed data | |
| * const arrayChannel = Channel.fromIterable([ | |
| * Array.make(1, 2, 3, 4, 5), | |
| * Array.make(6, 7, 8, 9, 10), | |
| * Array.make(11, 12, 13, 14, 15) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * | |
| * // Filter arrays to keep only even numbers | |
| * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4], [6, 8, 10], [12, 14] | |
| * // Note: Only non-empty filtered arrays are emitted | |
| * | |
| * // Arrays that would become empty after filtering are discarded entirely | |
| * const oddChannel = Channel.fromIterable([ | |
| * Array.make(1, 3, 5), | |
| * Array.make(2, 4), | |
| * Array.make(7, 9) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B extends OutElem>(refinement: Predicate.Refinement<OutElem, B>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters arrays of elements emitted by a channel, applying the filter | |
| * to each element within the arrays and only emitting non-empty filtered arrays. | |
| * | |
| * **Example** (Filtering array output) | |
| * | |
| * ```ts | |
| * import { Array, Channel } from "effect" | |
| * | |
| * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty | |
| * | |
| * // Create a channel that outputs arrays of mixed data | |
| * const arrayChannel = Channel.fromIterable([ | |
| * Array.make(1, 2, 3, 4, 5), | |
| * Array.make(6, 7, 8, 9, 10), | |
| * Array.make(11, 12, 13, 14, 15) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * | |
| * // Filter arrays to keep only even numbers | |
| * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4], [6, 8, 10], [12, 14] | |
| * // Note: Only non-empty filtered arrays are emitted | |
| * | |
| * // Arrays that would become empty after filtering are discarded entirely | |
| * const oddChannel = Channel.fromIterable([ | |
| * Array.make(1, 3, 5), | |
| * Array.make(2, 4), | |
| * Array.make(7, 9) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem>(predicate: Predicate.Predicate<Types.NoInfer<OutElem>>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters arrays of elements emitted by a channel, applying the filter | |
| * to each element within the arrays and only emitting non-empty filtered arrays. | |
| * | |
| * **Example** (Filtering array output) | |
| * | |
| * ```ts | |
| * import { Array, Channel } from "effect" | |
| * | |
| * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty | |
| * | |
| * // Create a channel that outputs arrays of mixed data | |
| * const arrayChannel = Channel.fromIterable([ | |
| * Array.make(1, 2, 3, 4, 5), | |
| * Array.make(6, 7, 8, 9, 10), | |
| * Array.make(11, 12, 13, 14, 15) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * | |
| * // Filter arrays to keep only even numbers | |
| * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4], [6, 8, 10], [12, 14] | |
| * // Note: Only non-empty filtered arrays are emitted | |
| * | |
| * // Arrays that would become empty after filtering are discarded entirely | |
| * const oddChannel = Channel.fromIterable([ | |
| * Array.make(1, 3, 5), | |
| * Array.make(2, 4), | |
| * Array.make(7, 9) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B extends OutElem>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| refinement: Predicate.Refinement<OutElem, B> | |
| ): Channel<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters arrays of elements emitted by a channel, applying the filter | |
| * to each element within the arrays and only emitting non-empty filtered arrays. | |
| * | |
| * **Example** (Filtering array output) | |
| * | |
| * ```ts | |
| * import { Array, Channel } from "effect" | |
| * | |
| * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty | |
| * | |
| * // Create a channel that outputs arrays of mixed data | |
| * const arrayChannel = Channel.fromIterable([ | |
| * Array.make(1, 2, 3, 4, 5), | |
| * Array.make(6, 7, 8, 9, 10), | |
| * Array.make(11, 12, 13, 14, 15) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * | |
| * // Filter arrays to keep only even numbers | |
| * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4], [6, 8, 10], [12, 14] | |
| * // Note: Only non-empty filtered arrays are emitted | |
| * | |
| * // Arrays that would become empty after filtering are discarded entirely | |
| * const oddChannel = Channel.fromIterable([ | |
| * Array.make(1, 3, 5), | |
| * Array.make(2, 4), | |
| * Array.make(7, 9) | |
| * ]).pipe(Channel.filter(nonEmptyArrayPredicate)) | |
| * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0) | |
| * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded) | |
| * ``` | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<Types.NoInfer<OutElem>> | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<Types.NoInfer<OutElem>> | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| transformPull(self, (pull) => | |
| Effect.succeed(Effect.flatMap( | |
| pull, | |
| function loop(arr): Pull.Pull<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone> { | |
| const passes: Array<OutElem> = [] | |
| for (let i = 0; i < arr.length; i++) { | |
| if (predicate(arr[i] as Types.NoInfer<OutElem>)) { | |
| passes.push(arr[i]) | |
| } | |
| } | |
| return Arr.isReadonlyArrayNonEmpty(passes) | |
| ? Effect.succeed(passes) | |
| : Effect.flatMap(pull, loop) | |
| } | |
| )))) | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using a | |
| * `Filter`. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterMapArray: { | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using a | |
| * `Filter`. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B, X>(filter: Filter.Filter<Types.NoInfer<OutElem>, B, X>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using a | |
| * `Filter`. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutElem, B, X> | |
| ): Channel<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutElem, B, X> | |
| ): Channel<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| transformPull(self, (pull) => | |
| Effect.succeed(Effect.flatMap( | |
| pull, | |
| function loop(arr): Pull.Pull<Arr.NonEmptyReadonlyArray<B>, OutErr, OutDone> { | |
| const passes: Array<B> = [] | |
| for (let i = 0; i < arr.length; i++) { | |
| const result = filter(arr[i]) | |
| if (Result.isSuccess(result)) { | |
| passes.push(result.success) | |
| } | |
| } | |
| return Arr.isReadonlyArrayNonEmpty(passes) | |
| ? Effect.succeed(passes) | |
| : Effect.flatMap(pull, loop) | |
| } | |
| )))) | |
| /** | |
| * Filters each element inside emitted non-empty arrays with an effectful | |
| * predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when filtering array-valued channel outputs requires Effects or services, | |
| * and arrays that become empty should be skipped. | |
| * | |
| * **Details** | |
| * | |
| * The predicate receives the element and its index within the array. Elements | |
| * for which the predicate succeeds with `true` are kept. Arrays that become | |
| * empty are discarded. Predicate failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterArrayEffect: { | |
| /** | |
| * Filters each element inside emitted non-empty arrays with an effectful | |
| * predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when filtering array-valued channel outputs requires Effects or services, | |
| * and arrays that become empty should be skipped. | |
| * | |
| * **Details** | |
| * | |
| * The predicate receives the element and its index within the array. Elements | |
| * for which the predicate succeeds with `true` are kept. Arrays that become | |
| * empty are discarded. Predicate failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, E, R>( | |
| predicate: (a: Types.NoInfer<OutElem>, index: number) => Effect.Effect<boolean, E, R> | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Filters each element inside emitted non-empty arrays with an effectful | |
| * predicate. | |
| * | |
| * **When to use** | |
| * | |
| * Use when filtering array-valued channel outputs requires Effects or services, | |
| * and arrays that become empty should be skipped. | |
| * | |
| * **Details** | |
| * | |
| * The predicate receives the element and its index within the array. Elements | |
| * for which the predicate succeeds with `true` are kept. Arrays that become | |
| * empty are discarded. Predicate failures fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, E, R>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: (a: Types.NoInfer<OutElem>, index: number) => Effect.Effect<boolean, E, R> | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, E, R>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: (a: Types.NoInfer<OutElem>, index: number) => Effect.Effect<boolean, E, R> | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| transformPull(self, (pull) => { | |
| const f = Effect.flatMap(pull, (arr) => Effect.filter(arr, predicate)) | |
| return Effect.succeed(Effect.flatMap( | |
| f, | |
| function loop(arr): Pull.Pull<Arr.NonEmptyReadonlyArray<OutElem>, OutErr | E, OutDone, R> { | |
| return Arr.isReadonlyArrayNonEmpty(arr) ? Effect.succeed(arr) : Effect.flatMap(f, loop) | |
| } | |
| )) | |
| })) | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using an | |
| * effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when array-valued channel outputs need an effectful filter-map that can | |
| * fail and can discard arrays that become empty. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. Failures | |
| * from the effectful filter fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| export const filterMapArrayEffect: { | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using an | |
| * effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when array-valued channel outputs need an effectful filter-map that can | |
| * fail and can discard arrays that become empty. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. Failures | |
| * from the effectful filter fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, B, X, EX, RX>(filter: Filter.FilterEffect<Types.NoInfer<OutElem>, B, X, EX, RX>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<B>, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> | |
| /** | |
| * Filters and maps each element inside emitted non-empty arrays using an | |
| * effectful `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when array-valued channel outputs need an effectful filter-map that can | |
| * fail and can discard arrays that become empty. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are kept as mapped values. Failed filter results | |
| * are removed from the array. Arrays that become empty are discarded. Failures | |
| * from the effectful filter fail the returned channel. | |
| * | |
| * @category filtering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X, EX, RX>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.FilterEffect<OutElem, B, X, EX, RX> | |
| ): Channel<Arr.NonEmptyReadonlyArray<B>, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, B, X, EX, RX>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.FilterEffect<OutElem, B, X, EX, RX> | |
| ): Channel<Arr.NonEmptyReadonlyArray<B>, OutErr | EX, OutDone, InElem, InErr, InDone, Env | RX> => | |
| transformPull(self, (pull) => | |
| Effect.succeed(Effect.flatMap( | |
| pull, | |
| function loop(arr): Pull.Pull<Arr.NonEmptyReadonlyArray<B>, OutErr | EX, OutDone, RX> { | |
| return Effect.flatMap( | |
| Effect.filterMapEffect(arr, filter as any), | |
| (passes) => | |
| Arr.isReadonlyArrayNonEmpty(passes) | |
| ? Effect.succeed(passes as Arr.NonEmptyReadonlyArray<B>) | |
| : Effect.flatMap(pull, loop) | |
| ) | |
| } | |
| )))) | |
| /** | |
| * Maps over a channel statefully with an accumulator, where each element can produce multiple output values. | |
| * | |
| * **Example** (Mapping with accumulated state) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Use mapAccum to create running sums and emit both current and sum | |
| * const runningSum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => 0, // initial accumulator state | |
| * (sum, current) => { | |
| * const newSum = sum + current | |
| * // Return [newState, outputValues] | |
| * return [newSum, [current, newSum]] as const | |
| * } | |
| * ) | |
| * // Outputs: 1, 1, 2, 3, 3, 6, 4, 10 | |
| * | |
| * // Using with Effect for async processing | |
| * const asyncMapAccum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * const newAcc = acc + value.toString() | |
| * return [newAcc, [`${value}-processed`, newAcc]] as const | |
| * }) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const mapAccum: { | |
| /** | |
| * Maps over a channel statefully with an accumulator, where each element can produce multiple output values. | |
| * | |
| * **Example** (Mapping with accumulated state) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Use mapAccum to create running sums and emit both current and sum | |
| * const runningSum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => 0, // initial accumulator state | |
| * (sum, current) => { | |
| * const newSum = sum + current | |
| * // Return [newState, outputValues] | |
| * return [newSum, [current, newSum]] as const | |
| * } | |
| * ) | |
| * // Outputs: 1, 1, 2, 3, 3, 6, 4, 10 | |
| * | |
| * // Using with Effect for async processing | |
| * const asyncMapAccum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * const newAcc = acc + value.toString() | |
| * return [newAcc, [`${value}-processed`, newAcc]] as const | |
| * }) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <S, OutElem, B, E = never, R = never>( | |
| initial: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| a: Types.NoInfer<OutElem> | |
| ) => | |
| | Effect.Effect<readonly [state: S, values: ReadonlyArray<B>], E, R> | |
| | readonly [state: S, values: ReadonlyArray<B>], | |
| options?: { | |
| readonly onHalt?: ((state: S) => Array<B>) | undefined | |
| } | |
| ): < | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| B, | |
| OutErr | E, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| /** | |
| * Maps over a channel statefully with an accumulator, where each element can produce multiple output values. | |
| * | |
| * **Example** (Mapping with accumulated state) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Use mapAccum to create running sums and emit both current and sum | |
| * const runningSum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => 0, // initial accumulator state | |
| * (sum, current) => { | |
| * const newSum = sum + current | |
| * // Return [newState, outputValues] | |
| * return [newSum, [current, newSum]] as const | |
| * } | |
| * ) | |
| * // Outputs: 1, 1, 2, 3, 3, 6, 4, 10 | |
| * | |
| * // Using with Effect for async processing | |
| * const asyncMapAccum = Channel.mapAccum( | |
| * numbersChannel, | |
| * () => "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * const newAcc = acc + value.toString() | |
| * return [newAcc, [`${value}-processed`, newAcc]] as const | |
| * }) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, B, E = never, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| a: Types.NoInfer<OutElem> | |
| ) => | |
| | Effect.Effect<readonly [state: S, values: ReadonlyArray<B>], E, R> | |
| | readonly [state: S, values: ReadonlyArray<B>], | |
| options?: { | |
| readonly onHalt?: ((state: S) => Array<B>) | undefined | |
| } | |
| ): Channel<B, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, B, E = never, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: LazyArg<S>, | |
| f: ( | |
| s: S, | |
| a: Types.NoInfer<OutElem> | |
| ) => | |
| | Effect.Effect<readonly [state: S, values: ReadonlyArray<B>], E, R> | |
| | readonly [state: S, values: ReadonlyArray<B>], | |
| options?: { | |
| readonly onHalt?: ((state: S) => ReadonlyArray<B>) | undefined | |
| } | |
| ): Channel<B, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| fromTransform((upstream, scope) => | |
| Effect.map(toTransform(self)(upstream, scope), (pull) => { | |
| let state = initial() | |
| let current: ReadonlyArray<B> | undefined | |
| let index = 0 | |
| let cause: Cause.Cause<OutErr | Cause.Done<OutDone>> | undefined | |
| const pullNext = Effect.matchCauseEffect(pull, { | |
| onFailure(cause_) { | |
| cause = cause_ | |
| const b = options?.onHalt && options.onHalt(state) | |
| return b && b.length > 0 | |
| ? Effect.succeed([state, b] as const) | |
| : Effect.failCause(cause_) | |
| }, | |
| onSuccess(a): Effect.Effect<readonly [state: S, values: ReadonlyArray<B>], E, R> { | |
| const b = f(state, a) | |
| return Arr.isArray(b) | |
| ? Effect.succeed(b as any) | |
| : b as any | |
| } | |
| }) | |
| const pump = Effect.suspend(function loop(): Pull.Pull<B, OutErr | E, OutDone, R> { | |
| if (current === undefined) { | |
| if (cause) return Effect.failCause(cause) | |
| return Effect.flatMap(pullNext, ([newState, values]) => { | |
| state = newState | |
| if (values.length === 0) { | |
| return loop() | |
| } else if (values.length === 1) { | |
| return Effect.succeed(values[0]) | |
| } | |
| current = values | |
| return loop() | |
| }) | |
| } | |
| const next = current[index++] | |
| if (index >= current.length) { | |
| current = undefined | |
| index = 0 | |
| } | |
| return Effect.succeed(next) | |
| }) | |
| return pump | |
| }) | |
| ) | |
| ) | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **Example** (Scanning channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Scan to create running sum | |
| * const runningSumChannel = Channel.scan(numbersChannel, 0, (sum, n) => sum + n) | |
| * // Outputs: 0, 1, 3, 6, 10, 15 | |
| * // Note: emits the initial value and each intermediate result | |
| * | |
| * // Scan with string concatenation | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "from", "effect"]) | |
| * const sentenceChannel = Channel.scan( | |
| * wordsChannel, | |
| * "", | |
| * (sentence, word) => sentence === "" ? word : `${sentence} ${word}` | |
| * ) | |
| * // Outputs: "", "hello", "hello world", "hello world from", "hello world from effect" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const scan: { | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **Example** (Scanning channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Scan to create running sum | |
| * const runningSumChannel = Channel.scan(numbersChannel, 0, (sum, n) => sum + n) | |
| * // Outputs: 0, 1, 3, 6, 10, 15 | |
| * // Note: emits the initial value and each intermediate result | |
| * | |
| * // Scan with string concatenation | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "from", "effect"]) | |
| * const sentenceChannel = Channel.scan( | |
| * wordsChannel, | |
| * "", | |
| * (sentence, word) => sentence === "" ? word : `${sentence} ${word}` | |
| * ) | |
| * // Outputs: "", "hello", "hello world", "hello world from", "hello world from effect" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <S, OutElem>(initial: S, f: (s: S, a: Types.NoInfer<OutElem>) => S): < | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| S, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **Example** (Scanning channel output) | |
| * | |
| * ```ts | |
| * import { Channel } from "effect" | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Scan to create running sum | |
| * const runningSumChannel = Channel.scan(numbersChannel, 0, (sum, n) => sum + n) | |
| * // Outputs: 0, 1, 3, 6, 10, 15 | |
| * // Note: emits the initial value and each intermediate result | |
| * | |
| * // Scan with string concatenation | |
| * const wordsChannel = Channel.fromIterable(["hello", "world", "from", "effect"]) | |
| * const sentenceChannel = Channel.scan( | |
| * wordsChannel, | |
| * "", | |
| * (sentence, word) => sentence === "" ? word : `${sentence} ${word}` | |
| * ) | |
| * // Outputs: "", "hello", "hello world", "hello world from", "hello world from effect" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: S, | |
| f: (s: S, a: Types.NoInfer<OutElem>) => S | |
| ): Channel<S, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: S, | |
| f: (s: S, a: Types.NoInfer<OutElem>) => S | |
| ): Channel<S, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| scanEffect(self, initial, (s, a) => Effect.succeed(f(s, a)))) | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an effectful accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **When to use** | |
| * | |
| * Use when maintaining accumulated state over channel output requires Effects | |
| * or can fail, while still emitting each intermediate state. | |
| * | |
| * **Example** (Scanning channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class ScanError extends Data.TaggedError("ScanError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Effectful scan with async operations | |
| * const asyncScanChannel = Channel.scanEffect( | |
| * numbersChannel, | |
| * "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * // Simulate async work | |
| * yield* Effect.sleep("10 millis") | |
| * return acc + value.toString() | |
| * }) | |
| * ) | |
| * // Outputs: "", "1", "12", "123", "1234" | |
| * | |
| * // Scan with error handling | |
| * const errorHandlingScan = Channel.scanEffect( | |
| * numbersChannel, | |
| * 0, | |
| * (sum, n) => { | |
| * if (n < 0) { | |
| * return Effect.fail(new ScanError({ reason: "negative number" })) | |
| * } | |
| * return Effect.succeed(sum + n) | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const scanEffect: { | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an effectful accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **When to use** | |
| * | |
| * Use when maintaining accumulated state over channel output requires Effects | |
| * or can fail, while still emitting each intermediate state. | |
| * | |
| * **Example** (Scanning channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class ScanError extends Data.TaggedError("ScanError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Effectful scan with async operations | |
| * const asyncScanChannel = Channel.scanEffect( | |
| * numbersChannel, | |
| * "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * // Simulate async work | |
| * yield* Effect.sleep("10 millis") | |
| * return acc + value.toString() | |
| * }) | |
| * ) | |
| * // Outputs: "", "1", "12", "123", "1234" | |
| * | |
| * // Scan with error handling | |
| * const errorHandlingScan = Channel.scanEffect( | |
| * numbersChannel, | |
| * 0, | |
| * (sum, n) => { | |
| * if (n < 0) { | |
| * return Effect.fail(new ScanError({ reason: "negative number" })) | |
| * } | |
| * return Effect.succeed(sum + n) | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <S, OutElem, E, R>(initial: S, f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R>): < | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| S, | |
| OutErr | E, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| /** | |
| * Transforms a channel statefully by scanning over its output with an effectful accumulator function. | |
| * Emits the intermediate results of the scan operation. | |
| * | |
| * **When to use** | |
| * | |
| * Use when maintaining accumulated state over channel output requires Effects | |
| * or can fail, while still emitting each intermediate state. | |
| * | |
| * **Example** (Scanning channel output with effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class ScanError extends Data.TaggedError("ScanError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4]) | |
| * | |
| * // Effectful scan with async operations | |
| * const asyncScanChannel = Channel.scanEffect( | |
| * numbersChannel, | |
| * "", | |
| * (acc, value) => | |
| * Effect.gen(function*() { | |
| * // Simulate async work | |
| * yield* Effect.sleep("10 millis") | |
| * return acc + value.toString() | |
| * }) | |
| * ) | |
| * // Outputs: "", "1", "12", "123", "1234" | |
| * | |
| * // Scan with error handling | |
| * const errorHandlingScan = Channel.scanEffect( | |
| * numbersChannel, | |
| * 0, | |
| * (sum, n) => { | |
| * if (n < 0) { | |
| * return Effect.fail(new ScanError({ reason: "negative number" })) | |
| * } | |
| * return Effect.succeed(sum + n) | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: S, | |
| f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R> | |
| ): Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, S, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| initial: S, | |
| f: (s: S, a: Types.NoInfer<OutElem>) => Effect.Effect<S, E, R> | |
| ): Channel<S, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| fromTransform((upstream, scope) => | |
| Effect.map(toTransform(self)(upstream, scope), (pull) => { | |
| let state = initial | |
| let isFirst = true | |
| return Effect.suspend(() => { | |
| if (isFirst) { | |
| isFirst = false | |
| return Effect.succeed(state) | |
| } | |
| return Effect.map( | |
| Effect.flatMap(pull, (a) => f(state, a)), | |
| (newState) => { | |
| state = newState | |
| return state | |
| } | |
| ) | |
| }) | |
| }) | |
| )) | |
| /** | |
| * Catches any cause of failure from the channel and allows recovery by | |
| * creating a new channel based on the caught cause. | |
| * | |
| * **Example** (Recovering from failure causes) | |
| * | |
| * ```ts | |
| * import { Cause, Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * class RecoveryError extends Data.TaggedError("RecoveryError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a failing channel | |
| * const failingChannel = Channel.fail( | |
| * new ProcessError({ reason: "network error" }) | |
| * ) | |
| * | |
| * // Catch the cause and provide recovery | |
| * const recoveredChannel = Channel.catchCause(failingChannel, (cause) => { | |
| * if (Cause.hasFails(cause)) { | |
| * return Channel.succeed("Recovered from failure") | |
| * } | |
| * return Channel.succeed("Recovered from interruption") | |
| * }) | |
| * | |
| * // The channel recovers gracefully from errors | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| export const catchCause: { | |
| /** | |
| * Catches any cause of failure from the channel and allows recovery by | |
| * creating a new channel based on the caught cause. | |
| * | |
| * **Example** (Recovering from failure causes) | |
| * | |
| * ```ts | |
| * import { Cause, Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * class RecoveryError extends Data.TaggedError("RecoveryError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a failing channel | |
| * const failingChannel = Channel.fail( | |
| * new ProcessError({ reason: "network error" }) | |
| * ) | |
| * | |
| * // Catch the cause and provide recovery | |
| * const recoveredChannel = Channel.catchCause(failingChannel, (cause) => { | |
| * if (Cause.hasFails(cause)) { | |
| * return Channel.succeed("Recovered from failure") | |
| * } | |
| * return Channel.succeed("Recovered from interruption") | |
| * }) | |
| * | |
| * // The channel recovers gracefully from errors | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| <OutErr, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (d: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| /** | |
| * Catches any cause of failure from the channel and allows recovery by | |
| * creating a new channel based on the caught cause. | |
| * | |
| * **Example** (Recovering from failure causes) | |
| * | |
| * ```ts | |
| * import { Cause, Channel, Data } from "effect" | |
| * | |
| * class ProcessError extends Data.TaggedError("ProcessError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * class RecoveryError extends Data.TaggedError("RecoveryError")<{ | |
| * readonly message: string | |
| * }> {} | |
| * | |
| * // Create a failing channel | |
| * const failingChannel = Channel.fail( | |
| * new ProcessError({ reason: "network error" }) | |
| * ) | |
| * | |
| * // Catch the cause and provide recovery | |
| * const recoveredChannel = Channel.catchCause(failingChannel, (cause) => { | |
| * if (Cause.hasFails(cause)) { | |
| * return Channel.succeed("Recovered from failure") | |
| * } | |
| * return Channel.succeed("Recovered from interruption") | |
| * }) | |
| * | |
| * // The channel recovers gracefully from errors | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| fromTransform((upstream, scope) => { | |
| let forkedScope = Scope.forkUnsafe(scope) | |
| return Effect.map(toTransform(self)(upstream, forkedScope), (pull) => { | |
| let currentPull: Pull.Pull<OutElem | OutElem1, OutErr1, OutDone | OutDone1, Env | Env1> = pull.pipe( | |
| Effect.catchCause((cause): Pull.Pull<OutElem1, OutErr1, OutDone | OutDone1, Env1> => { | |
| if (Pull.isDoneCause(cause)) { | |
| return Effect.failCause(cause as Cause.Cause<Cause.Done<OutDone>>) | |
| } | |
| const toClose = forkedScope | |
| forkedScope = Scope.forkUnsafe(scope) | |
| return Scope.close(toClose, Exit.failCause(cause)).pipe( | |
| Effect.andThen(toTransform(f(cause as Cause.Cause<OutErr>))(upstream, forkedScope)), | |
| Effect.flatMap((childPull) => { | |
| currentPull = childPull | |
| return childPull | |
| }) | |
| ) | |
| }) | |
| ) | |
| return Effect.suspend(() => currentPull) | |
| }) | |
| })) | |
| /** | |
| * Runs an effect with the full failure `Cause` when the channel fails, then | |
| * fails the returned channel with the original cause. | |
| * | |
| * **When to use** | |
| * | |
| * Use when observing the full channel failure `Cause` is needed without | |
| * changing successful output or replacing the original cause. | |
| * | |
| * **Details** | |
| * | |
| * Use this for observing failures, such as logging or metrics. If the observer | |
| * effect fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const tapCause: { | |
| /** | |
| * Runs an effect with the full failure `Cause` when the channel fails, then | |
| * fails the returned channel with the original cause. | |
| * | |
| * **When to use** | |
| * | |
| * Use when observing the full channel failure `Cause` is needed without | |
| * changing successful output or replacing the original cause. | |
| * | |
| * **Details** | |
| * | |
| * Use this for observing failures, such as logging or metrics. If the observer | |
| * effect fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <OutErr, A, E, R>(f: (d: Cause.Cause<OutErr>) => Effect.Effect<A, E, R>): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| /** | |
| * Runs an effect with the full failure `Cause` when the channel fails, then | |
| * fails the returned channel with the original cause. | |
| * | |
| * **When to use** | |
| * | |
| * Use when observing the full channel failure `Cause` is needed without | |
| * changing successful output or replacing the original cause. | |
| * | |
| * **Details** | |
| * | |
| * Use this for observing failures, such as logging or metrics. If the observer | |
| * effect fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Cause.Cause<OutErr>) => Effect.Effect<A, E, R> | |
| ): Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: Cause.Cause<OutErr>) => Effect.Effect<A, E, R> | |
| ): Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > => catchCause(self, (cause) => fromEffectDrain(Effect.flatMap(f(cause), (_) => Effect.failCause(cause))))) | |
| /** | |
| * Catches causes of failure that match a specific filter, allowing | |
| * conditional error recovery based on the type of failure. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover a channel only when its full `Cause` satisfies a boolean | |
| * predicate. | |
| * | |
| * **Details** | |
| * | |
| * When the predicate matches, the recovery function receives the original | |
| * cause. When it does not match, the returned channel fails with the original | |
| * cause. | |
| * | |
| * @see {@link catchCauseFilter} for selecting causes with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * @see {@link catchIf} for recovering from typed channel errors | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchCauseIf: { | |
| /** | |
| * Catches causes of failure that match a specific filter, allowing | |
| * conditional error recovery based on the type of failure. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover a channel only when its full `Cause` satisfies a boolean | |
| * predicate. | |
| * | |
| * **Details** | |
| * | |
| * When the predicate matches, the recovery function receives the original | |
| * cause. When it does not match, the returned channel fails with the original | |
| * cause. | |
| * | |
| * @see {@link catchCauseFilter} for selecting causes with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * @see {@link catchIf} for recovering from typed channel errors | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| predicate: Predicate.Predicate<Cause.Cause<OutErr>>, | |
| f: (cause: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| /** | |
| * Catches causes of failure that match a specific filter, allowing | |
| * conditional error recovery based on the type of failure. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover a channel only when its full `Cause` satisfies a boolean | |
| * predicate. | |
| * | |
| * **Details** | |
| * | |
| * When the predicate matches, the recovery function receives the original | |
| * cause. When it does not match, the returned channel fails with the original | |
| * cause. | |
| * | |
| * @see {@link catchCauseFilter} for selecting causes with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * @see {@link catchIf} for recovering from typed channel errors | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<Cause.Cause<OutErr>>, | |
| f: (cause: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual(3, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<Cause.Cause<OutErr>>, | |
| f: (cause: Cause.Cause<OutErr>) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| catchCause( | |
| self, | |
| ( | |
| cause | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| > => { | |
| return predicate(cause) | |
| ? f(cause) | |
| : failCause(cause as any) | |
| } | |
| )) | |
| /** | |
| * Recovers from channel failures whose full `Cause` is selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to recover a channel only from causes selected by a | |
| * `Filter`, while giving the recovery both the selected value and the original | |
| * `Cause`. | |
| * | |
| * **Details** | |
| * | |
| * When the filter succeeds, the recovery function receives the selected value | |
| * and the original cause. When the filter fails, the returned channel fails | |
| * with the residual cause produced by the filter. | |
| * | |
| * @see {@link catchCauseIf} for selecting causes with a predicate | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchCauseFilter: { | |
| /** | |
| * Recovers from channel failures whose full `Cause` is selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to recover a channel only from causes selected by a | |
| * `Filter`, while giving the recovery both the selected value and the original | |
| * `Cause`. | |
| * | |
| * **Details** | |
| * | |
| * When the filter succeeds, the recovery function receives the selected value | |
| * and the original cause. When the filter fails, the returned channel fails | |
| * with the residual cause produced by the filter. | |
| * | |
| * @see {@link catchCauseIf} for selecting causes with a predicate | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| EB, | |
| X extends Cause.Cause<any>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| filter: Filter.Filter<Cause.Cause<OutErr>, EB, X>, | |
| f: ( | |
| failure: EB, | |
| cause: Cause.Cause<OutErr> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1, | |
| Cause.Cause.Error<X> | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| /** | |
| * Recovers from channel failures whose full `Cause` is selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to recover a channel only from causes selected by a | |
| * `Filter`, while giving the recovery both the selected value and the original | |
| * `Cause`. | |
| * | |
| * **Details** | |
| * | |
| * When the filter succeeds, the recovery function receives the selected value | |
| * and the original cause. When the filter fails, the returned channel fails | |
| * with the residual cause produced by the filter. | |
| * | |
| * @see {@link catchCauseIf} for selecting causes with a predicate | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchCause} for recovering from every cause | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| EB, | |
| X extends Cause.Cause<any>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<Cause.Cause<OutErr>, EB, X>, | |
| f: ( | |
| failure: EB, | |
| cause: Cause.Cause<OutErr> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| Cause.Cause.Error<X> | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual(3, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| EB, | |
| X extends Cause.Cause<any>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<Cause.Cause<OutErr>, EB, X>, | |
| f: ( | |
| failure: EB, | |
| cause: Cause.Cause<OutErr> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| Cause.Cause.Error<X> | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| catchCause( | |
| self, | |
| ( | |
| cause | |
| ): Channel< | |
| OutElem1, | |
| Cause.Cause.Error<X> | OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| > => { | |
| const result = filter(cause) | |
| return Result.isFailure(result) | |
| ? failCause(result.failure) | |
| : f(result.success, cause) | |
| } | |
| )) | |
| const catch_: { | |
| <OutErr, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (d: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1> | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => catchCauseFilter(self, Cause.findError, (e) => f(e))) | |
| export { | |
| /** | |
| * Recovers from typed channel errors by running a fallback channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| catch_ as catch | |
| } | |
| /** | |
| * Runs an effect when the channel fails with a typed error, then preserves the | |
| * original channel failure. | |
| * | |
| * **Details** | |
| * | |
| * The effect is not run for normal channel completion. If the observer effect | |
| * fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const tapError: { | |
| /** | |
| * Runs an effect when the channel fails with a typed error, then preserves the | |
| * original channel failure. | |
| * | |
| * **Details** | |
| * | |
| * The effect is not run for normal channel completion. If the observer effect | |
| * fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <OutErr, A, E, R>(f: (d: OutErr) => Effect.Effect<A, E, R>): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| /** | |
| * Runs an effect when the channel fails with a typed error, then preserves the | |
| * original channel failure. | |
| * | |
| * **Details** | |
| * | |
| * The effect is not run for normal channel completion. If the observer effect | |
| * fails, that failure can fail the returned channel. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutErr) => Effect.Effect<A, E, R> | |
| ): Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| A, | |
| E, | |
| R | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutErr) => Effect.Effect<A, E, R> | |
| ): Channel< | |
| OutElem, | |
| OutErr | E, | |
| OutDone | void, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | R | |
| > => | |
| transformPull( | |
| self, | |
| (pull) => | |
| Effect.succeed(Effect.tapError( | |
| pull, | |
| (err) => Cause.isDone(err) ? Effect.void : Effect.asVoid(f(err)) | |
| )) | |
| )) | |
| /** | |
| * Recovers from typed channel errors that match a predicate or refinement. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from typed channel errors when a predicate or refinement | |
| * selects the failures that should switch to a recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Matching errors are handled by the recovery function. Non-matching errors | |
| * are handled by `orElse` when provided. Without `orElse`, non-matching errors | |
| * are re-failed. | |
| * | |
| * @see {@link catch_ catch} for recovering from every typed channel error | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchIf: { | |
| /** | |
| * Recovers from typed channel errors that match a predicate or refinement. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from typed channel errors when a predicate or refinement | |
| * selects the failures that should switch to a recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Matching errors are handled by the recovery function. Non-matching errors | |
| * are handled by `orElse` when provided. Without `orElse`, non-matching errors | |
| * are re-failed. | |
| * | |
| * @see {@link catch_ catch} for recovering from every typed channel error | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| EB extends OutErr, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| refinement: Predicate.Refinement<OutErr, EB>, | |
| f: (failure: EB) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: Exclude<OutErr, EB> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? Exclude<OutErr, EB> : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Recovers from typed channel errors that match a predicate or refinement. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from typed channel errors when a predicate or refinement | |
| * selects the failures that should switch to a recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Matching errors are handled by the recovery function. Non-matching errors | |
| * are handled by `orElse` when provided. Without `orElse`, non-matching errors | |
| * are re-failed. | |
| * | |
| * @see {@link catch_ catch} for recovering from every typed channel error | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| predicate: Predicate.Predicate<OutErr>, | |
| f: (failure: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: OutErr | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? OutErr : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Recovers from typed channel errors that match a predicate or refinement. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from typed channel errors when a predicate or refinement | |
| * selects the failures that should switch to a recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Matching errors are handled by the recovery function. Non-matching errors | |
| * are handled by `orElse` when provided. Without `orElse`, non-matching errors | |
| * are re-failed. | |
| * | |
| * @see {@link catch_ catch} for recovering from every typed channel error | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| EB extends OutErr, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| refinement: Predicate.Refinement<OutErr, EB>, | |
| f: (failure: EB) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: Exclude<OutErr, EB> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? Exclude<OutErr, EB> : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Recovers from typed channel errors that match a predicate or refinement. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from typed channel errors when a predicate or refinement | |
| * selects the failures that should switch to a recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Matching errors are handled by the recovery function. Non-matching errors | |
| * are handled by `orElse` when provided. Without `orElse`, non-matching errors | |
| * are re-failed. | |
| * | |
| * @see {@link catch_ catch} for recovering from every typed channel error | |
| * @see {@link catchFilter} for selecting typed errors with a `Filter` | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<OutErr>, | |
| f: (failure: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: OutErr | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? OutErr : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| } = dual((args) => isChannel(args[0]), < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = never, | |
| OutErr2 = OutErr, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| predicate: Predicate.Predicate<OutErr>, | |
| f: (failure: OutErr) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: OutErr | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | OutElem2, | |
| OutErr1 | OutErr2, | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > => | |
| catch_( | |
| self, | |
| (err): Channel< | |
| OutElem1 | OutElem2, | |
| OutErr1 | OutErr2, | |
| OutDone1 | OutDone2, | |
| InElem1 & InElem2, | |
| InErr1 & InErr2, | |
| InDone1 & InDone2, | |
| Env1 | Env2 | |
| > => { | |
| return predicate(err) | |
| ? f(err) | |
| : orElse | |
| ? orElse(err) | |
| : fail(err as any) as any | |
| } | |
| )) | |
| /** | |
| * Recovers from typed channel errors selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from channel errors with a reusable `Filter` when matching | |
| * can also narrow or transform the error before choosing the recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are handled by the recovery function. Failed | |
| * filter results are handled by `orElse` when provided. Without `orElse`, | |
| * failed filter results are re-failed. | |
| * | |
| * @see {@link catchIf} for selecting typed errors with a predicate | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchFilter: { | |
| /** | |
| * Recovers from typed channel errors selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from channel errors with a reusable `Filter` when matching | |
| * can also narrow or transform the error before choosing the recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are handled by the recovery function. Failed | |
| * filter results are handled by `orElse` when provided. Without `orElse`, | |
| * failed filter results are re-failed. | |
| * | |
| * @see {@link catchIf} for selecting typed errors with a predicate | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| EB, | |
| X, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| filter: Filter.Filter<OutErr, EB, X>, | |
| f: (failure: EB) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: X | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? X : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Recovers from typed channel errors selected by a `Filter`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to recover from channel errors with a reusable `Filter` when matching | |
| * can also narrow or transform the error before choosing the recovery channel. | |
| * | |
| * **Details** | |
| * | |
| * Successful filter results are handled by the recovery function. Failed | |
| * filter results are handled by `orElse` when provided. Without `orElse`, | |
| * failed filter results are re-failed. | |
| * | |
| * @see {@link catchIf} for selecting typed errors with a predicate | |
| * @see {@link catchTag} for selecting tagged typed errors | |
| * @see {@link catchCauseFilter} for selecting full causes with a `Filter` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| EB, | |
| X, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutErr, EB, X>, | |
| f: (failure: EB) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: X | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2 | (OutElem2 extends Types.unassigned ? X : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| } = dual((args) => isChannel(args[0]), < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| EB, | |
| X, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = never, | |
| OutErr2 = X, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| filter: Filter.Filter<OutErr, EB, X>, | |
| f: (failure: EB) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| failure: X | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | OutElem2, | |
| OutErr1 | OutErr2, | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > => | |
| catch_( | |
| self, | |
| (err): Channel< | |
| OutElem1 | OutElem2, | |
| OutErr1 | OutErr2, | |
| OutDone1 | OutDone2, | |
| InElem1 & InElem2, | |
| InErr1 & InErr2, | |
| InDone1 & InDone2, | |
| Env1 | Env2 | |
| > => { | |
| const result = filter(err) | |
| return Result.isFailure(result) | |
| ? orElse | |
| ? orElse(result.failure) | |
| : fail(result.failure as any) as any | |
| : f(result.success) | |
| } | |
| )) | |
| /** | |
| * Recovers from tagged channel errors whose `_tag` matches one or more tags. | |
| * | |
| * **Details** | |
| * | |
| * Matching tagged errors are handled by the recovery function. Non-matching | |
| * errors are handled by `orElse` when provided. Without `orElse`, | |
| * non-matching errors are re-failed. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchTag: { | |
| /** | |
| * Recovers from tagged channel errors whose `_tag` matches one or more tags. | |
| * | |
| * **Details** | |
| * | |
| * Matching tagged errors are handled by the recovery function. Non-matching | |
| * errors are handled by `orElse` when provided. Without `orElse`, | |
| * non-matching errors are re-failed. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| const K extends Types.Tags<OutErr> | Arr.NonEmptyReadonlyArray<Types.Tags<OutErr>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| k: K, | |
| f: ( | |
| e: Types.ExtractTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| e: Types.ExcludeTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >(self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>) => Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| | OutErr1 | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned | |
| ? Types.ExcludeTag<OutErr, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Recovers from tagged channel errors whose `_tag` matches one or more tags. | |
| * | |
| * **Details** | |
| * | |
| * Matching tagged errors are handled by the recovery function. Non-matching | |
| * errors are handled by `orElse` when provided. Without `orElse`, | |
| * non-matching errors are re-failed. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| const K extends Types.Tags<OutErr> | Arr.NonEmptyReadonlyArray<Types.Tags<OutErr>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| k: K, | |
| f: ( | |
| e: Types.ExtractTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| e: Types.ExcludeTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| | OutErr1 | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned | |
| ? Types.ExcludeTag<OutErr, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| } = dual((args) => isChannel(args[0]), < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| const K extends Types.Tags<OutErr> | Arr.NonEmptyReadonlyArray<Types.Tags<OutErr>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = never, | |
| OutErr2 = Types.ExcludeTag<OutErr, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K>, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| k: K, | |
| f: ( | |
| e: Types.ExtractTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| e: Types.ExcludeTag<NoInfer<OutErr>, K extends Arr.NonEmptyReadonlyArray<string> ? K[number] : K> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | OutElem2, | |
| OutErr1 | OutErr2, | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > => { | |
| const pred = Array.isArray(k) | |
| ? ((e: OutErr): e is any => hasProperty(e, "_tag") && k.includes(e._tag)) | |
| : isTagged(k as string) | |
| return catchIf(self, pred, f, orElse as any) as any | |
| }) | |
| /** | |
| * Catches a specific reason within a tagged error. | |
| * | |
| * **Example** (Recovering from nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const recovered = channel.pipe( | |
| * Channel.catchReason("AiError", "RateLimitError", (reason) => | |
| * Channel.succeed(`retry: ${reason.retryAfter}`) | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchReason: { | |
| /** | |
| * Catches a specific reason within a tagged error. | |
| * | |
| * **Example** (Recovering from nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const recovered = channel.pipe( | |
| * Channel.catchReason("AiError", "RateLimitError", (reason) => | |
| * Channel.succeed(`retry: ${reason.retryAfter}`) | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutErr, | |
| K extends Types.Tags<OutErr>, | |
| RK extends Types.ReasonTags<Types.ExtractTag<Types.NoInfer<OutErr>, K>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| errorTag: K, | |
| reasonTag: RK, | |
| f: ( | |
| reason: Types.ExtractReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.NarrowReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| reason: Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.OmitReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): < | |
| OutElem, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| | Types.ExcludeTag<OutErr, K> | |
| | OutErr1 | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned ? Types.ExtractTag<OutErr, K> : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| /** | |
| * Catches a specific reason within a tagged error. | |
| * | |
| * **Example** (Recovering from nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const recovered = channel.pipe( | |
| * Channel.catchReason("AiError", "RateLimitError", (reason) => | |
| * Channel.succeed(`retry: ${reason.retryAfter}`) | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| K extends Types.Tags<OutErr>, | |
| RK extends Types.ReasonTags<Types.ExtractTag<Types.NoInfer<OutErr>, K>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| errorTag: K, | |
| reasonTag: RK, | |
| f: ( | |
| reason: Types.ExtractReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.NarrowReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| reason: Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.OmitReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| | Types.ExcludeTag<OutErr, K> | |
| | OutErr1 | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned ? Types.ExtractTag<OutErr, K> : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > | |
| } = dual((args) => isChannel(args[0]), < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| K extends Types.Tags<OutErr>, | |
| RK extends Types.ReasonTags<Types.ExtractTag<Types.NoInfer<OutErr>, K>>, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| errorTag: K, | |
| reasonTag: RK, | |
| f: ( | |
| reason: Types.ExtractReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.NarrowReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| orElse?: | |
| | (( | |
| reason: Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.OmitReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| OutElem | OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| | Types.ExcludeTag<OutErr, K> | |
| | OutErr1 | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned ? Types.ExtractTag<OutErr, K> : never), | |
| OutDone | OutDone1 | OutDone2, | |
| InElem & InElem1 & InElem2, | |
| InErr & InErr1 & InErr2, | |
| InDone & InDone1 & InDone2, | |
| Env | Env1 | Env2 | |
| > => | |
| catch_( | |
| self, | |
| (error): Channel< | |
| OutElem1 | Exclude<OutElem2, Types.unassigned>, | |
| OutErr1 | OutErr2, | |
| OutDone1 | OutDone2, | |
| InElem1 & InElem2, | |
| InErr1 & InErr2, | |
| InDone1 & InDone2, | |
| Env1 | Env2 | |
| > => { | |
| if (isTagged(error, errorTag) && hasProperty(error, "reason")) { | |
| const reason = error.reason as Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| if (isTagged(reason, reasonTag)) { | |
| return f(reason as any, error as any) | |
| } | |
| return orElse ? orElse(reason, error as any) as any : fail(error) as any | |
| } | |
| return fail(error) as any | |
| } | |
| )) | |
| /** | |
| * Catches multiple reasons within a tagged error using an object of handlers. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const catchReasons: { | |
| /** | |
| * Catches multiple reasons within a tagged error using an object of handlers. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| K extends Types.Tags<OutErr>, | |
| OutErr, | |
| Cases extends { | |
| [RK in Types.ReasonTags<Types.ExtractTag<Types.NoInfer<OutErr>, K>>]+?: ( | |
| reason: Types.ExtractReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK>, | |
| error: Types.NarrowReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, RK> | |
| ) => Channel<any, any, any, any, any, any, any> | |
| }, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| errorTag: K, | |
| cases: Cases, | |
| orElse?: | |
| | (( | |
| reason: Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, Extract<keyof Cases, string>>, | |
| error: Types.OmitReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, Extract<keyof Cases, string>> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): <OutElem, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| | OutElem | |
| | Exclude<OutElem2, Types.unassigned> | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<infer OutElem1, any, any, any, any, any, any> ? OutElem1 : never | |
| }[keyof Cases], | |
| | Types.ExcludeTag<OutErr, K> | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned ? Types.ExtractTag<OutErr, K> : never) | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, infer OutErr1, any, any, any, any, any> ? OutErr1 : never | |
| }[keyof Cases], | |
| | OutDone | |
| | OutDone2 | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, infer OutDone1, any, any, any, any> ? OutDone1 : never | |
| }[keyof Cases], | |
| & InElem | |
| & InElem2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, infer InElem1, any, any, any> ? InElem1 : never | |
| }[keyof Cases], | |
| & InErr | |
| & InErr2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, infer InErr1, any, any> ? InErr1 : never | |
| }[keyof Cases], | |
| & InDone | |
| & InDone2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, any, infer InDone1, any> ? InDone1 : never | |
| }[keyof Cases], | |
| | Env | |
| | Env2 | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, any, any, infer Env1> ? Env1 : never | |
| }[keyof Cases] | |
| > | |
| /** | |
| * Catches multiple reasons within a tagged error using an object of handlers. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| K extends Types.Tags<OutErr>, | |
| Cases extends { | |
| [RK in Types.ReasonTags<Types.ExtractTag<OutErr, K>>]+?: ( | |
| reason: Types.ExtractReason<Types.ExtractTag<OutErr, K>, RK>, | |
| error: Types.NarrowReason<Types.ExtractTag<OutErr, K>, RK> | |
| ) => Channel<any, any, any, any, any, any, any> | |
| }, | |
| OutElem2 = Types.unassigned, | |
| OutErr2 = never, | |
| OutDone2 = never, | |
| InElem2 = unknown, | |
| InErr2 = unknown, | |
| InDone2 = unknown, | |
| Env2 = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| errorTag: K, | |
| cases: Cases, | |
| orElse?: | |
| | (( | |
| reason: Types.ExcludeReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, Extract<keyof Cases, string>>, | |
| error: Types.OmitReason<Types.ExtractTag<Types.NoInfer<OutErr>, K>, Extract<keyof Cases, string>> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>) | |
| | undefined | |
| ): Channel< | |
| | OutElem | |
| | Exclude<OutElem2, Types.unassigned> | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<infer OutElem1, any, any, any, any, any, any> ? OutElem1 : never | |
| }[keyof Cases], | |
| | Types.ExcludeTag<OutErr, K> | |
| | OutErr2 | |
| | (OutElem2 extends Types.unassigned ? Types.ExtractTag<OutErr, K> : never) | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, infer OutErr1, any, any, any, any, any> ? OutErr1 : never | |
| }[keyof Cases], | |
| | OutDone | |
| | OutDone2 | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, infer OutDone1, any, any, any, any> ? OutDone1 : never | |
| }[keyof Cases], | |
| & InElem | |
| & InElem2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, infer InElem1, any, any, any> ? InElem1 : never | |
| }[keyof Cases], | |
| & InErr | |
| & InErr2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, infer InErr1, any, any> ? InErr1 : never | |
| }[keyof Cases], | |
| & InDone | |
| & InDone2 | |
| & { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, any, infer InDone1, any> ? InDone1 : never | |
| }[keyof Cases], | |
| | Env | |
| | Env2 | |
| | { | |
| [RK in keyof Cases]: Cases[RK] extends | |
| (...args: Array<any>) => Channel<any, any, any, any, any, any, infer Env1> ? Env1 : never | |
| }[keyof Cases] | |
| > | |
| } = dual((args) => isChannel(args[0]), (self, errorTag, cases, orElse) => { | |
| let keys: Set<string> | |
| return catch_(self, (error) => { | |
| if ( | |
| isTagged(error, errorTag) && | |
| hasProperty(error, "reason") && | |
| hasProperty(error.reason, "_tag") && | |
| String.isString(error.reason._tag) | |
| ) { | |
| const reason = error.reason as { readonly _tag: string } | |
| keys ??= new Set(Object.keys(cases)) | |
| if (keys.has(reason._tag)) { | |
| return (cases as any)[reason._tag](reason as any, error) | |
| } | |
| return orElse ? orElse(reason, error) as any : fail(error) as any | |
| } | |
| return fail(error) as any | |
| }) | |
| }) | |
| /** | |
| * Promotes nested reason errors into the channel error, replacing the parent error. | |
| * | |
| * **Example** (Promoting nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const unwrapped = channel.pipe(Channel.unwrapReason("AiError")) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const unwrapReason: { | |
| /** | |
| * Promotes nested reason errors into the channel error, replacing the parent error. | |
| * | |
| * **Example** (Promoting nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const unwrapped = channel.pipe(Channel.unwrapReason("AiError")) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| K extends TagsWithReason<OutErr>, | |
| OutErr | |
| >(errorTag: K): <OutElem, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem, | |
| Types.ExcludeTag<OutErr, K> | Types.ReasonOf<Types.ExtractTag<OutErr, K>>, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| /** | |
| * Promotes nested reason errors into the channel error, replacing the parent error. | |
| * | |
| * **Example** (Promoting nested reasons) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class RateLimitError extends Data.TaggedError("RateLimitError")<{ | |
| * retryAfter: number | |
| * }> {} | |
| * | |
| * class QuotaExceededError extends Data.TaggedError("QuotaExceededError")<{ | |
| * limit: number | |
| * }> {} | |
| * | |
| * class AiError extends Data.TaggedError("AiError")<{ | |
| * reason: RateLimitError | QuotaExceededError | |
| * }> {} | |
| * | |
| * const channel = Channel.fail( | |
| * new AiError({ reason: new RateLimitError({ retryAfter: 60 }) }) | |
| * ) | |
| * | |
| * const unwrapped = channel.pipe(Channel.unwrapReason("AiError")) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| K extends TagsWithReason<OutErr> | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| errorTag: K | |
| ): Channel< | |
| OutElem, | |
| Types.ExcludeTag<OutErr, K> | Types.ReasonOf<Types.ExtractTag<OutErr, K>>, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| } = dual(2, < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| K extends TagsWithReason<OutErr> | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| errorTag: K | |
| ): Channel< | |
| OutElem, | |
| Types.ExcludeTag<OutErr, K> | Types.ReasonOf<Types.ExtractTag<OutErr, K>>, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > => | |
| catchFilter( | |
| self, | |
| (error) => | |
| isTagged(error, errorTag) && hasProperty(error, "reason") ? Result.succeed(error.reason) : Result.fail(error), | |
| fail | |
| ) as any) | |
| /** | |
| * Returns a new channel, which is the same as this one, except the failure | |
| * value of the returned channel is created by applying the specified function | |
| * to the failure value of this channel. | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| export const mapError: { | |
| /** | |
| * Returns a new channel, which is the same as this one, except the failure | |
| * value of the returned channel is created by applying the specified function | |
| * to the failure value of this channel. | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| <OutErr, OutErr2>(f: (err: OutErr) => OutErr2): <OutElem, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr2, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Returns a new channel, which is the same as this one, except the failure | |
| * value of the returned channel is created by applying the specified function | |
| * to the failure value of this channel. | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutErr2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (err: OutErr) => OutErr2 | |
| ): Channel<OutElem, OutErr2, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutErr2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (err: OutErr) => OutErr2 | |
| ): Channel<OutElem, OutErr2, OutDone, InElem, InErr, InDone, Env> => catch_(self, (err) => fail(f(err)))) | |
| /** | |
| * Converts all errors in the channel to defects (unrecoverable failures). | |
| * This is useful when you want to treat errors as programming errors. | |
| * | |
| * **Example** (Converting failures to defects) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class ValidationError extends Data.TaggedError("ValidationError")<{ | |
| * readonly field: string | |
| * }> {} | |
| * | |
| * // Create a channel that might fail | |
| * const failingChannel = Channel.fail(new ValidationError({ field: "email" })) | |
| * | |
| * // Convert failures to defects | |
| * const fatalChannel = Channel.orDie(failingChannel) | |
| * | |
| * // Any failure will now become a defect (uncaught exception) | |
| * ``` | |
| * | |
| * @category error handling | |
| * @since 2.0.0 | |
| */ | |
| export const orDie = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): Channel<OutElem, never, OutDone, InElem, InErr, InDone, Env> => catch_(self, die) | |
| /** | |
| * Ignores all errors in the channel, converting them to an empty channel. | |
| * | |
| * **Details** | |
| * | |
| * Use the `log` option to emit the full {@link Cause} when the channel fails. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const ignore: < | |
| Arg extends Channel<any, any, any, any, any, any, any> | { | |
| readonly log?: boolean | Severity | undefined | |
| } | undefined = { | |
| readonly log?: boolean | Severity | undefined | |
| } | |
| >( | |
| selfOrOptions: Arg, | |
| options?: { | |
| readonly log?: boolean | Severity | undefined | |
| } | undefined | |
| ) => [Arg] extends | |
| [Channel<infer OutElem, infer _OutErr, infer OutDone, infer InElem, infer InErr, infer InDone, infer Env>] | |
| ? Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> | |
| : <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options?: { | |
| readonly log?: boolean | Severity | undefined | |
| } | undefined | |
| ): Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> => { | |
| if (!options?.log) { | |
| return catch_(self, () => empty) | |
| } | |
| const logEffect = Effect.logWithLevel(options.log === true ? undefined : options.log) | |
| return catch_( | |
| tapCause(self, (cause) => Cause.hasFails(cause) ? logEffect(cause) : Effect.void), | |
| () => empty | |
| ) | |
| } | |
| ) | |
| const ignoreCause_ = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> => catchCause(self, () => empty) | |
| /** | |
| * Ignores all errors in the channel including defects, converting them to an empty channel. | |
| * | |
| * **When to use** | |
| * | |
| * Use when a channel should become best-effort and all failure causes, including | |
| * defects and interruptions, can be converted to empty output. | |
| * | |
| * **Details** | |
| * | |
| * Use the `log` option to emit the full {@link Cause} when the channel fails. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const ignoreCause: < | |
| Arg extends Channel<any, any, any, any, any, any, any> | { | |
| readonly log?: boolean | Severity | undefined | |
| } | undefined = { | |
| readonly log?: boolean | Severity | undefined | |
| } | |
| >( | |
| selfOrOptions: Arg, | |
| options?: { | |
| readonly log?: boolean | Severity | undefined | |
| } | undefined | |
| ) => [Arg] extends | |
| [Channel<infer OutElem, infer _OutErr, infer OutDone, infer InElem, infer InErr, infer InDone, infer Env>] | |
| ? Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> | |
| : <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options?: { readonly log?: boolean | Severity | undefined } | undefined | |
| ): Channel<OutElem, never, OutDone | void, InElem, InErr, InDone, Env> => { | |
| if (!options?.log) return ignoreCause_(self) | |
| const logEffect = Effect.logWithLevel(options.log === true ? undefined : options.log) | |
| return ignoreCause_(tapCause(self, (cause) => logEffect(cause))) | |
| } | |
| ) | |
| /** | |
| * Returns a new channel that retries this channel according to the specified | |
| * schedule whenever it fails. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const retry: { | |
| /** | |
| * Returns a new channel that retries this channel according to the specified | |
| * schedule whenever it fails. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <SO, OutErr, SE, SR>( | |
| schedule: | |
| | Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR> | |
| | (( | |
| $: <SO, SE, SR>( | |
| _: Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR> | |
| ) => Schedule.Schedule<SO, OutErr, SE, SR> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR>) | |
| ): <OutElem, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| ) => Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| /** | |
| * Returns a new channel that retries this channel according to the specified | |
| * schedule whenever it fails. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: | |
| | Schedule.Schedule<SO, OutErr, SE, SR> | |
| | (( | |
| $: <SO, SE, SR>( | |
| _: Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR> | |
| ) => Schedule.Schedule<SO, OutErr, SE, SR> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR>) | |
| ): Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, SO, SE, SR>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| schedule: | |
| | Schedule.Schedule<SO, OutErr, SE, SR> | |
| | (( | |
| $: <O, SE, R>(_: Schedule.Schedule<O, Types.NoInfer<OutErr>, SE, R>) => Schedule.Schedule<O, OutErr, SE, R> | |
| ) => Schedule.Schedule<SO, Types.NoInfer<OutErr>, SE, SR>) | |
| ): Channel<OutElem, OutErr | SE, OutDone, InElem, InErr, InDone, Env | SR> => | |
| suspend(() => { | |
| let step: ((input: OutErr) => Pull.Pull<Schedule.Metadata<SO, OutErr>, SE, SO, SR>) | undefined = undefined | |
| let meta = Schedule.CurrentMetadata.defaultValue() | |
| const selfWithMeta = provideServiceEffect(self, Schedule.CurrentMetadata, Effect.sync(() => meta)) | |
| const withReset = onFirst(selfWithMeta, () => { | |
| step = undefined | |
| return Effect.void | |
| }) | |
| const resolvedSchedule = typeof schedule === "function" ? schedule(identity_) : schedule | |
| const loop: Channel< | |
| OutElem, | |
| OutErr | SE, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | SR | |
| > = catch_( | |
| withReset, | |
| Effect.fnUntraced( | |
| function*(error) { | |
| if (!step) { | |
| step = yield* Schedule.toStepWithMetadata(resolvedSchedule) | |
| } | |
| meta = yield* step(error) | |
| return loop | |
| }, | |
| (effect, error) => Pull.catchDone(effect, () => Effect.succeed(fail(error))), | |
| unwrap | |
| ) | |
| ) | |
| return loop | |
| })) | |
| /** | |
| * Maps each output element to a channel and emits values from the most recent | |
| * active child channels. | |
| * | |
| * **Details** | |
| * | |
| * With the default concurrency of `1`, starting a new child channel interrupts | |
| * the previous child channel. Use `options.concurrency` to allow more active | |
| * child channels. The source channel's done value is preserved. | |
| * | |
| * **Example** (Switching mapped channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SwitchError extends Data.TaggedError("SwitchError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Switch to new channels based on each value | |
| * const switchedChannel = Channel.switchMap( | |
| * numberChannel, | |
| * (n) => Channel.fromIterable([`value-${n}`]) | |
| * ) | |
| * | |
| * // Outputs: "value-1", "value-2", "value-3" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| export const switchMap: { | |
| /** | |
| * Maps each output element to a channel and emits values from the most recent | |
| * active child channels. | |
| * | |
| * **Details** | |
| * | |
| * With the default concurrency of `1`, starting a new child channel interrupts | |
| * the previous child channel. Use `options.concurrency` to allow more active | |
| * child channels. The source channel's done value is preserved. | |
| * | |
| * **Example** (Switching mapped channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SwitchError extends Data.TaggedError("SwitchError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Switch to new channels based on each value | |
| * const switchedChannel = Channel.switchMap( | |
| * numberChannel, | |
| * (n) => Channel.fromIterable([`value-${n}`]) | |
| * ) | |
| * | |
| * // Outputs: "value-1", "value-2", "value-3" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem1, | |
| OutErr1 | OutErr, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Maps each output element to a channel and emits values from the most recent | |
| * active child channels. | |
| * | |
| * **Details** | |
| * | |
| * With the default concurrency of `1`, starting a new child channel interrupts | |
| * the previous child channel. Use `options.concurrency` to allow more active | |
| * child channels. The source channel's done value is preserved. | |
| * | |
| * **Example** (Switching mapped channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SwitchError extends Data.TaggedError("SwitchError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs numbers | |
| * const numberChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Switch to new channels based on each value | |
| * const switchedChannel = Channel.switchMap( | |
| * numberChannel, | |
| * (n) => Channel.fromIterable([`value-${n}`]) | |
| * ) | |
| * | |
| * // Outputs: "value-1", "value-2", "value-3" | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| f: (d: OutElem) => Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| OutElem1, | |
| OutErr | OutErr1, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| self.pipe( | |
| map(f), | |
| mergeAll({ | |
| ...options, | |
| concurrency: options?.concurrency ?? 1, | |
| switch: true | |
| }) | |
| ) | |
| ) | |
| /** | |
| * Merges multiple channels with specified concurrency and buffering options. | |
| * | |
| * **When to use** | |
| * | |
| * Use when channel outputs are themselves channels and multiple inner channels | |
| * should run with configured concurrency and buffering. | |
| * | |
| * **Example** (Merging nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeAllError extends Data.TaggedError("MergeAllError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create channels that output other channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Merge all channels with bounded concurrency | |
| * const mergedChannel = Channel.mergeAll({ | |
| * concurrency: 2, | |
| * bufferSize: 16 | |
| * })(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 (order may vary due to concurrency) | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| export const mergeAll: { | |
| /** | |
| * Merges multiple channels with specified concurrency and buffering options. | |
| * | |
| * **When to use** | |
| * | |
| * Use when channel outputs are themselves channels and multiple inner channels | |
| * should run with configured concurrency and buffering. | |
| * | |
| * **Example** (Merging nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeAllError extends Data.TaggedError("MergeAllError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create channels that output other channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Merge all channels with bounded concurrency | |
| * const mergedChannel = Channel.mergeAll({ | |
| * concurrency: 2, | |
| * bufferSize: 16 | |
| * })(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 (order may vary due to concurrency) | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly concurrency: number | "unbounded" | |
| readonly bufferSize?: number | undefined | |
| readonly switch?: boolean | undefined | |
| } | |
| ): <OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| channels: Channel< | |
| Channel<OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| ) => Channel< | |
| OutElem, | |
| OutErr1 | OutErr, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Merges multiple channels with specified concurrency and buffering options. | |
| * | |
| * **When to use** | |
| * | |
| * Use when channel outputs are themselves channels and multiple inner channels | |
| * should run with configured concurrency and buffering. | |
| * | |
| * **Example** (Merging nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeAllError extends Data.TaggedError("MergeAllError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create channels that output other channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Merge all channels with bounded concurrency | |
| * const mergedChannel = Channel.mergeAll({ | |
| * concurrency: 2, | |
| * bufferSize: 16 | |
| * })(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 (order may vary due to concurrency) | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| channels: Channel< | |
| Channel<OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >, | |
| options: { | |
| readonly concurrency: number | "unbounded" | |
| readonly bufferSize?: number | undefined | |
| readonly switch?: boolean | undefined | |
| } | |
| ): Channel< | |
| OutElem, | |
| OutErr1 | OutErr, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| channels: Channel< | |
| Channel<OutElem, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| >, | |
| { bufferSize = 16, concurrency, switch: switch_ = false }: { | |
| readonly concurrency: number | "unbounded" | |
| readonly bufferSize?: number | undefined | |
| readonly switch?: boolean | undefined | |
| } | |
| ): Channel< | |
| OutElem, | |
| OutErr1 | OutErr, | |
| OutDone, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > => | |
| fromTransformBracket( | |
| Effect.fnUntraced(function*(upstream, scope, forkedScope) { | |
| const concurrencyN = concurrency === "unbounded" | |
| ? Number.MAX_SAFE_INTEGER | |
| : Math.max(1, concurrency) | |
| const semaphore = switch_ ? undefined : Semaphore.makeUnsafe(concurrencyN) | |
| const doneLatch = yield* Latch.make(true) | |
| const fibers = new Set<Fiber.Fiber<any, any>>() | |
| const queue = yield* Queue.bounded</** | |
| * Merges multiple channels with specified concurrency and buffering options. | |
| * | |
| * **When to use** | |
| * | |
| * Use when channel outputs are themselves channels and multiple inner channels | |
| * should run with configured concurrency and buffering. | |
| * | |
| * **Example** (Merging nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeAllError extends Data.TaggedError("MergeAllError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create channels that output other channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Merge all channels with bounded concurrency | |
| * const mergedChannel = Channel.mergeAll({ | |
| * concurrency: 2, | |
| * bufferSize: 16 | |
| * })(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 (order may vary due to concurrency) | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| OutElem, /** | |
| * Merges multiple channels with specified concurrency and buffering options. | |
| * | |
| * **When to use** | |
| * | |
| * Use when channel outputs are themselves channels and multiple inner channels | |
| * should run with configured concurrency and buffering. | |
| * | |
| * **Example** (Merging nested channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeAllError extends Data.TaggedError("MergeAllError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create channels that output other channels | |
| * const nestedChannels = Channel.fromIterable([ | |
| * Channel.fromIterable([1, 2]), | |
| * Channel.fromIterable([3, 4]), | |
| * Channel.fromIterable([5, 6]) | |
| * ]) | |
| * | |
| * // Merge all channels with bounded concurrency | |
| * const mergedChannel = Channel.mergeAll({ | |
| * concurrency: 2, | |
| * bufferSize: 16 | |
| * })(nestedChannels) | |
| * | |
| * // Outputs: 1, 2, 3, 4, 5, 6 (order may vary due to concurrency) | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| OutErr | OutErr1 | Cause.Done<OutDone>>( | |
| bufferSize | |
| ) | |
| yield* Scope.addFinalizer(forkedScope, Queue.shutdown(queue)) | |
| const pull = yield* toTransform(channels)(upstream, scope) | |
| yield* Effect.gen(function*() { | |
| while (true) { | |
| if (semaphore) yield* semaphore.take(1) | |
| const channel = yield* pull | |
| const childScope = Scope.forkUnsafe(forkedScope) | |
| const childPull = yield* toTransform(channel)(upstream, childScope) | |
| while (fibers.size >= concurrencyN) { | |
| const fiber = Iterable.headUnsafe(fibers) | |
| fibers.delete(fiber) | |
| if (fibers.size === 0) yield* doneLatch.open | |
| yield* Fiber.interrupt(fiber) | |
| } | |
| const fiber = yield* childPull.pipe( | |
| Effect.tap(() => Effect.yieldNow), | |
| Effect.flatMap((value) => Queue.offer(queue, value)), | |
| Effect.forever({ disableYield: true }), | |
| Effect.onError(Effect.fnUntraced(function*(cause) { | |
| const halt = Pull.filterDone(cause) | |
| yield* Effect.exit(Scope.close( | |
| childScope, | |
| !Result.isFailure(halt) ? Exit.succeed(halt.success.value) : Exit.failCause(halt.failure) | |
| )) | |
| if (!fibers.has(fiber)) return | |
| fibers.delete(fiber) | |
| if (semaphore) yield* semaphore.release(1) | |
| if (fibers.size === 0) yield* doneLatch.open | |
| if (Result.isSuccess(halt)) return | |
| return yield* Queue.failCause(queue, cause as any) | |
| })), | |
| Effect.forkChild | |
| ) | |
| doneLatch.closeUnsafe() | |
| fibers.add(fiber) | |
| } | |
| }).pipe( | |
| Effect.catchCause((cause) => doneLatch.whenOpen(Queue.failCause(queue, cause))), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| return Queue.take(queue) | |
| }) | |
| ) | |
| ) | |
| /** | |
| * Represents strategies for halting merged channels when one completes or fails. | |
| * | |
| * **Example** (Choosing merge halt strategies) | |
| * | |
| * ```ts | |
| * import type { Channel } from "effect" | |
| * | |
| * // Different halt strategies for channel merging | |
| * const leftFirst: Channel.HaltStrategy = "left" // Stop when left channel halts | |
| * const rightFirst: Channel.HaltStrategy = "right" // Stop when right channel halts | |
| * const both: Channel.HaltStrategy = "both" // Stop when both channels halt | |
| * const either: Channel.HaltStrategy = "either" // Stop when either channel halts | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type HaltStrategy = "left" | "right" | "both" | "either" | |
| /** | |
| * Returns a new channel, which is the merge of this channel and the specified | |
| * channel. | |
| * | |
| * **Example** (Merging channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeError extends Data.TaggedError("MergeError")<{ | |
| * readonly source: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const leftChannel = Channel.fromIterable([1, 2, 3]) | |
| * const rightChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Merge them with "either" halt strategy | |
| * const mergedChannel = Channel.merge(leftChannel, rightChannel, { | |
| * haltStrategy: "either" | |
| * }) | |
| * | |
| * // Outputs elements from both channels concurrently | |
| * // Order may vary: 1, "a", 2, "b", 3, "c" | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| export const merge: { | |
| /** | |
| * Returns a new channel, which is the merge of this channel and the specified | |
| * channel. | |
| * | |
| * **Example** (Merging channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeError extends Data.TaggedError("MergeError")<{ | |
| * readonly source: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const leftChannel = Channel.fromIterable([1, 2, 3]) | |
| * const rightChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Merge them with "either" halt strategy | |
| * const mergedChannel = Channel.merge(leftChannel, rightChannel, { | |
| * haltStrategy: "either" | |
| * }) | |
| * | |
| * // Outputs elements from both channels concurrently | |
| * // Order may vary: 1, "a", 2, "b", 3, "c" | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| <OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>( | |
| right: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly haltStrategy?: HaltStrategy | undefined | |
| } | undefined | |
| ): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| left: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| OutElem1 | OutElem, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env1 | Env | |
| > | |
| /** | |
| * Returns a new channel, which is the merge of this channel and the specified | |
| * channel. | |
| * | |
| * **Example** (Merging channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeError extends Data.TaggedError("MergeError")<{ | |
| * readonly source: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const leftChannel = Channel.fromIterable([1, 2, 3]) | |
| * const rightChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Merge them with "either" halt strategy | |
| * const mergedChannel = Channel.merge(leftChannel, rightChannel, { | |
| * haltStrategy: "either" | |
| * }) | |
| * | |
| * // Outputs elements from both channels concurrently | |
| * // Order may vary: 1, "a", 2, "b", 3, "c" | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| left: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| right: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly haltStrategy?: HaltStrategy | undefined | |
| } | undefined | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > | |
| } = dual((args) => isChannel(args[0]) && isChannel(args[1]), < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| OutElem1, | |
| OutErr1, | |
| OutDone1, | |
| InElem1, | |
| InErr1, | |
| InDone1, | |
| Env1 | |
| >( | |
| left: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| right: Channel<OutElem1, OutErr1, OutDone1, InElem1, InErr1, InDone1, Env1>, | |
| options?: { | |
| readonly haltStrategy?: HaltStrategy | undefined | |
| } | undefined | |
| ): Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| > => | |
| fromTransformBracket(Effect.fnUntraced(function*(upstream, _scope, forkedScope) { | |
| const strategy = options?.haltStrategy ?? "both" | |
| const queue = yield* Queue.bounded</** | |
| * Returns a new channel, which is the merge of this channel and the specified | |
| * channel. | |
| * | |
| * **Example** (Merging channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeError extends Data.TaggedError("MergeError")<{ | |
| * readonly source: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const leftChannel = Channel.fromIterable([1, 2, 3]) | |
| * const rightChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Merge them with "either" halt strategy | |
| * const mergedChannel = Channel.merge(leftChannel, rightChannel, { | |
| * haltStrategy: "either" | |
| * }) | |
| * | |
| * // Outputs elements from both channels concurrently | |
| * // Order may vary: 1, "a", 2, "b", 3, "c" | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| OutElem | OutElem1, /** | |
| * Returns a new channel, which is the merge of this channel and the specified | |
| * channel. | |
| * | |
| * **Example** (Merging channels) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class MergeError extends Data.TaggedError("MergeError")<{ | |
| * readonly source: string | |
| * }> {} | |
| * | |
| * // Create two channels | |
| * const leftChannel = Channel.fromIterable([1, 2, 3]) | |
| * const rightChannel = Channel.fromIterable(["a", "b", "c"]) | |
| * | |
| * // Merge them with "either" halt strategy | |
| * const mergedChannel = Channel.merge(leftChannel, rightChannel, { | |
| * haltStrategy: "either" | |
| * }) | |
| * | |
| * // Outputs elements from both channels concurrently | |
| * // Order may vary: 1, "a", 2, "b", 3, "c" | |
| * ``` | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| OutErr | OutErr1 | Cause.Done<OutDone | OutDone1>>(0) | |
| yield* Scope.addFinalizer(forkedScope, Queue.shutdown(queue)) | |
| let done = 0 | |
| function onExit( | |
| side: "left" | "right", | |
| cause: Cause.Cause<OutErr | OutErr1 | Cause.Done<OutDone | OutDone1>> | |
| ): Effect.Effect<void> { | |
| done++ | |
| if (!Pull.isDoneCause(cause)) { | |
| return Queue.failCause(queue, cause) | |
| } | |
| switch (strategy) { | |
| case "both": { | |
| return done === 2 ? Queue.failCause(queue, cause) : Effect.void | |
| } | |
| case "left": | |
| case "right": { | |
| return side === strategy ? Queue.failCause(queue, cause) : Effect.void | |
| } | |
| case "either": { | |
| return Queue.failCause(queue, cause) | |
| } | |
| } | |
| } | |
| const runSide = ( | |
| side: "left" | "right", | |
| channel: Channel< | |
| OutElem | OutElem1, | |
| OutErr | OutErr1, | |
| OutDone | OutDone1, | |
| InElem & InElem1, | |
| InErr & InErr1, | |
| InDone & InDone1, | |
| Env | Env1 | |
| >, | |
| scope: Scope.Closeable | |
| ) => | |
| toTransform(channel)(upstream, scope).pipe( | |
| Effect.flatMap((pull) => | |
| pull.pipe( | |
| Effect.flatMap((value) => Queue.offer(queue, value)), | |
| Effect.forever | |
| ) | |
| ), | |
| Effect.onError((cause) => | |
| Effect.andThen( | |
| Scope.close(scope, Pull.doneExitFromCause(cause)), | |
| onExit(side, cause) | |
| ) | |
| ), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| yield* runSide("left", left, Scope.forkUnsafe(forkedScope)) | |
| yield* runSide("right", right, Scope.forkUnsafe(forkedScope)) | |
| return Queue.take(queue) | |
| }))) | |
| /** | |
| * Runs an effect concurrently with a channel while emitting only the channel's | |
| * output elements. | |
| * | |
| * **When to use** | |
| * | |
| * Use when a side effect should run for the lifetime of a channel and only the | |
| * channel's output elements should be emitted. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails while the | |
| * channel is running, the returned channel fails with that error. | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| export const mergeEffect: { | |
| /** | |
| * Runs an effect concurrently with a channel while emitting only the channel's | |
| * output elements. | |
| * | |
| * **When to use** | |
| * | |
| * Use when a side effect should run for the lifetime of a channel and only the | |
| * channel's output elements should be emitted. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails while the | |
| * channel is running, the returned channel fails with that error. | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| <X, E, R>(effect: Effect.Effect<X, E, R>): <OutElem, OutDone, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Runs an effect concurrently with a channel while emitting only the channel's | |
| * output elements. | |
| * | |
| * **When to use** | |
| * | |
| * Use when a side effect should run for the lifetime of a channel and only the | |
| * channel's output elements should be emitted. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails while the | |
| * channel is running, the returned channel fails with that error. | |
| * | |
| * @category combining | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, X, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<X, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, X, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<X, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| merge( | |
| self, | |
| fromEffectDrain(effect), | |
| { haltStrategy: "left" } | |
| ) as any) | |
| /** | |
| * Splits upstream string chunks into lines, recognizing `\n`, `\r\n`, and | |
| * standalone `\r` as line terminators. The behavior matches | |
| * `String.linesIterator` regardless of how the input is chunked. | |
| * | |
| * **Details** | |
| * | |
| * A line terminator at the very end of the stream does **not** produce a | |
| * trailing empty line (consistent with `String.linesIterator`). Conversely, | |
| * if the stream ends without a terminator the final partial line is still | |
| * emitted. | |
| * | |
| * **Example** (Splitting string chunks into lines) | |
| * | |
| * ```ts | |
| * import { Effect, Stream } from "effect" | |
| * | |
| * Effect.runPromise(Effect.gen(function*() { | |
| * const result = yield* Stream.runCollect( | |
| * Stream.splitLines(Stream.make("hel", "lo\r\nwor", "ld\n")) | |
| * ) | |
| * console.log(result) | |
| * // [ 'hello', 'world' ] | |
| * })) | |
| * ``` | |
| * | |
| * @category String manipulation | |
| * @since 2.0.0 | |
| */ | |
| export const splitLines = <Err, Done>(): Channel< | |
| Arr.NonEmptyReadonlyArray<string>, | |
| Err, | |
| Done, | |
| Arr.NonEmptyReadonlyArray<string>, | |
| Err, | |
| Done | |
| > => | |
| fromTransform((upstream, _scope) => | |
| Effect.sync(() => { | |
| // Accumulates text that has not yet been terminated by a line break. | |
| // Content is carried across chunks until a terminator is found. | |
| let stringBuilder = "" | |
| // Set when a chunk ends with \r so the next chunk can check whether | |
| // the following character is \n (completing a \r\n pair) or not | |
| // (standalone \r, which is itself a line terminator). | |
| let midCRLF = false | |
| // Remembers the upstream Done value after the first time the upstream | |
| // signals completion, so subsequent pulls return Done immediately | |
| // without pulling upstream again. | |
| let done = Option.none<Done>() | |
| function splitLinesArray(chunk: Arr.NonEmptyReadonlyArray<string>): Arr.NonEmptyReadonlyArray<string> | null { | |
| const chunkBuilder: Array<string> = [] | |
| function pushLine(segment: string): void { | |
| if (stringBuilder.length === 0) { | |
| chunkBuilder.push(segment) | |
| } else { | |
| chunkBuilder.push(stringBuilder + segment) | |
| stringBuilder = "" | |
| } | |
| } | |
| for (let i = 0; i < chunk.length; i++) { | |
| const str = chunk[i] | |
| if (str.length !== 0) { | |
| let from = 0 | |
| let indexOfCR = str.indexOf("\r") | |
| let indexOfLF = str.indexOf("\n") | |
| if (midCRLF) { | |
| if (indexOfLF === 0) { | |
| pushLine("") | |
| from = 1 | |
| indexOfLF = str.indexOf("\n", from) | |
| } else { | |
| pushLine("") | |
| } | |
| midCRLF = false | |
| } | |
| while (indexOfCR !== -1 || indexOfLF !== -1) { | |
| if (indexOfCR === -1 || (indexOfLF !== -1 && indexOfLF < indexOfCR)) { | |
| pushLine(str.substring(from, indexOfLF)) | |
| from = indexOfLF + 1 | |
| indexOfLF = str.indexOf("\n", from) | |
| } else { | |
| if (str.length === indexOfCR + 1) { | |
| midCRLF = true | |
| indexOfCR = -1 | |
| } else { | |
| pushLine(str.substring(from, indexOfCR)) | |
| from = indexOfCR + (indexOfLF === indexOfCR + 1 ? 2 : 1) | |
| indexOfCR = str.indexOf("\r", from) | |
| indexOfLF = str.indexOf("\n", from) | |
| } | |
| } | |
| } | |
| stringBuilder = stringBuilder + str.substring(from, str.length - (midCRLF ? 1 : 0)) | |
| } | |
| } | |
| return Arr.isReadonlyArrayNonEmpty(chunkBuilder) ? chunkBuilder : null | |
| } | |
| const pullOrFlush: Pull.Pull<Arr.NonEmptyReadonlyArray<string>, Err, Done> = Effect.suspend(() => { | |
| if (done._tag === "Some") { | |
| return Cause.done(done.value) | |
| } | |
| return Pull.matchEffect(upstream, { | |
| onSuccess: loop, | |
| onFailure: Effect.failCause, | |
| onDone: (leftover) => { | |
| done = Option.some(leftover) | |
| if (stringBuilder.length > 0 || midCRLF) { | |
| const last = stringBuilder | |
| stringBuilder = "" | |
| midCRLF = false | |
| return Effect.succeed([last] as Arr.NonEmptyReadonlyArray<string>) | |
| } | |
| return Cause.done(leftover) | |
| } | |
| }) | |
| }) | |
| function loop(chunk: Arr.NonEmptyReadonlyArray<string>): Pull.Pull<Arr.NonEmptyReadonlyArray<string>, Err, Done> { | |
| const lines = splitLinesArray(chunk) | |
| return lines !== null ? Effect.succeed(lines) : pullOrFlush | |
| } | |
| return pullOrFlush | |
| }) | |
| ) | |
| /** | |
| * Decodes incoming `Uint8Array` chunks into strings using `TextDecoder`. | |
| * | |
| * **Details** | |
| * | |
| * Input chunks are decoded with streaming enabled so multi-byte characters may | |
| * span `Uint8Array` boundaries. The optional `encoding` and `options` are | |
| * passed to `TextDecoder`. | |
| * | |
| * @category String manipulation | |
| * @since 4.0.0 | |
| */ | |
| export const decodeText = <Err, Done>(encoding?: string, options?: TextDecoderOptions): Channel< | |
| Arr.NonEmptyReadonlyArray<string>, | |
| Err, | |
| Done, | |
| Arr.NonEmptyReadonlyArray<Uint8Array>, | |
| Err, | |
| Done | |
| > => | |
| fromTransform((upstream, _scope) => | |
| Effect.sync(() => { | |
| const decoder = new TextDecoder(encoding, options) | |
| const streamOptions = { stream: true } | |
| return Effect.map(upstream, Arr.map((line) => decoder.decode(line, streamOptions))) | |
| }) | |
| ) | |
| /** | |
| * Encodes incoming string chunks into `Uint8Array` values using `TextEncoder`. | |
| * | |
| * **Details** | |
| * | |
| * Each string inside an emitted array is encoded independently. | |
| * | |
| * @category String manipulation | |
| * @since 4.0.0 | |
| */ | |
| export const encodeText = <Err, Done>(): Channel< | |
| Arr.NonEmptyReadonlyArray<Uint8Array>, | |
| Err, | |
| Done, | |
| Arr.NonEmptyReadonlyArray<string>, | |
| Err, | |
| Done | |
| > => | |
| fromTransform((upstream, _scope) => | |
| Effect.sync(() => { | |
| const encoder = new TextEncoder() | |
| return Effect.map(upstream, Arr.map((line) => encoder.encode(line))) | |
| }) | |
| ) | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel. The returned channel has the input type of this channel, | |
| * and the output type of the specified channel, terminating with the value of | |
| * the specified channel. | |
| * | |
| * **Example** (Piping one channel into another) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class PipeError extends Data.TaggedError("PipeError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create source and transform channels | |
| * const sourceChannel = Channel.fromIterable([1, 2, 3]) | |
| * const transformChannel = Channel.map(sourceChannel, (n: number) => n * 2) | |
| * | |
| * // Pipe the source into the transform | |
| * const pipedChannel = Channel.pipeTo(sourceChannel, transformChannel) | |
| * | |
| * // Outputs: 2, 4, 6 | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const pipeTo: { | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel. The returned channel has the input type of this channel, | |
| * and the output type of the specified channel, terminating with the value of | |
| * the specified channel. | |
| * | |
| * **Example** (Piping one channel into another) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class PipeError extends Data.TaggedError("PipeError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create source and transform channels | |
| * const sourceChannel = Channel.fromIterable([1, 2, 3]) | |
| * const transformChannel = Channel.map(sourceChannel, (n: number) => n * 2) | |
| * | |
| * // Pipe the source into the transform | |
| * const pipedChannel = Channel.pipeTo(sourceChannel, transformChannel) | |
| * | |
| * // Outputs: 2, 4, 6 | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem2, OutErr2, OutDone2, OutElem, OutErr, OutDone, Env2>(that: Channel<OutElem2, OutErr2, OutDone2, OutElem, OutErr, OutDone, Env2>): <InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem2, OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel. The returned channel has the input type of this channel, | |
| * and the output type of the specified channel, terminating with the value of | |
| * the specified channel. | |
| * | |
| * **Example** (Piping one channel into another) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class PipeError extends Data.TaggedError("PipeError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create source and transform channels | |
| * const sourceChannel = Channel.fromIterable([1, 2, 3]) | |
| * const transformChannel = Channel.map(sourceChannel, (n: number) => n * 2) | |
| * | |
| * // Pipe the source into the transform | |
| * const pipedChannel = Channel.pipeTo(sourceChannel, transformChannel) | |
| * | |
| * // Outputs: 2, 4, 6 | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2, OutErr2, OutDone2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, OutElem, OutErr, OutDone, Env2> | |
| ): Channel<OutElem2, OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2, OutErr2, OutDone2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, OutElem, OutErr, OutDone, Env2> | |
| ): Channel<OutElem2, OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> => | |
| fromTransform((upstream, scope) => | |
| Effect.flatMap(toTransform(self)(upstream, scope), (upstream) => toTransform(that)(upstream, scope)) | |
| ) | |
| ) | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel and preserves this channel's failures without providing | |
| * them to the other channel for observation. | |
| * | |
| * **Example** (Piping while preserving failures) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SourceError extends Data.TaggedError("SourceError")<{ | |
| * readonly code: number | |
| * }> {} | |
| * | |
| * // Create a failing source channel | |
| * const failingSource = Channel.fail(new SourceError({ code: 404 })) | |
| * const safeTransform = Channel.succeed("transformed") | |
| * | |
| * // Pipe while preserving source failures | |
| * const safePipedChannel = Channel.pipeToOrFail(failingSource, safeTransform) | |
| * | |
| * // Source errors are preserved and not sent to transform channel | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const pipeToOrFail: { | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel and preserves this channel's failures without providing | |
| * them to the other channel for observation. | |
| * | |
| * **Example** (Piping while preserving failures) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SourceError extends Data.TaggedError("SourceError")<{ | |
| * readonly code: number | |
| * }> {} | |
| * | |
| * // Create a failing source channel | |
| * const failingSource = Channel.fail(new SourceError({ code: 404 })) | |
| * const safeTransform = Channel.succeed("transformed") | |
| * | |
| * // Pipe while preserving source failures | |
| * const safePipedChannel = Channel.pipeToOrFail(failingSource, safeTransform) | |
| * | |
| * // Source errors are preserved and not sent to transform channel | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem2, OutErr2, OutDone2, OutElem, OutDone, Env2>(that: Channel<OutElem2, OutErr2, OutDone2, OutElem, never, OutDone, Env2>): <OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem2, OutErr | OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Returns a new channel that pipes the output of this channel into the | |
| * specified channel and preserves this channel's failures without providing | |
| * them to the other channel for observation. | |
| * | |
| * **Example** (Piping while preserving failures) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class SourceError extends Data.TaggedError("SourceError")<{ | |
| * readonly code: number | |
| * }> {} | |
| * | |
| * // Create a failing source channel | |
| * const failingSource = Channel.fail(new SourceError({ code: 404 })) | |
| * const safeTransform = Channel.succeed("transformed") | |
| * | |
| * // Pipe while preserving source failures | |
| * const safePipedChannel = Channel.pipeToOrFail(failingSource, safeTransform) | |
| * | |
| * // Source errors are preserved and not sent to transform channel | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2, OutErr2, OutDone2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, OutElem, never, OutDone, Env2> | |
| ): Channel<OutElem2, OutErr | OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutElem2, OutErr2, OutDone2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| that: Channel<OutElem2, OutErr2, OutDone2, OutElem, never, OutDone, Env2> | |
| ): Channel<OutElem2, OutErr | OutErr2, OutDone2, InElem, InErr, InDone, Env2 | Env> => | |
| fromTransform((upstream, scope) => | |
| Effect.flatMap(toTransform(self)(upstream, scope), (upstream) => { | |
| const upstreamPull = Effect.catchCause( | |
| upstream, | |
| (cause) => Pull.isDoneCause(cause) ? Effect.failCause(cause) : Effect.die(Cause.Done(cause)) | |
| ) as Pull.Pull<OutElem, never, OutDone> | |
| return Effect.map( | |
| toTransform(that)(upstreamPull, scope), | |
| (pull) => | |
| Effect.catchDefect( | |
| pull, | |
| (defect) => | |
| Cause.isDone(defect) ? Effect.failCause(defect.value as Cause.Cause<OutErr>) : Effect.die(defect) | |
| ) | |
| ) | |
| }) | |
| ) | |
| ) | |
| /** | |
| * Constructs a `Channel` from a scoped effect that will result in a | |
| * `Channel` if successful. | |
| * | |
| * **Example** (Unwrapping channel effects) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class UnwrapError extends Data.TaggedError("UnwrapError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create an effect that produces a channel | |
| * const channelEffect = Effect.succeed( | |
| * Channel.fromIterable([1, 2, 3]) | |
| * ) | |
| * | |
| * // Unwrap the effect to get the channel | |
| * const unwrappedChannel = Channel.unwrap(channelEffect) | |
| * | |
| * // The resulting channel outputs: 1, 2, 3 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const unwrap = <OutElem, OutErr, OutDone, InElem, InErr, InDone, R2, E, R>( | |
| channel: Effect.Effect<Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, R2>, E, R> | |
| ): Channel<OutElem, E | OutErr, OutDone, InElem, InErr, InDone, Exclude<R, Scope.Scope> | R2> => | |
| fromTransform((upstream, scope) => { | |
| let pull: Pull.Pull<OutElem, E | OutErr, OutDone> | undefined | |
| return Effect.succeed(Effect.suspend(() => { | |
| if (pull) return pull | |
| return channel.pipe( | |
| Scope.provide(scope), | |
| Effect.flatMap((channel) => toTransform(channel)(upstream, scope)), | |
| Effect.flatMap((pull_) => pull = pull_) | |
| ) | |
| })) | |
| }) | |
| /** | |
| * Runs a channel with a scope provided for the duration of the channel | |
| * execution, removing the channel's `Scope` requirement. | |
| * | |
| * @category resource management | |
| * @since 2.0.0 | |
| */ | |
| export const scoped = <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, Scope.Scope>> => | |
| fromTransformBracket((upstream, scope, forkedScope) => | |
| Effect.map( | |
| Scope.provide(toTransform(self)(upstream, scope), forkedScope), | |
| Scope.provide(forkedScope) | |
| ) | |
| ) | |
| /** | |
| * Runs an input handler against the upstream pull while the wrapped channel | |
| * runs without receiving upstream input directly. | |
| * | |
| * **Details** | |
| * | |
| * The input handler is forked in the channel scope. The wrapped channel is run | |
| * with an already-completed input. | |
| * | |
| * **Example** (Embedding custom input handling) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a base channel | |
| * const baseChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Drain the embedded input while the base channel runs | |
| * const embeddedChannel = Channel.embedInput( | |
| * baseChannel, | |
| * (upstream) => | |
| * upstream.pipe( | |
| * Effect.tap((message) => | |
| * Effect.sync(() => console.log(message)) | |
| * ), | |
| * Effect.forever, | |
| * Effect.ignore | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| export const embedInput: { | |
| /** | |
| * Runs an input handler against the upstream pull while the wrapped channel | |
| * runs without receiving upstream input directly. | |
| * | |
| * **Details** | |
| * | |
| * The input handler is forked in the channel scope. The wrapped channel is run | |
| * with an already-completed input. | |
| * | |
| * **Example** (Embedding custom input handling) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a base channel | |
| * const baseChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Drain the embedded input while the base channel runs | |
| * const embeddedChannel = Channel.embedInput( | |
| * baseChannel, | |
| * (upstream) => | |
| * upstream.pipe( | |
| * Effect.tap((message) => | |
| * Effect.sync(() => console.log(message)) | |
| * ), | |
| * Effect.forever, | |
| * Effect.ignore | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <InElem, InErr, InDone, R>( | |
| input: ( | |
| upstream: Pull.Pull<InElem, InErr, InDone> | |
| ) => Effect.Effect<void, never, R> | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Runs an input handler against the upstream pull while the wrapped channel | |
| * runs without receiving upstream input directly. | |
| * | |
| * **Details** | |
| * | |
| * The input handler is forked in the channel scope. The wrapped channel is run | |
| * with an already-completed input. | |
| * | |
| * **Example** (Embedding custom input handling) | |
| * | |
| * ```ts | |
| * import { Channel, Effect } from "effect" | |
| * | |
| * // Create a base channel | |
| * const baseChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Drain the embedded input while the base channel runs | |
| * const embeddedChannel = Channel.embedInput( | |
| * baseChannel, | |
| * (upstream) => | |
| * upstream.pipe( | |
| * Effect.tap((message) => | |
| * Effect.sync(() => console.log(message)) | |
| * ), | |
| * Effect.forever, | |
| * Effect.ignore | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category sequencing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env, InErr, InElem, InDone, R>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| input: ( | |
| upstream: Pull.Pull<InElem, InErr, InDone> | |
| ) => Effect.Effect<void, never, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, Env, InErr, InElem, InDone, R>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| input: ( | |
| upstream: Pull.Pull<InElem, InErr, InDone> | |
| ) => Effect.Effect<void, never, R> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | R> => | |
| fromTransformBracket((upstream, scope, forkedScope) => | |
| Effect.andThen( | |
| Effect.forkIn(input(upstream), forkedScope), | |
| toTransform(self)(Cause.done(), scope) | |
| ) | |
| ) | |
| ) | |
| /** | |
| * Buffers individual output elements in a queue with the configured `capacity` | |
| * so a faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when output elements can be decoupled from downstream demand and the | |
| * configured backpressure or loss strategy is acceptable. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Dropping and sliding strategies can lose output elements under backpressure. | |
| * | |
| * @see {@link bufferArray} for buffering elements from array outputs | |
| * | |
| * @category Buffering | |
| * @since 2.0.0 | |
| */ | |
| export const buffer: { | |
| /** | |
| * Buffers individual output elements in a queue with the configured `capacity` | |
| * so a faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when output elements can be decoupled from downstream demand and the | |
| * configured backpressure or loss strategy is acceptable. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Dropping and sliding strategies can lose output elements under backpressure. | |
| * | |
| * @see {@link bufferArray} for buffering elements from array outputs | |
| * | |
| * @category Buffering | |
| * @since 2.0.0 | |
| */ | |
| ( | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Buffers individual output elements in a queue with the configured `capacity` | |
| * so a faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when output elements can be decoupled from downstream demand and the | |
| * configured backpressure or loss strategy is acceptable. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Dropping and sliding strategies can lose output elements under backpressure. | |
| * | |
| * @see {@link bufferArray} for buffering elements from array outputs | |
| * | |
| * @category Buffering | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| fromTransform(Effect.fnUntraced(function*(upstream, scope) { | |
| const pull = yield* toTransform(self)(upstream, scope) | |
| const queue = yield* Queue.make</** | |
| * Buffers individual output elements in a queue with the configured `capacity` | |
| * so a faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when output elements can be decoupled from downstream demand and the | |
| * configured backpressure or loss strategy is acceptable. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Dropping and sliding strategies can lose output elements under backpressure. | |
| * | |
| * @see {@link bufferArray} for buffering elements from array outputs | |
| * | |
| * @category Buffering | |
| * @since 2.0.0 | |
| */ | |
| OutElem, /** | |
| * Buffers individual output elements in a queue with the configured `capacity` | |
| * so a faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when output elements can be decoupled from downstream demand and the | |
| * configured backpressure or loss strategy is acceptable. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Dropping and sliding strategies can lose output elements under backpressure. | |
| * | |
| * @see {@link bufferArray} for buffering elements from array outputs | |
| * | |
| * @category Buffering | |
| * @since 2.0.0 | |
| */ | |
| OutErr | Cause.Done<OutDone>>({ | |
| capacity: options.capacity === "unbounded" ? undefined : options.capacity, | |
| strategy: options.capacity === "unbounded" ? undefined : options.strategy | |
| }) | |
| yield* Scope.addFinalizer(scope, Queue.shutdown(queue)) | |
| yield* pull.pipe( | |
| Effect.flatMap((value) => Queue.offer(queue, value)), | |
| Effect.forever({ disableYield: true }), | |
| Effect.onError((cause) => Queue.failCause(queue, cause)), | |
| Effect.forkIn(scope) | |
| ) | |
| return Queue.take(queue) | |
| }))) | |
| /** | |
| * Buffers array output elements in a queue with the configured `capacity` so a | |
| * faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when emitted arrays are batches of elements and it is acceptable for | |
| * buffering to flatten and rebuild those batches. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Input arrays are offered to the queue element-by-element and outputs are | |
| * rebuilt from the currently available queued elements, so upstream array | |
| * boundaries are not preserved. | |
| * | |
| * @see {@link buffer} for buffering output elements without flattening arrays | |
| * | |
| * @category Buffering | |
| * @since 4.0.0 | |
| */ | |
| export const bufferArray: { | |
| /** | |
| * Buffers array output elements in a queue with the configured `capacity` so a | |
| * faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when emitted arrays are batches of elements and it is acceptable for | |
| * buffering to flatten and rebuild those batches. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Input arrays are offered to the queue element-by-element and outputs are | |
| * rebuilt from the currently available queued elements, so upstream array | |
| * boundaries are not preserved. | |
| * | |
| * @see {@link buffer} for buffering output elements without flattening arrays | |
| * | |
| * @category Buffering | |
| * @since 4.0.0 | |
| */ | |
| ( | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| /** | |
| * Buffers array output elements in a queue with the configured `capacity` so a | |
| * faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when emitted arrays are batches of elements and it is acceptable for | |
| * buffering to flatten and rebuild those batches. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Input arrays are offered to the queue element-by-element and outputs are | |
| * rebuilt from the currently available queued elements, so upstream array | |
| * boundaries are not preserved. | |
| * | |
| * @see {@link buffer} for buffering output elements without flattening arrays | |
| * | |
| * @category Buffering | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| options: { readonly capacity: "unbounded" } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, InElem, InErr, InDone, Env> => | |
| fromTransform(Effect.fnUntraced(function*(upstream, scope) { | |
| const pull = yield* toTransform(self)(upstream, scope) | |
| const queue = yield* Queue.make</** | |
| * Buffers array output elements in a queue with the configured `capacity` so a | |
| * faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when emitted arrays are batches of elements and it is acceptable for | |
| * buffering to flatten and rebuild those batches. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Input arrays are offered to the queue element-by-element and outputs are | |
| * rebuilt from the currently available queued elements, so upstream array | |
| * boundaries are not preserved. | |
| * | |
| * @see {@link buffer} for buffering output elements without flattening arrays | |
| * | |
| * @category Buffering | |
| * @since 4.0.0 | |
| */ | |
| OutElem, /** | |
| * Buffers array output elements in a queue with the configured `capacity` so a | |
| * faster producer can progress independently of a slower consumer. | |
| * | |
| * **When to use** | |
| * | |
| * Use when emitted arrays are batches of elements and it is acceptable for | |
| * buffering to flatten and rebuild those batches. | |
| * | |
| * **Details** | |
| * | |
| * Finite queues use the `strategy` option. The default `"suspend"` strategy | |
| * applies backpressure, while `"dropping"` and `"sliding"` can discard output | |
| * elements when the queue is full. `"unbounded"` capacity does not use a finite | |
| * capacity strategy. | |
| * | |
| * **Gotchas** | |
| * | |
| * Input arrays are offered to the queue element-by-element and outputs are | |
| * rebuilt from the currently available queued elements, so upstream array | |
| * boundaries are not preserved. | |
| * | |
| * @see {@link buffer} for buffering output elements without flattening arrays | |
| * | |
| * @category Buffering | |
| * @since 4.0.0 | |
| */ | |
| OutErr | Cause.Done<OutDone>>({ | |
| capacity: options.capacity === "unbounded" ? undefined : options.capacity, | |
| strategy: options.capacity === "unbounded" ? undefined : options.strategy | |
| }) | |
| yield* Scope.addFinalizer(scope, Queue.shutdown(queue)) | |
| yield* pull.pipe( | |
| Effect.flatMap((value) => Queue.offerAll(queue, value)), | |
| Effect.forever({ disableYield: true }), | |
| Effect.onError((cause) => Queue.failCause(queue, cause)), | |
| Effect.forkIn(scope) | |
| ) | |
| return Queue.takeAll(queue) | |
| }))) | |
| /** | |
| * Interrupts a channel when another effect completes. | |
| * | |
| * **When to use** | |
| * | |
| * Use to race channel execution against an external effect whose success can | |
| * become the channel's done value. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes first, its success value becomes the returned | |
| * channel's done value. If the channel completes first, the original channel's | |
| * done value is preserved. | |
| * | |
| * @category interruption | |
| * @since 2.0.0 | |
| */ | |
| export const interruptWhen: { | |
| /** | |
| * Interrupts a channel when another effect completes. | |
| * | |
| * **When to use** | |
| * | |
| * Use to race channel execution against an external effect whose success can | |
| * become the channel's done value. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes first, its success value becomes the returned | |
| * channel's done value. If the channel completes first, the original channel's | |
| * done value is preserved. | |
| * | |
| * @category interruption | |
| * @since 2.0.0 | |
| */ | |
| <OutDone2, OutErr2, Env2>(effect: Effect.Effect<OutDone2, OutErr2, Env2>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Interrupts a channel when another effect completes. | |
| * | |
| * **When to use** | |
| * | |
| * Use to race channel execution against an external effect whose success can | |
| * become the channel's done value. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes first, its success value becomes the returned | |
| * channel's done value. If the channel completes first, the original channel's | |
| * done value is preserved. | |
| * | |
| * @category interruption | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, OutErr2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<OutDone2, OutErr2, Env2> | |
| ): Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, OutErr2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<OutDone2, OutErr2, Env2> | |
| ): Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> => | |
| merge( | |
| self, | |
| fromPull(Effect.succeed(Effect.flatMap(effect, Cause.done))), | |
| { haltStrategy: "either" } | |
| )) | |
| /** | |
| * Stops a channel when the specified effect completes or fails. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes before the channel is done, its success value becomes | |
| * the returned channel's done value. If the effect fails, the returned channel | |
| * fails with that error. If the channel completes first, the channel's done | |
| * value is preserved. | |
| * | |
| * @category interruption | |
| * @since 4.0.0 | |
| */ | |
| export const haltWhen: { | |
| /** | |
| * Stops a channel when the specified effect completes or fails. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes before the channel is done, its success value becomes | |
| * the returned channel's done value. If the effect fails, the returned channel | |
| * fails with that error. If the channel completes first, the channel's done | |
| * value is preserved. | |
| * | |
| * @category interruption | |
| * @since 4.0.0 | |
| */ | |
| <OutDone2, OutErr2, Env2>(effect: Effect.Effect<OutDone2, OutErr2, Env2>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Stops a channel when the specified effect completes or fails. | |
| * | |
| * **Details** | |
| * | |
| * If the effect completes before the channel is done, its success value becomes | |
| * the returned channel's done value. If the effect fails, the returned channel | |
| * fails with that error. If the channel completes first, the channel's done | |
| * value is preserved. | |
| * | |
| * @category interruption | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, OutErr2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<OutDone2, OutErr2, Env2> | |
| ): Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, OutDone2, OutErr2, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| effect: Effect.Effect<OutDone2, OutErr2, Env2> | |
| ): Channel<OutElem, OutErr | OutErr2, OutDone | OutDone2, InElem, InErr, InDone, Env2 | Env> => | |
| fromTransformBracket(Effect.fnUntraced(function*(upstream, scope, forkedScope) { | |
| const pull = yield* toTransform(self)(upstream, scope) | |
| let haltCause: Cause.Cause<OutErr2 | Cause.Done<OutDone2>> | undefined = undefined | |
| yield* effect.pipe( | |
| Effect.catchCause((cause) => { | |
| haltCause = cause | |
| return Effect.void | |
| }), | |
| Effect.forkIn(forkedScope) | |
| ) | |
| return Effect.suspend((): Pull.Pull<OutElem, OutErr | OutErr2, OutDone | OutDone2> => | |
| haltCause ? Effect.failCause(haltCause) : pull | |
| ) | |
| }))) | |
| /** | |
| * Attaches a finalizer that runs only when the channel exits with failure. | |
| * | |
| * **Details** | |
| * | |
| * The finalizer receives the failure `Cause`. The original channel failure is | |
| * preserved. The finalizer itself must not fail. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| export const onError: { | |
| /** | |
| * Attaches a finalizer that runs only when the channel exits with failure. | |
| * | |
| * **Details** | |
| * | |
| * The finalizer receives the failure `Cause`. The original channel failure is | |
| * preserved. The finalizer itself must not fail. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutErr, Env2>( | |
| finalizer: (cause: Cause.Cause<OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): <OutElem, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Attaches a finalizer that runs only when the channel exits with failure. | |
| * | |
| * **Details** | |
| * | |
| * The finalizer receives the failure `Cause`. The original channel failure is | |
| * preserved. The finalizer itself must not fail. | |
| * | |
| * @category error handling | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: (cause: Cause.Cause<OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: (cause: Cause.Cause<OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> => | |
| onExit(self, (exit) => Exit.isFailure(exit) ? finalizer(exit.cause) : Effect.void)) | |
| /** | |
| * Returns a channel with an exit-aware finalizer that is guaranteed to run once | |
| * the channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Running exit finalizers) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data, Exit } from "effect" | |
| * | |
| * class ExitError extends Data.TaggedError("ExitError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Attach exit handler | |
| * const channelWithExit = Channel.onExit(dataChannel, (exit) => { | |
| * if (Exit.isSuccess(exit)) { | |
| * return Console.log(`Channel completed successfully with: ${exit.value}`) | |
| * } else { | |
| * return Console.log(`Channel failed with: ${exit.cause}`) | |
| * } | |
| * }) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 4.0.0 | |
| */ | |
| export const onExit: { | |
| /** | |
| * Returns a channel with an exit-aware finalizer that is guaranteed to run once | |
| * the channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Running exit finalizers) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data, Exit } from "effect" | |
| * | |
| * class ExitError extends Data.TaggedError("ExitError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Attach exit handler | |
| * const channelWithExit = Channel.onExit(dataChannel, (exit) => { | |
| * if (Exit.isSuccess(exit)) { | |
| * return Console.log(`Channel completed successfully with: ${exit.value}`) | |
| * } else { | |
| * return Console.log(`Channel failed with: ${exit.cause}`) | |
| * } | |
| * }) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 4.0.0 | |
| */ | |
| <OutDone, OutErr, Env2>( | |
| finalizer: (e: Exit.Exit<OutDone, OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): <OutElem, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Returns a channel with an exit-aware finalizer that is guaranteed to run once | |
| * the channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Running exit finalizers) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data, Exit } from "effect" | |
| * | |
| * class ExitError extends Data.TaggedError("ExitError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Attach exit handler | |
| * const channelWithExit = Channel.onExit(dataChannel, (exit) => { | |
| * if (Exit.isSuccess(exit)) { | |
| * return Console.log(`Channel completed successfully with: ${exit.value}`) | |
| * } else { | |
| * return Console.log(`Channel failed with: ${exit.cause}`) | |
| * } | |
| * }) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: (e: Exit.Exit<OutDone, OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: (e: Exit.Exit<OutDone, OutErr>) => Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> => | |
| fromTransformBracket((upstream, scope, forkedScope) => | |
| Scope.addFinalizerExit(forkedScope, finalizer as any).pipe( | |
| Effect.andThen(toTransform(self)(upstream, scope)) | |
| ) | |
| )) | |
| /** | |
| * Runs an effect before the channel starts. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails, the returned | |
| * channel fails before running the source channel. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| export const onStart: { | |
| /** | |
| * Runs an effect before the channel starts. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails, the returned | |
| * channel fails before running the source channel. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <A, E, R>(onStart: Effect.Effect<A, E, R>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Runs an effect before the channel starts. | |
| * | |
| * **Details** | |
| * | |
| * The effect's successful value is ignored. If the effect fails, the returned | |
| * channel fails before running the source channel. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onStart: Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onStart: Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => unwrap(Effect.as(onStart, self))) | |
| /** | |
| * Runs an effect the first time the channel emits an output element. | |
| * | |
| * **When to use** | |
| * | |
| * Use when initialization depends on the first output element rather than only | |
| * on channel startup. | |
| * | |
| * **Details** | |
| * | |
| * The effect receives the first emitted element. The first element is still | |
| * emitted unchanged. The effect is not run if the channel completes without | |
| * emitting an element. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| export const onFirst: { | |
| /** | |
| * Runs an effect the first time the channel emits an output element. | |
| * | |
| * **When to use** | |
| * | |
| * Use when initialization depends on the first output element rather than only | |
| * on channel startup. | |
| * | |
| * **Details** | |
| * | |
| * The effect receives the first emitted element. The first element is still | |
| * emitted unchanged. The effect is not run if the channel completes without | |
| * emitting an element. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, A, E, R>(onFirst: (element: Types.NoInfer<OutElem>) => Effect.Effect<A, E, R>): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Runs an effect the first time the channel emits an output element. | |
| * | |
| * **When to use** | |
| * | |
| * Use when initialization depends on the first output element rather than only | |
| * on channel startup. | |
| * | |
| * **Details** | |
| * | |
| * The effect receives the first emitted element. The first element is still | |
| * emitted unchanged. The effect is not run if the channel completes without | |
| * emitting an element. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onFirst: (element: Types.NoInfer<OutElem>) => Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onFirst: (element: Types.NoInfer<OutElem>) => Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| transformPull(self, (pull) => | |
| Effect.sync(() => { | |
| let isFirst = true | |
| const pullFirst = Effect.tap(pull, (element) => { | |
| isFirst = false | |
| return onFirst(element) | |
| }) | |
| return Effect.suspend(() => isFirst ? pullFirst : pull) | |
| }))) | |
| /** | |
| * Runs an effect when the channel completes successfully. | |
| * | |
| * **Details** | |
| * | |
| * The effect runs before the original done value is propagated. The effect is | |
| * not run when the channel fails. If the effect fails, the returned channel | |
| * fails with that error. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| export const onEnd: { | |
| /** | |
| * Runs an effect when the channel completes successfully. | |
| * | |
| * **Details** | |
| * | |
| * The effect runs before the original done value is propagated. The effect is | |
| * not run when the channel fails. If the effect fails, the returned channel | |
| * fails with that error. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <A, E, R>(onEnd: Effect.Effect<A, E, R>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| /** | |
| * Runs an effect when the channel completes successfully. | |
| * | |
| * **Details** | |
| * | |
| * The effect runs before the original done value is propagated. The effect is | |
| * not run when the channel fails. If the effect fails, the returned channel | |
| * fails with that error. | |
| * | |
| * @category hooks | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onEnd: Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| onEnd: Effect.Effect<A, E, R> | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Env | R> => | |
| transformPull(self, (pull) => | |
| Effect.succeed(Pull.catchDone( | |
| pull, | |
| (leftover) => Effect.flatMap(onEnd, () => Cause.done(leftover as OutDone)) | |
| )))) | |
| /** | |
| * Returns a channel with a finalizer effect that is guaranteed to run once the | |
| * channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Ensuring cleanup runs) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class EnsureError extends Data.TaggedError("EnsureError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Ensure cleanup always runs | |
| * const channelWithCleanup = Channel.ensuring( | |
| * dataChannel, | |
| * Console.log("Cleanup executed regardless of success or failure") | |
| * ) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 2.0.0 | |
| */ | |
| export const ensuring: { | |
| /** | |
| * Returns a channel with a finalizer effect that is guaranteed to run once the | |
| * channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Ensuring cleanup runs) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class EnsureError extends Data.TaggedError("EnsureError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Ensure cleanup always runs | |
| * const channelWithCleanup = Channel.ensuring( | |
| * dataChannel, | |
| * Console.log("Cleanup executed regardless of success or failure") | |
| * ) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 2.0.0 | |
| */ | |
| <Env2>(finalizer: Effect.Effect<unknown, never, Env2>): <OutElem, OutDone, OutErr, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| /** | |
| * Returns a channel with a finalizer effect that is guaranteed to run once the | |
| * channel begins execution, whether it succeeds or fails. | |
| * | |
| * **Example** (Ensuring cleanup runs) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class EnsureError extends Data.TaggedError("EnsureError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const dataChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Ensure cleanup always runs | |
| * const channelWithCleanup = Channel.ensuring( | |
| * dataChannel, | |
| * Console.log("Cleanup executed regardless of success or failure") | |
| * ) | |
| * ``` | |
| * | |
| * @category resource management | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, Env2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| finalizer: Effect.Effect<unknown, never, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2 | Env> => onExit(self, (_) => finalizer)) | |
| const runWith = < | |
| OutElem, | |
| OutErr, | |
| OutDone, | |
| Env, | |
| EX, | |
| RX, | |
| AH = OutDone, | |
| EH = never, | |
| RH = never | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| f: (pull: Pull.Pull<OutElem, OutErr, OutDone>) => Effect.Effect<void, EX, RX>, | |
| onHalt?: (leftover: OutDone) => Effect.Effect<AH, EH, RH> | |
| ): Effect.Effect<AH, Pull.ExcludeDone<EX> | EH, Env | RX | RH> => | |
| Effect.suspend(() => { | |
| const scope = Scope.makeUnsafe() | |
| const makePull = toTransform(self)(Cause.done(), scope) | |
| return Pull.catchDone(Effect.flatMap(makePull, f), onHalt ? onHalt : Effect.succeed as any).pipe( | |
| Effect.onExit((exit) => Scope.close(scope, exit)) | |
| ) as any | |
| }) | |
| /** | |
| * Creates a channel from the specified services. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| export const contextWith = <Env, OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2>( | |
| f: (context: Context.Context<Env>) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env | Env2> => | |
| fromTransform((upstream, scope) => | |
| Effect.contextWith((context: Context.Context<Env>) => toTransform(f(context))(upstream, scope)) | |
| ) | |
| /** | |
| * Provides a `Context` to the channel, removing the corresponding service | |
| * requirements from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| export const provideContext: { | |
| /** | |
| * Provides a `Context` to the channel, removing the corresponding service | |
| * requirements from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <R2>(context: Context.Context<R2>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, R2>> | |
| /** | |
| * Provides a `Context` to the channel, removing the corresponding service | |
| * requirements from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, R2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| context: Context.Context<R2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, R2>> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, R2>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| context: Context.Context<R2> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, R2>> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| Effect.provideContext(toTransform(self)(upstream, scope), context), | |
| Effect.provideContext(context) | |
| ) | |
| )) | |
| /** | |
| * Provides a concrete service for a context key, removing that service | |
| * requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| export const provideService: { | |
| /** | |
| * Provides a concrete service for a context key, removing that service | |
| * requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <I, S>(key: Context.Key<I, S>, service: NoInfer<S>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, I>> | |
| /** | |
| * Provides a concrete service for a context key, removing that service | |
| * requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| key: Context.Key<I, S>, | |
| service: NoInfer<S> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, I>> | |
| } = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| key: Context.Key<I, S>, | |
| service: NoInfer<S> | |
| ): Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Exclude<Env, I>> => | |
| fromTransform((upstream, scope) => | |
| Effect.map( | |
| Effect.provideService(toTransform(self)(upstream, scope), key, service), | |
| Effect.provideService(key, service) | |
| ) | |
| )) | |
| /** | |
| * Provides a service to the channel after obtaining it from an effect. | |
| * | |
| * **When to use** | |
| * | |
| * Use to supply a channel dependency when constructing the service itself is | |
| * effectful or can fail. | |
| * | |
| * **Details** | |
| * | |
| * If the service effect fails, the returned channel fails. The provided service | |
| * removes the corresponding service requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| export const provideServiceEffect: { | |
| /** | |
| * Provides a service to the channel after obtaining it from an effect. | |
| * | |
| * **When to use** | |
| * | |
| * Use to supply a channel dependency when constructing the service itself is | |
| * effectful or can fail. | |
| * | |
| * **Details** | |
| * | |
| * If the service effect fails, the returned channel fails. The provided service | |
| * removes the corresponding service requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <I, S, ES, RS>(key: Context.Key<I, S>, service: Effect.Effect<NoInfer<S>, ES, RS>): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | ES, OutDone, InElem, InErr, InDone, Exclude<Env, I> | RS> | |
| /** | |
| * Provides a service to the channel after obtaining it from an effect. | |
| * | |
| * **When to use** | |
| * | |
| * Use to supply a channel dependency when constructing the service itself is | |
| * effectful or can fail. | |
| * | |
| * **Details** | |
| * | |
| * If the service effect fails, the returned channel fails. The provided service | |
| * removes the corresponding service requirement from the returned channel. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S, ES, RS>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| key: Context.Key<I, S>, | |
| service: Effect.Effect<NoInfer<S>, ES, RS> | |
| ): Channel<OutElem, OutErr | ES, OutDone, InElem, InErr, InDone, Exclude<Env, I> | RS> | |
| } = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S, ES, RS>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| key: Context.Key<I, S>, | |
| service: Effect.Effect<NoInfer<S>, ES, RS> | |
| ): Channel<OutElem, OutErr | ES, OutDone, InElem, InErr, InDone, Exclude<Env, I> | RS> => | |
| fromTransform((upstream, scope) => | |
| Effect.flatMap( | |
| service, | |
| (s) => toTransform(provideService(self, key, s))(upstream, scope) | |
| ) | |
| )) | |
| /** | |
| * Provides a `Layer` or `Context` to the channel, removing the corresponding | |
| * service requirements. | |
| * | |
| * **Details** | |
| * | |
| * Providing a `Context` delegates to `provideContext`. Providing a `Layer` | |
| * builds the layer in the channel scope. Use `options.local` to build a fresh | |
| * layer instance for this provision. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| export const provide: { | |
| /** | |
| * Provides a `Layer` or `Context` to the channel, removing the corresponding | |
| * service requirements. | |
| * | |
| * **Details** | |
| * | |
| * Providing a `Context` delegates to `provideContext`. Providing a `Layer` | |
| * builds the layer in the channel scope. Use `options.local` to build a fresh | |
| * layer instance for this provision. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <A, E = never, R = never>( | |
| layer: Layer.Layer<A, E, R> | Context.Context<A>, | |
| options?: { | |
| readonly local?: boolean | undefined | |
| } | undefined | |
| ): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Exclude<Env, A> | R> | |
| /** | |
| * Provides a `Layer` or `Context` to the channel, removing the corresponding | |
| * service requirements. | |
| * | |
| * **Details** | |
| * | |
| * Providing a `Context` delegates to `provideContext`. Providing a `Layer` | |
| * builds the layer in the channel scope. Use `options.local` to build a fresh | |
| * layer instance for this provision. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E = never, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| layer: Layer.Layer<A, E, R> | Context.Context<A>, | |
| options?: { | |
| readonly local?: boolean | undefined | |
| } | undefined | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Exclude<Env, A> | R> | |
| } = dual((args) => isChannel(args[0]), <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, A, E = never, R = never>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| layer: Layer.Layer<A, E, R> | Context.Context<A>, | |
| options?: { | |
| readonly local?: boolean | undefined | |
| } | undefined | |
| ): Channel<OutElem, OutErr | E, OutDone, InElem, InErr, InDone, Exclude<Env, A> | R> => | |
| Context.isContext(layer) ? provideContext(self, layer) : fromTransform((upstream, scope) => | |
| Effect.flatMap( | |
| options?.local | |
| ? Layer.buildWithMemoMap(layer, Layer.makeMemoMapUnsafe(), scope) | |
| : Layer.buildWithScope(layer, scope), | |
| (context) => | |
| Effect.map( | |
| Effect.provideContext(toTransform(self)(upstream, scope), context), | |
| Effect.provideContext(context) | |
| ) | |
| ) | |
| )) | |
| /** | |
| * Transforms the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The function receives the surrounding context and returns the context to | |
| * provide to the channel. The returned channel requires the services needed to | |
| * build that context. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| export const updateContext: { | |
| /** | |
| * Transforms the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The function receives the surrounding context and returns the context to | |
| * provide to the channel. The returned channel requires the services needed to | |
| * build that context. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <Env, R2>(f: (context: Context.Context<R2>) => Context.Context<Env>): <OutElem, OutErr, OutDone, InElem, InErr, InDone>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env> | |
| ) => Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R2> | |
| /** | |
| * Transforms the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The function receives the surrounding context and returns the context to | |
| * provide to the channel. The returned channel requires the services needed to | |
| * build that context. | |
| * | |
| * @category services | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, R2>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env>, | |
| f: (context: Context.Context<R2>) => Context.Context<Env> | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R2> | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, R2>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env>, | |
| f: (context: Context.Context<R2>) => Context.Context<Env> | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R2> => | |
| fromTransform((upstream, scope) => | |
| Effect.contextWith((context) => { | |
| const toProvide = f(context) | |
| return toTransform(provideContext(self, toProvide))(upstream, scope) | |
| }) | |
| )) | |
| /** | |
| * Updates a service in the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The existing service is read from the context. The updated service is | |
| * provided to the channel under the same key. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| export const updateService: { | |
| /** | |
| * Updates a service in the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The existing service is read from the context. The updated service is | |
| * provided to the channel under the same key. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <I, S>(key: Context.Key<I, S>, f: (service: NoInfer<S>) => S): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env> | |
| ) => Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env | I> | |
| /** | |
| * Updates a service in the current context before running the channel. | |
| * | |
| * **Details** | |
| * | |
| * The existing service is read from the context. The updated service is | |
| * provided to the channel under the same key. | |
| * | |
| * @category services | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env>, | |
| service: Context.Key<I, S>, | |
| f: (service: NoInfer<S>) => S | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env | I> | |
| } = dual(3, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, I, S>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env>, | |
| service: Context.Key<I, S>, | |
| f: (service: NoInfer<S>) => S | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Env | I> => | |
| updateContext(self, (context) => | |
| Context.add( | |
| context, | |
| service, | |
| f(Context.get(context, service)) | |
| ))) | |
| /** | |
| * Runs the channel inside a tracing span with the specified name and options. | |
| * | |
| * **Details** | |
| * | |
| * The created span is provided as the current parent span while the channel | |
| * runs. The span is ended with the channel's exit value. | |
| * | |
| * @category tracing | |
| * @since 2.0.0 | |
| */ | |
| export const withSpan: { | |
| /** | |
| * Runs the channel inside a tracing span with the specified name and options. | |
| * | |
| * **Details** | |
| * | |
| * The created span is provided as the current parent span while the channel | |
| * runs. The span is ended with the channel's exit value. | |
| * | |
| * @category tracing | |
| * @since 2.0.0 | |
| */ | |
| (name: string, options?: SpanOptions): <OutElem, OutErr, OutDone, InElem, InErr, InDone, R>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R> | |
| ) => Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Exclude<R, ParentSpan>> | |
| /** | |
| * Runs the channel inside a tracing span with the specified name and options. | |
| * | |
| * **Details** | |
| * | |
| * The created span is provided as the current parent span while the channel | |
| * runs. The span is ended with the channel's exit value. | |
| * | |
| * @category tracing | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, R>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R>, | |
| name: string, | |
| options?: SpanOptions | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Exclude<R, ParentSpan>> | |
| } = function() { | |
| const dataFirst = isChannel(arguments[0]) | |
| const name = dataFirst ? arguments[1] : arguments[0] | |
| const options = addSpanStackTrace(dataFirst ? arguments[2] : arguments[1]) | |
| if (dataFirst) { | |
| const self = arguments[0] | |
| return withSpanImpl(self, name, options) | |
| } | |
| return (self: any) => withSpanImpl(self, name, options) | |
| } as any | |
| const withSpanImpl = <OutElem, OutErr, OutDone, InElem, InErr, InDone, R>( | |
| self: Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, R>, | |
| name: string, | |
| options?: SpanOptions | |
| ): Channel<OutElem, InElem, OutErr, InErr, OutDone, InDone, Exclude<R, ParentSpan>> => | |
| acquireUseRelease( | |
| Effect.makeSpan(name, options), | |
| (span) => provideService(self, ParentSpan, span), | |
| (span, exit) => | |
| Effect.withFiber((fiber) => { | |
| const clock = fiber.getRef(ClockRef) | |
| const timingEnabled = fiber.getRef(TracerTimingEnabled) | |
| return endSpan(span, exit, clock, timingEnabled) | |
| }) | |
| ) | |
| /** | |
| * The starting channel for Do notation, emitting an empty object. | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| export const Do: Channel<{}> = succeed({}) | |
| const let_: { | |
| <N extends string, OutElem extends object, B>( | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => B | |
| ): <OutErr, OutDone, InElem, InErr, InDone, R>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, R> | |
| ) => Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| R | |
| > | |
| <OutElem extends object, OutErr, OutDone, InElem, InErr, InDone, R, N extends string, B>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, R>, | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => B | |
| ): Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| R | |
| > | |
| } = dual(3, <OutElem extends object, OutErr, OutDone, InElem, InErr, InDone, R, N extends string, B>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, R>, | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => B | |
| ): Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| R | |
| > => | |
| map(self, (elem) => (({ | |
| ...elem, | |
| [name]: f(elem) | |
| }) as any))) | |
| export { | |
| /** | |
| * Adds a computed field to each object emitted by a channel. | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| let_ as let | |
| } | |
| /** | |
| * Adds a field to each object emitted by a channel by running another channel | |
| * derived from that object. | |
| * | |
| * **Details** | |
| * | |
| * The field name must not already exist on the emitted object. The derived | |
| * channel's output becomes the value of the new field. `options.concurrency` | |
| * and `options.bufferSize` control how derived channels are flattened. | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| export const bind: { | |
| /** | |
| * Adds a field to each object emitted by a channel by running another channel | |
| * derived from that object. | |
| * | |
| * **Details** | |
| * | |
| * The field name must not already exist on the emitted object. The derived | |
| * channel's output becomes the value of the new field. `options.concurrency` | |
| * and `options.bufferSize` control how derived channels are flattened. | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| <N extends string, OutElem extends object, B, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>( | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => Channel<B, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): <OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr2 | OutErr, | |
| OutDone, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env2 | Env | |
| > | |
| /** | |
| * Adds a field to each object emitted by a channel by running another channel | |
| * derived from that object. | |
| * | |
| * **Details** | |
| * | |
| * The field name must not already exist on the emitted object. The derived | |
| * channel's output becomes the value of the new field. `options.concurrency` | |
| * and `options.bufferSize` control how derived channels are flattened. | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| < | |
| OutElem extends object, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| N extends string, | |
| B, | |
| OutErr2, | |
| OutDone2, | |
| InElem2, | |
| InErr2, | |
| InDone2, | |
| Env2 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => Channel<B, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr2 | OutErr, | |
| OutDone, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env2 | Env | |
| > | |
| } = dual((args) => isChannel(args[0]), < | |
| OutElem extends object, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env, | |
| N extends string, | |
| B, | |
| OutErr2, | |
| OutDone2, | |
| InElem2, | |
| InErr2, | |
| InDone2, | |
| Env2 | |
| >( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| name: Exclude<N, keyof OutElem>, | |
| f: (a: NoInfer<OutElem>) => Channel<B, OutErr2, OutDone2, InElem2, InErr2, InDone2, Env2>, | |
| options?: { | |
| readonly concurrency?: number | "unbounded" | undefined | |
| readonly bufferSize?: number | undefined | |
| } | |
| ): Channel< | |
| { [K in N | keyof OutElem]: K extends keyof OutElem ? OutElem[K] : B }, | |
| OutErr2 | OutErr, | |
| OutDone, | |
| InElem & InElem2, | |
| InErr & InErr2, | |
| InDone & InDone2, | |
| Env2 | Env | |
| > => | |
| flatMap( | |
| self, | |
| (elem) => map(f(elem), (b) => ({ ...elem, [name]: b } as any)), | |
| options | |
| )) | |
| /** | |
| * Wraps each output element in an object under the specified field name. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to start a Channel Do-notation chain from an existing | |
| * output value by assigning that value to a field name. | |
| * | |
| * @see {@link Do} for starting Do notation from an empty object | |
| * @see {@link bind} for adding a field produced by another channel | |
| * @see {@link let_ let} for adding a computed field | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| export const bindTo: { | |
| /** | |
| * Wraps each output element in an object under the specified field name. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to start a Channel Do-notation chain from an existing | |
| * output value by assigning that value to a field name. | |
| * | |
| * @see {@link Do} for starting Do notation from an empty object | |
| * @see {@link bind} for adding a field produced by another channel | |
| * @see {@link let_ let} for adding a computed field | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| <N extends string>(name: N): <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env> | |
| ) => Channel< | |
| { [K in N]: OutElem }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| /** | |
| * Wraps each output element in an object under the specified field name. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to start a Channel Do-notation chain from an existing | |
| * output value by assigning that value to a field name. | |
| * | |
| * @see {@link Do} for starting Do notation from an empty object | |
| * @see {@link bind} for adding a field produced by another channel | |
| * @see {@link let_ let} for adding a computed field | |
| * | |
| * @category do notation | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, N extends string>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| name: N | |
| ): Channel< | |
| { [K in N]: OutElem }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > | |
| } = dual(2, <OutElem, OutErr, OutDone, InElem, InErr, InDone, Env, N extends string>( | |
| self: Channel<OutElem, OutErr, OutDone, InElem, InErr, InDone, Env>, | |
| name: N | |
| ): Channel< | |
| { [K in N]: OutElem }, | |
| OutErr, | |
| OutDone, | |
| InElem, | |
| InErr, | |
| InDone, | |
| Env | |
| > => map(self, (elem) => ({ [name]: elem } as any))) | |
| /** | |
| * Runs a channel and counts the number of elements it outputs. | |
| * | |
| * **Example** (Counting channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class CountError extends Data.TaggedError("CountError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel with multiple elements | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Count the elements | |
| * const countEffect = Channel.runCount(numbersChannel) | |
| * | |
| * // Effect.runSync(countEffect) // Returns: 5 | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runCount = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<void, OutErr, Env> => runFold(self, () => 0, (acc) => acc + 1) | |
| /** | |
| * Runs a channel and discards all output elements, returning only the final result. | |
| * | |
| * **Example** (Draining channel output at runtime) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class DrainError extends Data.TaggedError("DrainError")<{ | |
| * readonly stage: string | |
| * }> {} | |
| * | |
| * // Create a channel that outputs elements and completes with a result | |
| * const resultChannel = Channel.fromIterable([1, 2, 3]) | |
| * const completedChannel = Channel.concatWith( | |
| * resultChannel, | |
| * () => Channel.succeed("completed") | |
| * ) | |
| * | |
| * // Drain all elements and get only the final result | |
| * const drainEffect = Channel.runDrain(completedChannel) | |
| * | |
| * // Effect.runSync(drainEffect) // Returns: "completed" | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 2.0.0 | |
| */ | |
| export const runDrain = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<OutDone, OutErr, Env> => runWith(self, (pull) => Effect.forever(pull, { disableYield: true })) | |
| /** | |
| * Runs a channel and applies an effect to each output element. | |
| * | |
| * **Example** (Running effects for each output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class ForEachError extends Data.TaggedError("ForEachError")<{ | |
| * readonly element: unknown | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Run forEach to log each element | |
| * const forEachEffect = Channel.runForEach( | |
| * numbersChannel, | |
| * (n) => Console.log(`Processing: ${n}`) | |
| * ) | |
| * | |
| * // Logs: "Processing: 1", "Processing: 2", "Processing: 3" | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runForEach: { | |
| /** | |
| * Runs a channel and applies an effect to each output element. | |
| * | |
| * **Example** (Running effects for each output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class ForEachError extends Data.TaggedError("ForEachError")<{ | |
| * readonly element: unknown | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Run forEach to log each element | |
| * const forEachEffect = Channel.runForEach( | |
| * numbersChannel, | |
| * (n) => Console.log(`Processing: ${n}`) | |
| * ) | |
| * | |
| * // Logs: "Processing: 1", "Processing: 2", "Processing: 3" | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, EX, RX>(f: (o: OutElem) => Effect.Effect<void, EX, RX>): <OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<OutDone, OutErr | EX, Env | RX> | |
| /** | |
| * Runs a channel and applies an effect to each output element. | |
| * | |
| * **Example** (Running effects for each output) | |
| * | |
| * ```ts | |
| * import { Channel, Console, Data } from "effect" | |
| * | |
| * class ForEachError extends Data.TaggedError("ForEachError")<{ | |
| * readonly element: unknown | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Run forEach to log each element | |
| * const forEachEffect = Channel.runForEach( | |
| * numbersChannel, | |
| * (n) => Console.log(`Processing: ${n}`) | |
| * ) | |
| * | |
| * // Logs: "Processing: 1", "Processing: 2", "Processing: 3" | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| f: (o: OutElem) => Effect.Effect<void, EX, RX> | |
| ): Effect.Effect<OutDone, OutErr | EX, Env | RX> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, Env, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| f: (o: OutElem) => Effect.Effect<void, EX, RX> | |
| ): Effect.Effect<OutDone, OutErr | EX, Env | RX> => | |
| runWith(self, (pull) => Effect.forever(Effect.flatMap(pull, f), { disableYield: true })) | |
| ) | |
| /** | |
| * Runs a channel and applies an effectful predicate to each output element | |
| * until the predicate returns `false`. | |
| * | |
| * **Details** | |
| * | |
| * Returning `true` continues consuming the channel. Returning `false` stops | |
| * consumption early. The returned effect completes with `void`. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runForEachWhile: { | |
| /** | |
| * Runs a channel and applies an effectful predicate to each output element | |
| * until the predicate returns `false`. | |
| * | |
| * **Details** | |
| * | |
| * Returning `true` continues consuming the channel. Returning `false` stops | |
| * consumption early. The returned effect completes with `void`. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, EX, RX>(f: (o: OutElem) => Effect.Effect<boolean, EX, RX>): <OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<void, OutErr | EX, Env | RX> | |
| /** | |
| * Runs a channel and applies an effectful predicate to each output element | |
| * until the predicate returns `false`. | |
| * | |
| * **Details** | |
| * | |
| * Returning `true` continues consuming the channel. Returning `false` stops | |
| * consumption early. The returned effect completes with `void`. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| f: (o: OutElem) => Effect.Effect<boolean, EX, RX> | |
| ): Effect.Effect<void, OutErr | EX, Env | RX> | |
| } = dual( | |
| 2, | |
| <OutElem, OutErr, OutDone, Env, EX, RX>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| f: (o: OutElem) => Effect.Effect<boolean, EX, RX> | |
| ): Effect.Effect<void, OutErr | EX, Env | RX> => | |
| runWith(self, (pull) => | |
| pull.pipe( | |
| Effect.flatMap(f), | |
| Effect.flatMap((cont) => (cont ? Effect.void : Cause.done())), | |
| Effect.forever({ disableYield: true }) | |
| )) | |
| ) | |
| /** | |
| * Runs a channel and collects all output elements into an array. | |
| * | |
| * **Example** (Collecting channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class CollectError extends Data.TaggedError("CollectError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel with elements | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Collect all elements into an array | |
| * const collectEffect = Channel.runCollect(numbersChannel) | |
| * | |
| * // Effect.runSync(collectEffect) // Returns: [1, 2, 3, 4, 5] | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 2.0.0 | |
| */ | |
| export const runCollect = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<Array<OutElem>, OutErr, Env> => | |
| runFold(self, () => [] as Array<OutElem>, (acc, o) => { | |
| acc.push(o) | |
| return acc | |
| }) | |
| /** | |
| * Runs a channel and outputs the done value. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runDone = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<OutDone, OutErr, Env> => runWith(self, identity_, Effect.succeed) | |
| /** | |
| * Runs a channel until the first output element is available, returning it in | |
| * an `Option`. | |
| * | |
| * **Details** | |
| * | |
| * Returns `Option.some` with the first output element, or `Option.none` if the | |
| * channel completes without emitting output. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runHead = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<Option.Option<OutElem>, OutErr, Env> => | |
| Effect.suspend(() => { | |
| let head = Option.none<OutElem>() | |
| return runWith(self, (pull) => | |
| pull.pipe( | |
| Effect.asSome, | |
| Effect.flatMap((head_) => { | |
| head = head_ | |
| return Cause.done() | |
| }) | |
| ), () => Effect.succeed(head)) | |
| }) | |
| /** | |
| * Runs a channel to completion and returns the last output element in an | |
| * `Option`. | |
| * | |
| * **Details** | |
| * | |
| * Returns `Option.some` with the last emitted element, or `Option.none` if the | |
| * channel completes without emitting output. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runLast = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ): Effect.Effect<Option.Option<OutElem>, OutErr, Env> => | |
| Effect.suspend(() => { | |
| const absent = Symbol() // Prevent boxing | |
| let last: typeof absent | OutElem = absent | |
| return runWith( | |
| self, | |
| (pull) => | |
| Effect.forever( | |
| Effect.flatMap(pull, (item) => { | |
| last = item | |
| return Effect.void | |
| }), | |
| { disableYield: true } | |
| ), | |
| () => last === absent ? Effect.succeedNone : Effect.succeedSome(last) | |
| ) | |
| }) | |
| /** | |
| * Runs a channel and folds over all output elements with an accumulator. | |
| * | |
| * **Example** (Folding channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class FoldError extends Data.TaggedError("FoldError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Fold to calculate sum | |
| * const sumEffect = Channel.runFold(numbersChannel, () => 0, (acc, n) => acc + n) | |
| * | |
| * // Effect.runSync(sumEffect) // Returns: 15 | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runFold: { | |
| /** | |
| * Runs a channel and folds over all output elements with an accumulator. | |
| * | |
| * **Example** (Folding channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class FoldError extends Data.TaggedError("FoldError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Fold to calculate sum | |
| * const sumEffect = Channel.runFold(numbersChannel, () => 0, (acc, n) => acc + n) | |
| * | |
| * // Effect.runSync(sumEffect) // Returns: 15 | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <Z, OutElem>(initial: LazyArg<Z>, f: (acc: Z, o: OutElem) => Z): <OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<Z, OutErr, Env> | |
| /** | |
| * Runs a channel and folds over all output elements with an accumulator. | |
| * | |
| * **Example** (Folding channel output) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class FoldError extends Data.TaggedError("FoldError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with numbers | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Fold to calculate sum | |
| * const sumEffect = Channel.runFold(numbersChannel, () => 0, (acc, n) => acc + n) | |
| * | |
| * // Effect.runSync(sumEffect) // Returns: 15 | |
| * ``` | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env, Z>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| initial: LazyArg<Z>, | |
| f: (acc: Z, o: OutElem) => Z | |
| ): Effect.Effect<Z, OutErr, Env> | |
| } = dual(3, <OutElem, OutErr, OutDone, Env, Z>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| initial: LazyArg<Z>, | |
| f: (acc: Z, o: OutElem) => Z | |
| ): Effect.Effect<Z, OutErr, Env> => | |
| Effect.suspend(() => { | |
| let state = initial() | |
| return runWith( | |
| self, | |
| (pull) => | |
| Effect.whileLoop({ | |
| while: constTrue, | |
| body: () => pull, | |
| step: (value) => { | |
| state = f(state, value) | |
| } | |
| }), | |
| () => Effect.succeed(state) | |
| ) | |
| })) | |
| /** | |
| * Runs a channel and effectfully folds all output elements with an accumulator. | |
| * | |
| * **When to use** | |
| * | |
| * Use when folding channel output needs effects, services, or an additional | |
| * failure channel during accumulation. | |
| * | |
| * **Details** | |
| * | |
| * The initial accumulator is evaluated lazily. Each output element is passed to | |
| * the effectful accumulator function. The returned effect succeeds with the | |
| * final accumulator value. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| export const runFoldEffect: { | |
| /** | |
| * Runs a channel and effectfully folds all output elements with an accumulator. | |
| * | |
| * **When to use** | |
| * | |
| * Use when folding channel output needs effects, services, or an additional | |
| * failure channel during accumulation. | |
| * | |
| * **Details** | |
| * | |
| * The initial accumulator is evaluated lazily. Each output element is passed to | |
| * the effectful accumulator function. The returned effect succeeds with the | |
| * final accumulator value. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, Z, E, R>(initial: LazyArg<Z>, f: (acc: Z, o: OutElem) => Effect.Effect<Z, E, R>): <OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<Z, OutErr | E, Env | R> | |
| /** | |
| * Runs a channel and effectfully folds all output elements with an accumulator. | |
| * | |
| * **When to use** | |
| * | |
| * Use when folding channel output needs effects, services, or an additional | |
| * failure channel during accumulation. | |
| * | |
| * **Details** | |
| * | |
| * The initial accumulator is evaluated lazily. Each output element is passed to | |
| * the effectful accumulator function. The returned effect succeeds with the | |
| * final accumulator value. | |
| * | |
| * @category execution | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env, Z, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| initial: LazyArg<Z>, | |
| f: (acc: Z, o: OutElem) => Effect.Effect<Z, E, R> | |
| ): Effect.Effect<Z, OutErr | E, Env | R> | |
| } = dual(3, <OutElem, OutErr, OutDone, Env, Z, E, R>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| initial: LazyArg<Z>, | |
| f: (acc: Z, o: OutElem) => Effect.Effect<Z, E, R> | |
| ): Effect.Effect<Z, OutErr | E, Env | R> => | |
| Effect.suspend(() => { | |
| let state = initial() | |
| return runWith( | |
| self, | |
| (pull) => | |
| Effect.whileLoop({ | |
| while: constTrue, | |
| body: constant(pull.pipe( | |
| Effect.flatMap((o) => f(state, o)), | |
| Effect.map((s) => { | |
| state = s | |
| }) | |
| )), | |
| step: constVoid | |
| }), | |
| () => Effect.succeed(state) | |
| ) | |
| })) | |
| /** | |
| * Converts a channel to a scoped `Pull` for low-level consumption. | |
| * | |
| * **Details** | |
| * | |
| * The effect requires a `Scope`. The returned pull should be consumed only | |
| * while that scope remains open. Pulls are serialized so only one pull is | |
| * evaluated at a time. | |
| * | |
| * **Example** (Converting channels to pulls) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect } from "effect" | |
| * | |
| * class PullError extends Data.TaggedError("PullError")<{ | |
| * readonly step: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Convert to Pull within a scope | |
| * const pullEffect = Effect.scoped( | |
| * Channel.toPull(numbersChannel) | |
| * ) | |
| * | |
| * // Use the Pull to manually consume elements | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| export const toPull: <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect< | |
| Pull.Pull<OutElem, OutErr, OutDone>, | |
| never, | |
| Env | Scope.Scope | |
| > = Effect.fnUntraced( | |
| function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) { | |
| const semaphore = Semaphore.makeUnsafe(1) | |
| const context = yield* Effect.context<Env | Scope.Scope>() | |
| const scope = Context.get(context, Scope.Scope) | |
| const pull = yield* toTransform(self)(Cause.done(), scope) | |
| return pull.pipe( | |
| Effect.provideContext(context), | |
| semaphore.withPermits(1) | |
| ) | |
| }, | |
| // ensure errors are redirected to the pull effect | |
| Effect.catchCause((cause) => Effect.succeed(Effect.failCause(cause))) | |
| ) as any | |
| /** | |
| * Converts a channel to a Pull within an existing scope. | |
| * | |
| * **Example** (Converting channels to scoped pulls) | |
| * | |
| * ```ts | |
| * import { Channel, Data, Effect, Scope } from "effect" | |
| * | |
| * class ScopedPullError extends Data.TaggedError("ScopedPullError")<{ | |
| * readonly reason: string | |
| * }> {} | |
| * | |
| * // Create a channel | |
| * const numbersChannel = Channel.fromIterable([1, 2, 3]) | |
| * | |
| * // Convert to Pull with explicit scope | |
| * const scopedPullEffect = Effect.gen(function*() { | |
| * const scope = yield* Scope.make() | |
| * const pull = yield* Channel.toPullScoped(numbersChannel, scope) | |
| * return pull | |
| * }) | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const toPullScoped = <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| scope: Scope.Scope | |
| ): Effect.Effect<Pull.Pull<OutElem, OutErr, OutDone, Env>, never, Env> => toTransform(self)(Cause.done(), scope) | |
| /** | |
| * Runs a channel and offers each output element into a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const runIntoQueue: { | |
| /** | |
| * Runs a channel and offers each output element into a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr>(queue: Queue.Queue<OutElem, OutErr | Cause.Done>): <OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<void, never, Env> | |
| /** | |
| * Runs a channel and offers each output element into a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| queue: Queue.Queue<OutElem, OutErr | Cause.Done> | |
| ): Effect.Effect<void, never, Env> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| queue: Queue.Queue<OutElem, OutErr | Cause.Done> | |
| ): Effect.Effect<void, never, Env> => | |
| Effect.uninterruptibleMask((restore) => | |
| runForEach(self, (value) => Queue.offer(queue, value)).pipe( | |
| restore, | |
| Effect.exit, | |
| Effect.flatMap((exit) => { | |
| if (Exit.isSuccess(exit)) { | |
| Queue.endUnsafe(queue) | |
| } else { | |
| Queue.failCauseUnsafe(queue, exit.cause) | |
| } | |
| return Effect.void | |
| }) | |
| ) | |
| ) | |
| ) | |
| /** | |
| * Runs a channel that emits non-empty arrays and offers each array element into | |
| * a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const runIntoQueueArray: { | |
| /** | |
| * Runs a channel that emits non-empty arrays and offers each array element into | |
| * a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr>(queue: Queue.Queue<OutElem, OutErr | Cause.Done>): <OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<void, never, Env> | |
| /** | |
| * Runs a channel that emits non-empty arrays and offers each array element into | |
| * a queue. | |
| * | |
| * **Details** | |
| * | |
| * When the channel completes, the queue is ended. When the channel fails, the | |
| * queue is failed with the channel's cause. The returned effect itself | |
| * completes with `void`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| queue: Queue.Queue<OutElem, OutErr | Cause.Done> | |
| ): Effect.Effect<void, never, Env> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| queue: Queue.Queue<OutElem, OutErr | Cause.Done> | |
| ): Effect.Effect<void, never, Env> => | |
| Effect.uninterruptibleMask((restore) => | |
| runForEach(self, (value) => Queue.offerAll(queue, value)).pipe( | |
| restore, | |
| Effect.exit, | |
| Effect.flatMap((exit) => { | |
| if (Exit.isSuccess(exit)) { | |
| Queue.endUnsafe(queue) | |
| } else { | |
| Queue.failCauseUnsafe(queue, exit.cause) | |
| } | |
| return Effect.void | |
| }) | |
| ) | |
| ) | |
| ) | |
| /** | |
| * Creates a scoped queue and forks the channel to feed it for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Output elements are offered to the queue. Channel completion and failure are | |
| * signaled through the queue. The queue is shut down when the surrounding scope | |
| * closes. | |
| * | |
| * **Example** (Converting channels to queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with data | |
| * const dataChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Convert to queue for concurrent processing | |
| * const queueEffect = Channel.toQueue(dataChannel, { capacity: 32 }) | |
| * | |
| * // The queue can be used for concurrent consumption | |
| * // Multiple consumers can read from the queue | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| export const toQueue: { | |
| /** | |
| * Creates a scoped queue and forks the channel to feed it for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Output elements are offered to the queue. Channel completion and failure are | |
| * signaled through the queue. The queue is shut down when the surrounding scope | |
| * closes. | |
| * | |
| * **Example** (Converting channels to queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with data | |
| * const dataChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Convert to queue for concurrent processing | |
| * const queueEffect = Channel.toQueue(dataChannel, { capacity: 32 }) | |
| * | |
| * // The queue can be used for concurrent consumption | |
| * // Multiple consumers can read from the queue | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<Queue.Dequeue<OutElem, OutErr | Cause.Done>, never, Env | Scope.Scope> | |
| /** | |
| * Creates a scoped queue and forks the channel to feed it for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Output elements are offered to the queue. Channel completion and failure are | |
| * signaled through the queue. The queue is shut down when the surrounding scope | |
| * closes. | |
| * | |
| * **Example** (Converting channels to queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with data | |
| * const dataChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Convert to queue for concurrent processing | |
| * const queueEffect = Channel.toQueue(dataChannel, { capacity: 32 }) | |
| * | |
| * // The queue can be used for concurrent consumption | |
| * // Multiple consumers can read from the queue | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Effect.Effect<Queue.Dequeue<OutElem, OutErr | Cause.Done>, never, Env | Scope.Scope> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| Effect.fnUntraced(function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ) { | |
| const scope = yield* Effect.scope | |
| const queue = yield* Queue.make</** | |
| * Creates a scoped queue and forks the channel to feed it for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Output elements are offered to the queue. Channel completion and failure are | |
| * signaled through the queue. The queue is shut down when the surrounding scope | |
| * closes. | |
| * | |
| * **Example** (Converting channels to queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with data | |
| * const dataChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Convert to queue for concurrent processing | |
| * const queueEffect = Channel.toQueue(dataChannel, { capacity: 32 }) | |
| * | |
| * // The queue can be used for concurrent consumption | |
| * // Multiple consumers can read from the queue | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| OutElem, /** | |
| * Creates a scoped queue and forks the channel to feed it for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Output elements are offered to the queue. Channel completion and failure are | |
| * signaled through the queue. The queue is shut down when the surrounding scope | |
| * closes. | |
| * | |
| * **Example** (Converting channels to queues) | |
| * | |
| * ```ts | |
| * import { Channel, Data } from "effect" | |
| * | |
| * class QueueError extends Data.TaggedError("QueueError")<{ | |
| * readonly operation: string | |
| * }> {} | |
| * | |
| * // Create a channel with data | |
| * const dataChannel = Channel.fromIterable([1, 2, 3, 4, 5]) | |
| * | |
| * // Convert to queue for concurrent processing | |
| * const queueEffect = Channel.toQueue(dataChannel, { capacity: 32 }) | |
| * | |
| * // The queue can be used for concurrent consumption | |
| * // Multiple consumers can read from the queue | |
| * ``` | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| OutErr | Cause.Done>({ | |
| capacity: typeof options.capacity === "number" ? options.capacity : undefined, | |
| strategy: typeof options.capacity === "number" ? options.strategy : undefined | |
| }) | |
| yield* Scope.addFinalizer(scope, Queue.shutdown(queue)) | |
| yield* Effect.forkIn(runIntoQueue(self, queue), scope) | |
| return queue | |
| }) | |
| ) | |
| /** | |
| * Creates a scoped queue and forks an array-emitting channel to feed it. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is offered to the queue. Channel | |
| * completion and failure are signaled through the queue. The queue is shut down | |
| * when the surrounding scope closes. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const toQueueArray: { | |
| /** | |
| * Creates a scoped queue and forks an array-emitting channel to feed it. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is offered to the queue. Channel | |
| * completion and failure are signaled through the queue. The queue is shut down | |
| * when the surrounding scope closes. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<Queue.Dequeue<OutElem, OutErr | Cause.Done>, never, Env | Scope.Scope> | |
| /** | |
| * Creates a scoped queue and forks an array-emitting channel to feed it. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is offered to the queue. Channel | |
| * completion and failure are signaled through the queue. The queue is shut down | |
| * when the surrounding scope closes. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ): Effect.Effect<Queue.Dequeue<OutElem, OutErr | Cause.Done>, never, Env | Scope.Scope> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| Effect.fnUntraced(function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| } | |
| ) { | |
| const scope = yield* Effect.scope | |
| const queue = yield* Queue.make</** | |
| * Creates a scoped queue and forks an array-emitting channel to feed it. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is offered to the queue. Channel | |
| * completion and failure are signaled through the queue. The queue is shut down | |
| * when the surrounding scope closes. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| OutElem, /** | |
| * Creates a scoped queue and forks an array-emitting channel to feed it. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is offered to the queue. Channel | |
| * completion and failure are signaled through the queue. The queue is shut down | |
| * when the surrounding scope closes. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| OutErr | Cause.Done>({ | |
| capacity: typeof options.capacity === "number" ? options.capacity : undefined, | |
| strategy: typeof options.capacity === "number" ? options.strategy : undefined | |
| }) | |
| yield* Scope.addFinalizer(scope, Queue.shutdown(queue)) | |
| yield* Effect.forkIn(runIntoQueueArray(self, queue), scope) | |
| return queue | |
| }) | |
| ) | |
| /** | |
| * Converts a channel to a PubSub for concurrent consumption. | |
| * | |
| * **Details** | |
| * | |
| * `shutdownOnEnd` indicates whether the PubSub should be shut down when the | |
| * channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| export const toPubSub: { | |
| /** | |
| * Converts a channel to a PubSub for concurrent consumption. | |
| * | |
| * **Details** | |
| * | |
| * `shutdownOnEnd` indicates whether the PubSub should be shut down when the | |
| * channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<PubSub.PubSub<OutElem>, never, Env | Scope.Scope> | |
| /** | |
| * Converts a channel to a PubSub for concurrent consumption. | |
| * | |
| * **Details** | |
| * | |
| * `shutdownOnEnd` indicates whether the PubSub should be shut down when the | |
| * channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ): Effect.Effect<PubSub.PubSub<OutElem>, never, Env | Scope.Scope> | |
| } = dual( | |
| 2, | |
| Effect.fnUntraced(function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ) { | |
| const pubsub = yield* makePubSub</** | |
| * Converts a channel to a PubSub for concurrent consumption. | |
| * | |
| * **Details** | |
| * | |
| * `shutdownOnEnd` indicates whether the PubSub should be shut down when the | |
| * channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 2.0.0 | |
| */ | |
| OutElem>(options) | |
| yield* Effect.forkScoped(runIntoPubSub(self, pubsub, { | |
| shutdownOnEnd: options.shutdownOnEnd !== false | |
| })) | |
| return pubsub | |
| }) | |
| ) | |
| /** | |
| * Runs a channel and publishes each output element to a `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * The channel's output values are published as individual PubSub messages. Use | |
| * `options.shutdownOnEnd` to shut down the PubSub when channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const runIntoPubSub: { | |
| /** | |
| * Runs a channel and publishes each output element to a `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * The channel's output values are published as individual PubSub messages. Use | |
| * `options.shutdownOnEnd` to shut down the PubSub when channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem>( | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ): <OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<void, never, Env> | |
| /** | |
| * Runs a channel and publishes each output element to a `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * The channel's output values are published as individual PubSub messages. Use | |
| * `options.shutdownOnEnd` to shut down the PubSub when channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ): Effect.Effect<void, never, Env> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<OutElem, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ) => | |
| runForEach(self, (value) => PubSub.publish(pubsub, value)).pipe( | |
| options?.shutdownOnEnd === true ? Effect.ensuring(PubSub.shutdown(pubsub)) : identity_ | |
| ) | |
| ) | |
| const makePubSub = <A>( | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| } | |
| ) => | |
| Effect.acquireRelease( | |
| options.capacity === "unbounded" | |
| ? PubSub.unbounded<A>(options) | |
| : options.strategy === "dropping" | |
| ? PubSub.dropping<A>(options) | |
| : options.strategy === "sliding" | |
| ? PubSub.sliding<A>(options) | |
| : PubSub.bounded<A>(options), | |
| PubSub.shutdown | |
| ) | |
| /** | |
| * Converts an array-emitting channel to a scoped `PubSub` for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. `shutdownOnEnd` indicates whether the PubSub should be shut | |
| * down when the channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const toPubSubArray: { | |
| /** | |
| * Converts an array-emitting channel to a scoped `PubSub` for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. `shutdownOnEnd` indicates whether the PubSub should be shut | |
| * down when the channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<PubSub.PubSub<OutElem>, never, Env | Scope.Scope> | |
| /** | |
| * Converts an array-emitting channel to a scoped `PubSub` for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. `shutdownOnEnd` indicates whether the PubSub should be shut | |
| * down when the channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ): Effect.Effect<PubSub.PubSub<OutElem>, never, Env | Scope.Scope> | |
| } = dual( | |
| 2, | |
| Effect.fnUntraced(function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | |
| ) { | |
| const pubsub = yield* makePubSub</** | |
| * Converts an array-emitting channel to a scoped `PubSub` for concurrent | |
| * consumption. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. `shutdownOnEnd` indicates whether the PubSub should be shut | |
| * down when the channel ends. By default this is `true`. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| OutElem>(options) | |
| yield* Effect.forkScoped(runIntoPubSubArray(self, pubsub, { | |
| shutdownOnEnd: options.shutdownOnEnd !== false | |
| })) | |
| return pubsub | |
| }) | |
| ) | |
| /** | |
| * Runs an array-emitting channel and publishes each array element to a | |
| * `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. Use `options.shutdownOnEnd` to shut down the PubSub when | |
| * channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const runIntoPubSubArray: { | |
| /** | |
| * Runs an array-emitting channel and publishes each array element to a | |
| * `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. Use `options.shutdownOnEnd` to shut down the PubSub when | |
| * channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem>( | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ): <OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect<OutDone, OutErr, Env> | |
| /** | |
| * Runs an array-emitting channel and publishes each array element to a | |
| * `PubSub`. | |
| * | |
| * **Details** | |
| * | |
| * Each element inside emitted non-empty arrays is published as an individual | |
| * PubSub message. Use `options.shutdownOnEnd` to shut down the PubSub when | |
| * channel execution ends. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ): Effect.Effect<OutDone, OutErr, Env> | |
| } = dual( | |
| (args) => isChannel(args[0]), | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| pubsub: PubSub.PubSub<OutElem>, | |
| options?: { | |
| readonly shutdownOnEnd?: boolean | undefined | |
| } | undefined | |
| ) => | |
| runForEach(self, (value) => PubSub.publishAll(pubsub, value)).pipe( | |
| options?.shutdownOnEnd === true ? Effect.ensuring(PubSub.shutdown(pubsub)) : identity_ | |
| ) | |
| ) | |
| /** | |
| * Converts a channel to a scoped `PubSub` of `Take` values. | |
| * | |
| * **Details** | |
| * | |
| * Emitted non-empty arrays are published as output `Take` values. When the | |
| * channel ends, its final `Exit` is published so subscribers can observe | |
| * completion or failure. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| export const toPubSubTake: { | |
| /** | |
| * Converts a channel to a scoped `PubSub` of `Take` values. | |
| * | |
| * **Details** | |
| * | |
| * Emitted non-empty arrays are published as output `Take` values. When the | |
| * channel ends, its final `Exit` is published so subscribers can observe | |
| * completion or failure. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| ( | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| } | |
| ): <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutDone>, OutErr, OutDone, unknown, unknown, unknown, Env> | |
| ) => Effect.Effect< | |
| PubSub.PubSub<Take.Take<OutElem, OutErr, OutDone>>, | |
| never, | |
| Env | Scope.Scope | |
| > | |
| /** | |
| * Converts a channel to a scoped `PubSub` of `Take` values. | |
| * | |
| * **Details** | |
| * | |
| * Emitted non-empty arrays are published as output `Take` values. When the | |
| * channel ends, its final `Exit` is published so subscribers can observe | |
| * completion or failure. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| <OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| } | |
| ): Effect.Effect< | |
| PubSub.PubSub<Take.Take<OutElem, OutErr, OutDone>>, | |
| never, | |
| Env | Scope.Scope | |
| > | |
| } = dual( | |
| 2, | |
| Effect.fnUntraced(function*<OutElem, OutErr, OutDone, Env>( | |
| self: Channel<Arr.NonEmptyReadonlyArray<OutElem>, OutErr, OutDone, unknown, unknown, unknown, Env>, | |
| options: { | |
| readonly capacity: "unbounded" | |
| readonly replay?: number | undefined | |
| } | { | |
| readonly capacity: number | |
| readonly strategy?: "dropping" | "sliding" | "suspend" | undefined | |
| readonly replay?: number | undefined | |
| } | |
| ) { | |
| const pubsub = yield* makePubSub</** | |
| * Converts a channel to a scoped `PubSub` of `Take` values. | |
| * | |
| * **Details** | |
| * | |
| * Emitted non-empty arrays are published as output `Take` values. When the | |
| * channel ends, its final `Exit` is published so subscribers can observe | |
| * completion or failure. | |
| * | |
| * @category destructors | |
| * @since 4.0.0 | |
| */ | |
| Take.Take<OutElem, OutErr, OutDone>>(options) | |
| yield* runForEach(self, (value) => PubSub.publish(pubsub, value)).pipe( | |
| Effect.onExit((exit) => PubSub.publish(pubsub, exit)), | |
| Effect.forkScoped | |
| ) | |
| return pubsub | |
| }) | |
| ) | |
Xet Storage Details
- Size:
- 377 kB
- Xet hash:
- b9d36a2b8e7b3c6855304338c1627a53a2e2dfe6982129d990222d59502e84c8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.