import * as Arr from "../Array.js" import type * as Cause from "../Cause.js" import * as Chunk from "../Chunk.js" import * as Context from "../Context.js" import type * as Deferred from "../Deferred.js" import type * as Differ from "../Differ.js" import * as Duration from "../Duration.js" import type * as Effect from "../Effect.js" import * as Either from "../Either.js" import * as Equal from "../Equal.js" import type * as ExecutionStrategy from "../ExecutionStrategy.js" import type * as Exit from "../Exit.js" import type * as Fiber from "../Fiber.js" import * as FiberId from "../FiberId.js" import type * as FiberRef from "../FiberRef.js" import type * as FiberStatus from "../FiberStatus.js" import type { LazyArg } from "../Function.js" import { dual, identity, pipe } from "../Function.js" import { globalValue } from "../GlobalValue.js" import * as Hash from "../Hash.js" import * as HashMap from "../HashMap.js" import type * as HashSet from "../HashSet.js" import { format, NodeInspectSymbol, toJSON } from "../Inspectable.js" import * as List from "../List.js" import type * as LogLevel from "../LogLevel.js" import type * as LogSpan from "../LogSpan.js" import type * as MetricLabel from "../MetricLabel.js" import * as MutableRef from "../MutableRef.js" import * as Option from "../Option.js" import { pipeArguments } from "../Pipeable.js" import { hasProperty, isObject, isPromiseLike, type Predicate, type Refinement } from "../Predicate.js" import type * as Request from "../Request.js" import type * as BlockedRequests from "../RequestBlock.js" import type * as RequestResolver from "../RequestResolver.js" import type * as RuntimeFlags from "../RuntimeFlags.js" import * as RuntimeFlagsPatch from "../RuntimeFlagsPatch.js" import type * as Scope from "../Scope.js" import type * as Tracer from "../Tracer.js" import type { NoInfer, NotFunction } from "../Types.js" import { internalCall, YieldWrap } from "../Utils.js" import * as blockedRequests_ from "./blockedRequests.js" import * as internalCause from "./cause.js" import * as deferred from "./deferred.js" import * as internalDiffer from "./differ.js" import { CommitPrototype, effectVariance, StructuralCommitPrototype } from "./effectable.js" import { getBugErrorMessage } from "./errors.js" import type * as FiberRuntime from "./fiberRuntime.js" import type * as fiberScope from "./fiberScope.js" import * as DeferredOpCodes from "./opCodes/deferred.js" import * as OpCodes from "./opCodes/effect.js" import * as runtimeFlags_ from "./runtimeFlags.js" import { SingleShotGen } from "./singleShotGen.js" // ----------------------------------------------------------------------------- // Effect // ----------------------------------------------------------------------------- /** * @internal */ export const blocked = ( blockedRequests: BlockedRequests.RequestBlock, _continue: Effect.Effect ): Effect.Blocked => { const effect = new EffectPrimitive("Blocked") as any effect.effect_instruction_i0 = blockedRequests effect.effect_instruction_i1 = _continue return effect } /** * @internal */ export const runRequestBlock = ( blockedRequests: BlockedRequests.RequestBlock ): Effect.Effect => { const effect = new EffectPrimitive("RunBlocked") as any effect.effect_instruction_i0 = blockedRequests return effect } /** @internal */ export const EffectTypeId: Effect.EffectTypeId = Symbol.for("effect/Effect") as Effect.EffectTypeId /** @internal */ export type Primitive = | Async | Commit | Failure | OnFailure | OnSuccess | OnStep | OnSuccessAndFailure | Success | Sync | UpdateRuntimeFlags | While | FromIterator | WithRuntime | Yield | OpTag | Blocked | RunBlocked | Either.Either | Option.Option /** @internal */ export type Continuation = | OnSuccess | OnStep | OnSuccessAndFailure | OnFailure | While | FromIterator | RevertFlags /** @internal */ export class RevertFlags { readonly _op = OpCodes.OP_REVERT_FLAGS constructor( readonly patch: RuntimeFlagsPatch.RuntimeFlagsPatch, readonly op: Primitive & { _op: OpCodes.OP_UPDATE_RUNTIME_FLAGS } ) { } } class EffectPrimitive { public effect_instruction_i0 = undefined public effect_instruction_i1 = undefined public effect_instruction_i2 = undefined public trace = undefined; [EffectTypeId] = effectVariance constructor(readonly _op: Primitive["_op"]) {} [Equal.symbol](this: {}, that: unknown) { return this === that } [Hash.symbol](this: {}) { return Hash.cached(this, Hash.random(this)) } pipe() { return pipeArguments(this, arguments) } toJSON() { return { _id: "Effect", _op: this._op, effect_instruction_i0: toJSON(this.effect_instruction_i0), effect_instruction_i1: toJSON(this.effect_instruction_i1), effect_instruction_i2: toJSON(this.effect_instruction_i2) } } toString() { return format(this.toJSON()) } [NodeInspectSymbol]() { return this.toJSON() } [Symbol.iterator]() { return new SingleShotGen(new YieldWrap(this)) } } /** @internal */ class EffectPrimitiveFailure { public effect_instruction_i0 = undefined public effect_instruction_i1 = undefined public effect_instruction_i2 = undefined public trace = undefined; [EffectTypeId] = effectVariance constructor(readonly _op: Primitive["_op"]) { // @ts-expect-error this._tag = _op } [Equal.symbol](this: {}, that: unknown) { return exitIsExit(that) && that._op === "Failure" && // @ts-expect-error Equal.equals(this.effect_instruction_i0, that.effect_instruction_i0) } [Hash.symbol](this: {}) { return pipe( // @ts-expect-error Hash.string(this._tag), // @ts-expect-error Hash.combine(Hash.hash(this.effect_instruction_i0)), Hash.cached(this) ) } get cause() { return this.effect_instruction_i0 } pipe() { return pipeArguments(this, arguments) } toJSON() { return { _id: "Exit", _tag: this._op, cause: (this.cause as any).toJSON() } } toString() { return format(this.toJSON()) } [NodeInspectSymbol]() { return this.toJSON() } [Symbol.iterator]() { return new SingleShotGen(new YieldWrap(this)) } } /** @internal */ class EffectPrimitiveSuccess { public effect_instruction_i0 = undefined public effect_instruction_i1 = undefined public effect_instruction_i2 = undefined public trace = undefined; [EffectTypeId] = effectVariance constructor(readonly _op: Primitive["_op"]) { // @ts-expect-error this._tag = _op } [Equal.symbol](this: {}, that: unknown) { return exitIsExit(that) && that._op === "Success" && // @ts-expect-error Equal.equals(this.effect_instruction_i0, that.effect_instruction_i0) } [Hash.symbol](this: {}) { return pipe( // @ts-expect-error Hash.string(this._tag), // @ts-expect-error Hash.combine(Hash.hash(this.effect_instruction_i0)), Hash.cached(this) ) } get value() { return this.effect_instruction_i0 } pipe() { return pipeArguments(this, arguments) } toJSON() { return { _id: "Exit", _tag: this._op, value: toJSON(this.value) } } toString() { return format(this.toJSON()) } [NodeInspectSymbol]() { return this.toJSON() } [Symbol.iterator]() { return new SingleShotGen(new YieldWrap(this)) } } /** @internal */ export type Op = Effect.Effect & Body & { readonly _op: Tag } /** @internal */ export interface Async extends Op void): void readonly effect_instruction_i1: FiberId.FiberId }> {} /** @internal */ export interface Blocked extends Op<"Blocked", { readonly effect_instruction_i0: BlockedRequests.RequestBlock readonly effect_instruction_i1: Effect.Effect }> {} /** @internal */ export interface RunBlocked extends Op<"RunBlocked", { readonly effect_instruction_i0: BlockedRequests.RequestBlock }> {} /** @internal */ export interface Failure extends Op }> {} /** @internal */ export interface OpTag extends Op {} /** @internal */ export interface Commit extends Op }> {} /** @internal */ export interface OnFailure extends Op): Primitive }> {} /** @internal */ export interface OnSuccess extends Op {} /** @internal */ export interface OnStep extends Op<"OnStep", { readonly effect_instruction_i0: Primitive }> {} /** @internal */ export interface OnSuccessAndFailure extends Op): Primitive effect_instruction_i2(a: unknown): Primitive }> {} /** @internal */ export interface Success extends Op {} /** @internal */ export interface Sync extends Op {} /** @internal */ export interface UpdateRuntimeFlags extends Op Primitive }> {} /** @internal */ export interface While extends Op {} /** @internal */ export interface FromIterator extends Op, any> }> {} /** @internal */ export interface WithRuntime extends Op, status: FiberStatus.Running): Primitive }> {} /** @internal */ export interface Yield extends Op {} /** @internal */ export const isEffect = (u: unknown): u is Effect.Effect => hasProperty(u, EffectTypeId) /* @internal */ export const withFiberRuntime = ( withRuntime: (fiber: FiberRuntime.FiberRuntime, status: FiberStatus.Running) => Effect.Effect ): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_WITH_RUNTIME) as any effect.effect_instruction_i0 = withRuntime return effect } /* @internal */ export const acquireUseRelease: { ( use: (a: A) => Effect.Effect, release: (a: A, exit: Exit.Exit) => Effect.Effect ): (acquire: Effect.Effect) => Effect.Effect ( acquire: Effect.Effect, use: (a: A) => Effect.Effect, release: (a: A, exit: Exit.Exit) => Effect.Effect ): Effect.Effect } = dual(3, ( acquire: Effect.Effect, use: (a: A) => Effect.Effect, release: (a: A, exit: Exit.Exit) => Effect.Effect ): Effect.Effect => uninterruptibleMask((restore) => flatMap( acquire, (a) => flatMap(exit(suspend(() => restore(use(a)))), (exit): Effect.Effect => { return suspend(() => release(a, exit)).pipe( matchCauseEffect({ onFailure: (cause) => { switch (exit._tag) { case OpCodes.OP_FAILURE: return failCause(internalCause.sequential(exit.effect_instruction_i0, cause)) case OpCodes.OP_SUCCESS: return failCause(cause) } }, onSuccess: () => exit }) ) }) ) )) /* @internal */ export const as: { (value: B): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, value: B): Effect.Effect } = dual( 2, (self: Effect.Effect, value: B): Effect.Effect => flatMap(self, () => succeed(value)) ) /* @internal */ export const asVoid = (self: Effect.Effect): Effect.Effect => as(self, void 0) /* @internal */ export const custom: { (i0: X, body: (this: { effect_instruction_i0: X }) => Effect.Effect): Effect.Effect ( i0: X, i1: Y, body: (this: { effect_instruction_i0: X; effect_instruction_i1: Y }) => Effect.Effect ): Effect.Effect ( i0: X, i1: Y, i2: Z, body: ( this: { effect_instruction_i0: X; effect_instruction_i1: Y; effect_instruction_i2: Z } ) => Effect.Effect ): Effect.Effect } = function() { const wrapper = new EffectPrimitive(OpCodes.OP_COMMIT) as any switch (arguments.length) { case 2: { wrapper.effect_instruction_i0 = arguments[0] wrapper.commit = arguments[1] break } case 3: { wrapper.effect_instruction_i0 = arguments[0] wrapper.effect_instruction_i1 = arguments[1] wrapper.commit = arguments[2] break } case 4: { wrapper.effect_instruction_i0 = arguments[0] wrapper.effect_instruction_i1 = arguments[1] wrapper.effect_instruction_i2 = arguments[2] wrapper.commit = arguments[3] break } default: { throw new Error(getBugErrorMessage("you're not supposed to end up here")) } } return wrapper } /* @internal */ export const unsafeAsync = ( register: ( callback: (_: Effect.Effect) => void ) => void | Effect.Effect, blockingOn: FiberId.FiberId = FiberId.none ): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_ASYNC) as any let cancelerRef: Effect.Effect | void = undefined effect.effect_instruction_i0 = (resume: (_: Effect.Effect) => void) => { cancelerRef = register(resume) } effect.effect_instruction_i1 = blockingOn return onInterrupt(effect, (_) => isEffect(cancelerRef) ? cancelerRef : void_) } /* @internal */ export const asyncInterrupt = ( register: ( callback: (_: Effect.Effect) => void ) => void | Effect.Effect, blockingOn: FiberId.FiberId = FiberId.none ): Effect.Effect => suspend(() => unsafeAsync(register, blockingOn)) const async_ = ( resume: ( callback: (_: Effect.Effect) => void, signal: AbortSignal ) => void | Effect.Effect, blockingOn: FiberId.FiberId = FiberId.none ): Effect.Effect => { return custom(resume, function() { let backingResume: ((_: Effect.Effect) => void) | undefined = undefined let pendingEffect: Effect.Effect | undefined = undefined function proxyResume(effect: Effect.Effect) { if (backingResume) { backingResume(effect) } else if (pendingEffect === undefined) { pendingEffect = effect } } const effect = new EffectPrimitive(OpCodes.OP_ASYNC) as any effect.effect_instruction_i0 = (resume: (_: Effect.Effect) => void) => { backingResume = resume if (pendingEffect) { resume(pendingEffect) } } effect.effect_instruction_i1 = blockingOn let cancelerRef: Effect.Effect | void = undefined let controllerRef: AbortController | void = undefined if (this.effect_instruction_i0.length !== 1) { controllerRef = new AbortController() cancelerRef = internalCall(() => this.effect_instruction_i0(proxyResume, controllerRef!.signal)) } else { cancelerRef = internalCall(() => (this.effect_instruction_i0 as any)(proxyResume)) } return (cancelerRef || controllerRef) ? onInterrupt(effect, (_) => { if (controllerRef) { controllerRef.abort() } return cancelerRef ?? void_ }) : effect }) } export { /** @internal */ async_ as async } /* @internal */ export const catchAllCause = dual< ( f: (cause: Cause.Cause) => Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, f: (cause: Cause.Cause) => Effect.Effect ) => Effect.Effect >(2, (self, f) => { const effect = new EffectPrimitive(OpCodes.OP_ON_FAILURE) as any effect.effect_instruction_i0 = self effect.effect_instruction_i1 = f return effect }) /* @internal */ export const catchAll: { ( f: (e: E) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, f: (e: E) => Effect.Effect ): Effect.Effect } = dual( 2, ( self: Effect.Effect, f: (e: E) => Effect.Effect ): Effect.Effect => matchEffect(self, { onFailure: f, onSuccess: succeed }) ) /* @internal */ export const catchIf: { ( refinement: Refinement, EB>, f: (e: EB) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect, R2 | R> ( predicate: Predicate>, f: (e: NoInfer) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Refinement, f: (e: EB) => Effect.Effect ): Effect.Effect, R2 | R> ( self: Effect.Effect, predicate: Predicate, f: (e: E) => Effect.Effect ): Effect.Effect } = dual(3, ( self: Effect.Effect, predicate: Predicate, f: (e: E) => Effect.Effect ): Effect.Effect => catchAllCause(self, (cause): Effect.Effect => { const either = internalCause.failureOrCause(cause) switch (either._tag) { case "Left": return predicate(either.left) ? f(either.left) : failCause(cause) case "Right": return failCause(either.right) } })) /* @internal */ export const catchSome = dual< ( pf: (e: NoInfer) => Option.Option> ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, pf: (e: NoInfer) => Option.Option> ) => Effect.Effect >(2, ( self: Effect.Effect, pf: (e: NoInfer) => Option.Option> ) => catchAllCause(self, (cause): Effect.Effect => { const either = internalCause.failureOrCause(cause) switch (either._tag) { case "Left": return pipe(pf(either.left), Option.getOrElse(() => failCause(cause))) case "Right": return failCause(either.right) } })) /* @internal */ export const checkInterruptible = ( f: (isInterruptible: boolean) => Effect.Effect ): Effect.Effect => withFiberRuntime((_, status) => f(runtimeFlags_.interruption(status.runtimeFlags))) const originalSymbol = Symbol.for("effect/OriginalAnnotation") /* @internal */ export const originalInstance = (obj: E): E => { if (hasProperty(obj, originalSymbol)) { // @ts-expect-error return obj[originalSymbol] } return obj } /* @internal */ export const capture = (obj: E & object, span: Option.Option): E => { if (Option.isSome(span)) { return new Proxy(obj, { has(target, p) { return p === internalCause.spanSymbol || p === originalSymbol || p in target }, get(target, p) { if (p === internalCause.spanSymbol) { return span.value } if (p === originalSymbol) { return obj } // @ts-expect-error return target[p] } }) } return obj } /* @internal */ export const die = (defect: unknown): Effect.Effect => isObject(defect) && !(internalCause.spanSymbol in defect) ? withFiberRuntime((fiber) => failCause(internalCause.die(capture(defect, currentSpanFromFiber(fiber))))) : failCause(internalCause.die(defect)) /* @internal */ export const dieMessage = (message: string): Effect.Effect => failCauseSync(() => internalCause.die(new RuntimeException(message))) /* @internal */ export const dieSync = (evaluate: LazyArg): Effect.Effect => flatMap(sync(evaluate), die) /* @internal */ export const either = (self: Effect.Effect): Effect.Effect, never, R> => matchEffect(self, { onFailure: (e) => succeed(Either.left(e)), onSuccess: (a) => succeed(Either.right(a)) }) /* @internal */ export const exit = (self: Effect.Effect): Effect.Effect, never, R> => matchCause(self, { onFailure: exitFailCause, onSuccess: exitSucceed }) /* @internal */ export const fail = (error: E): Effect.Effect => isObject(error) && !(internalCause.spanSymbol in error) ? withFiberRuntime((fiber) => failCause(internalCause.fail(capture(error, currentSpanFromFiber(fiber))))) : failCause(internalCause.fail(error)) /* @internal */ export const failSync = (evaluate: LazyArg): Effect.Effect => flatMap(sync(evaluate), fail) /* @internal */ export const failCause = (cause: Cause.Cause): Effect.Effect => { const effect = new EffectPrimitiveFailure(OpCodes.OP_FAILURE) as any effect.effect_instruction_i0 = cause return effect } /* @internal */ export const failCauseSync = ( evaluate: LazyArg> ): Effect.Effect => flatMap(sync(evaluate), failCause) /* @internal */ export const fiberId: Effect.Effect = withFiberRuntime((state) => succeed(state.id())) /* @internal */ export const fiberIdWith = ( f: (descriptor: FiberId.Runtime) => Effect.Effect ): Effect.Effect => withFiberRuntime((state) => f(state.id())) /* @internal */ export const flatMap = dual< ( f: (a: A) => Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, f: (a: A) => Effect.Effect ) => Effect.Effect >( 2, (self, f) => { const effect = new EffectPrimitive(OpCodes.OP_ON_SUCCESS) as any effect.effect_instruction_i0 = self effect.effect_instruction_i1 = f return effect } ) /* @internal */ export const andThen: { ( f: (a: NoInfer) => X ): ( self: Effect.Effect ) => [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( f: NotFunction ): ( self: Effect.Effect ) => [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( self: Effect.Effect, f: (a: NoInfer) => X ): [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( self: Effect.Effect, f: NotFunction ): [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect } = dual(2, (self, f) => flatMap(self, (a) => { const b = typeof f === "function" ? (f as any)(a) : f if (isEffect(b)) { return b } else if (isPromiseLike(b)) { return unsafeAsync((resume) => { b.then((a) => resume(succeed(a)), (e) => resume(fail(new UnknownException(e, "An unknown error occurred in Effect.andThen")))) }) } return succeed(b) })) /* @internal */ export const step = ( self: Effect.Effect ): Effect.Effect | Effect.Blocked, never, R> => { const effect = new EffectPrimitive("OnStep") as any effect.effect_instruction_i0 = self return effect } /* @internal */ export const flatten = ( self: Effect.Effect, E, R> ): Effect.Effect => flatMap(self, identity) /* @internal */ export const flip = (self: Effect.Effect): Effect.Effect => matchEffect(self, { onFailure: succeed, onSuccess: fail }) /* @internal */ export const matchCause: { ( options: { readonly onFailure: (cause: Cause.Cause) => A2 readonly onSuccess: (a: A) => A3 } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly onFailure: (cause: Cause.Cause) => A2 readonly onSuccess: (a: A) => A3 } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly onFailure: (cause: Cause.Cause) => A2 readonly onSuccess: (a: A) => A3 } ): Effect.Effect => matchCauseEffect(self, { onFailure: (cause) => succeed(options.onFailure(cause)), onSuccess: (a) => succeed(options.onSuccess(a)) })) /* @internal */ export const matchCauseEffect: { ( options: { readonly onFailure: (cause: Cause.Cause) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly onFailure: (cause: Cause.Cause) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly onFailure: (cause: Cause.Cause) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_ON_SUCCESS_AND_FAILURE) as any effect.effect_instruction_i0 = self effect.effect_instruction_i1 = options.onFailure effect.effect_instruction_i2 = options.onSuccess return effect }) /* @internal */ export const matchEffect: { ( options: { readonly onFailure: (e: E) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly onFailure: (e: E) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly onFailure: (e: E) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ): Effect.Effect => matchCauseEffect(self, { onFailure: (cause) => { const defects = internalCause.defects(cause) if (defects.length > 0) { return failCause(internalCause.electFailures(cause)) } const failures = internalCause.failures(cause) if (failures.length > 0) { return options.onFailure(Chunk.unsafeHead(failures)) } return failCause(cause as Cause.Cause) }, onSuccess: options.onSuccess })) /* @internal */ export const forEachSequential: { (f: (a: A, i: number) => Effect.Effect): (self: Iterable) => Effect.Effect, E, R> (self: Iterable, f: (a: A, i: number) => Effect.Effect): Effect.Effect, E, R> } = dual( 2, (self: Iterable, f: (a: A, i: number) => Effect.Effect): Effect.Effect, E, R> => suspend(() => { const arr = Arr.fromIterable(self) const ret = Arr.allocate(arr.length) let i = 0 return as( whileLoop({ while: () => i < arr.length, body: () => f(arr[i], i), step: (b) => { ret[i++] = b } }), ret as Array ) }) ) /* @internal */ export const forEachSequentialDiscard: { (f: (a: A, i: number) => Effect.Effect): (self: Iterable) => Effect.Effect (self: Iterable, f: (a: A, i: number) => Effect.Effect): Effect.Effect } = dual( 2, (self: Iterable, f: (a: A, i: number) => Effect.Effect): Effect.Effect => suspend(() => { const arr = Arr.fromIterable(self) let i = 0 return whileLoop({ while: () => i < arr.length, body: () => f(arr[i], i), step: () => { i++ } }) }) ) /* @internal */ export const if_ = dual< ( options: { readonly onTrue: LazyArg> readonly onFalse: LazyArg> } ) => ( self: Effect.Effect | boolean ) => Effect.Effect, ( self: Effect.Effect | boolean, options: { readonly onTrue: LazyArg> readonly onFalse: LazyArg> } ) => Effect.Effect >( (args) => typeof args[0] === "boolean" || isEffect(args[0]), ( self: Effect.Effect | boolean, options: { readonly onTrue: LazyArg> readonly onFalse: LazyArg> } ): Effect.Effect => isEffect(self) ? flatMap(self, (b): Effect.Effect => (b ? options.onTrue() : options.onFalse())) : self ? options.onTrue() : options.onFalse() ) /* @internal */ export const interrupt: Effect.Effect = flatMap(fiberId, (fiberId) => interruptWith(fiberId)) /* @internal */ export const interruptWith = (fiberId: FiberId.FiberId): Effect.Effect => failCause(internalCause.interrupt(fiberId)) /* @internal */ export const interruptible = (self: Effect.Effect): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = RuntimeFlagsPatch.enable(runtimeFlags_.Interruption) effect.effect_instruction_i1 = () => self return effect } /* @internal */ export const interruptibleMask = ( f: (restore: (effect: Effect.Effect) => Effect.Effect) => Effect.Effect ): Effect.Effect => custom(f, function() { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = RuntimeFlagsPatch.enable(runtimeFlags_.Interruption) effect.effect_instruction_i1 = (oldFlags: RuntimeFlags.RuntimeFlags) => runtimeFlags_.interruption(oldFlags) ? internalCall(() => this.effect_instruction_i0(interruptible)) : internalCall(() => this.effect_instruction_i0(uninterruptible)) return effect }) /* @internal */ export const intoDeferred: { (deferred: Deferred.Deferred): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, deferred: Deferred.Deferred): Effect.Effect } = dual( 2, (self: Effect.Effect, deferred: Deferred.Deferred): Effect.Effect => uninterruptibleMask((restore) => flatMap( exit(restore(self)), (exit) => deferredDone(deferred, exit) ) ) ) /* @internal */ export const map: { (f: (a: A) => B): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, f: (a: A) => B): Effect.Effect } = dual( 2, (self: Effect.Effect, f: (a: A) => B): Effect.Effect => flatMap(self, (a) => sync(() => f(a))) ) /* @internal */ export const mapBoth: { ( options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 } ): Effect.Effect => matchEffect(self, { onFailure: (e) => failSync(() => options.onFailure(e)), onSuccess: (a) => sync(() => options.onSuccess(a)) })) /* @internal */ export const mapError: { (f: (e: E) => E2): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, f: (e: E) => E2): Effect.Effect } = dual( 2, (self: Effect.Effect, f: (e: E) => E2): Effect.Effect => matchCauseEffect(self, { onFailure: (cause) => { const either = internalCause.failureOrCause(cause) switch (either._tag) { case "Left": { return failSync(() => f(either.left)) } case "Right": { return failCause(either.right) } } }, onSuccess: succeed }) ) /* @internal */ export const onError: { ( cleanup: (cause: Cause.Cause) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, cleanup: (cause: Cause.Cause) => Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, cleanup: (cause: Cause.Cause) => Effect.Effect ): Effect.Effect => onExit(self, (exit) => exitIsSuccess(exit) ? void_ : cleanup(exit.effect_instruction_i0))) /* @internal */ export const onExit: { ( cleanup: (exit: Exit.Exit) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, cleanup: (exit: Exit.Exit) => Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, cleanup: (exit: Exit.Exit) => Effect.Effect ): Effect.Effect => uninterruptibleMask((restore) => matchCauseEffect(restore(self), { onFailure: (cause1) => { const result = exitFailCause(cause1) return matchCauseEffect(cleanup(result), { onFailure: (cause2) => exitFailCause(internalCause.sequential(cause1, cause2)), onSuccess: () => result }) }, onSuccess: (success) => { const result = exitSucceed(success) return zipRight(cleanup(result), result) } }) )) /* @internal */ export const onInterrupt: { ( cleanup: (interruptors: HashSet.HashSet) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, cleanup: (interruptors: HashSet.HashSet) => Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, cleanup: (interruptors: HashSet.HashSet) => Effect.Effect ): Effect.Effect => onExit( self, exitMatch({ onFailure: (cause) => internalCause.isInterruptedOnly(cause) ? asVoid(cleanup(internalCause.interruptors(cause))) : void_, onSuccess: () => void_ }) )) /* @internal */ export const orElse: { ( that: LazyArg> ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, that: LazyArg> ): Effect.Effect } = dual( 2, ( self: Effect.Effect, that: LazyArg> ): Effect.Effect => attemptOrElse(self, that, succeed) ) /* @internal */ export const orDie = (self: Effect.Effect): Effect.Effect => orDieWith(self, identity) /* @internal */ export const orDieWith: { (f: (error: E) => unknown): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, f: (error: E) => unknown): Effect.Effect } = dual( 2, (self: Effect.Effect, f: (error: E) => unknown): Effect.Effect => matchEffect(self, { onFailure: (e) => die(f(e)), onSuccess: succeed }) ) /* @internal */ export const partitionMap: ( elements: Iterable, f: (a: A) => Either.Either ) => [left: Array, right: Array] = Arr.partitionMap /* @internal */ export const runtimeFlags: Effect.Effect = withFiberRuntime((_, status) => succeed(status.runtimeFlags) ) /* @internal */ export const succeed = (value: A): Effect.Effect => { const effect = new EffectPrimitiveSuccess(OpCodes.OP_SUCCESS) as any effect.effect_instruction_i0 = value return effect } /* @internal */ export const suspend = (evaluate: LazyArg>): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_COMMIT) as any effect.commit = evaluate return effect } /* @internal */ export const sync = (thunk: LazyArg): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_SYNC) as any effect.effect_instruction_i0 = thunk return effect } /* @internal */ export const tap = dual< { ( f: (a: NoInfer) => X ): ( self: Effect.Effect ) => [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( f: (a: NoInfer) => Effect.Effect, options: { onlyEffect: true } ): ( self: Effect.Effect ) => Effect.Effect ( f: NotFunction ): ( self: Effect.Effect ) => [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( f: Effect.Effect, options: { onlyEffect: true } ): ( self: Effect.Effect ) => Effect.Effect }, { ( self: Effect.Effect, f: (a: NoInfer) => X ): [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( self: Effect.Effect, f: (a: NoInfer) => Effect.Effect, options: { onlyEffect: true } ): Effect.Effect ( self: Effect.Effect, f: NotFunction ): [X] extends [Effect.Effect] ? Effect.Effect : [X] extends [PromiseLike] ? Effect.Effect : Effect.Effect ( self: Effect.Effect, f: Effect.Effect, options: { onlyEffect: true } ): Effect.Effect } >( (args) => args.length === 3 || args.length === 2 && !(isObject(args[1]) && "onlyEffect" in args[1]), (self: Effect.Effect, f: X) => flatMap(self, (a) => { const b = typeof f === "function" ? (f as any)(a) : f if (isEffect(b)) { return as(b, a) } else if (isPromiseLike(b)) { return unsafeAsync((resume) => { b.then((_) => resume(succeed(a)), (e) => resume(fail(new UnknownException(e, "An unknown error occurred in Effect.tap")))) }) } return succeed(a) }) ) /* @internal */ export const transplant = ( f: (grafter: (effect: Effect.Effect) => Effect.Effect) => Effect.Effect ): Effect.Effect => withFiberRuntime((state) => { const scopeOverride = state.getFiberRef(currentForkScopeOverride) const scope = pipe(scopeOverride, Option.getOrElse(() => state.scope())) return f(fiberRefLocally(currentForkScopeOverride, Option.some(scope))) }) /* @internal */ export const attemptOrElse: { ( that: LazyArg>, onSuccess: (a: A) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, that: LazyArg>, onSuccess: (a: A) => Effect.Effect ): Effect.Effect } = dual(3, ( self: Effect.Effect, that: LazyArg>, onSuccess: (a: A) => Effect.Effect ): Effect.Effect => matchCauseEffect(self, { onFailure: (cause) => { const defects = internalCause.defects(cause) if (defects.length > 0) { return failCause(Option.getOrThrow(internalCause.keepDefectsAndElectFailures(cause))) } return that() }, onSuccess })) /* @internal */ export const uninterruptible: (self: Effect.Effect) => Effect.Effect = ( self: Effect.Effect ): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = RuntimeFlagsPatch.disable(runtimeFlags_.Interruption) effect.effect_instruction_i1 = () => self return effect } /* @internal */ export const uninterruptibleMask = ( f: (restore: (effect: Effect.Effect) => Effect.Effect) => Effect.Effect ): Effect.Effect => custom(f, function() { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = RuntimeFlagsPatch.disable(runtimeFlags_.Interruption) effect.effect_instruction_i1 = (oldFlags: RuntimeFlags.RuntimeFlags) => runtimeFlags_.interruption(oldFlags) ? internalCall(() => this.effect_instruction_i0(interruptible)) : internalCall(() => this.effect_instruction_i0(uninterruptible)) return effect }) const void_: Effect.Effect = succeed(void 0) export { /* @internal */ void_ as void } /* @internal */ export const updateRuntimeFlags = (patch: RuntimeFlagsPatch.RuntimeFlagsPatch): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = patch effect.effect_instruction_i1 = void 0 return effect } /* @internal */ export const whenEffect: { ( condition: Effect.Effect ): ( effect: Effect.Effect ) => Effect.Effect, E | E2, R | R2> ( self: Effect.Effect, condition: Effect.Effect ): Effect.Effect, E | E2, R | R2> } = dual(2, ( self: Effect.Effect, condition: Effect.Effect ): Effect.Effect, E | E2, R | R2> => flatMap(condition, (b) => { if (b) { return pipe(self, map(Option.some)) } return succeed(Option.none()) })) /* @internal */ export const whileLoop = ( options: { readonly while: LazyArg readonly body: LazyArg> readonly step: (a: A) => void } ): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_WHILE) as any effect.effect_instruction_i0 = options.while effect.effect_instruction_i1 = options.body effect.effect_instruction_i2 = options.step return effect } /* @internal */ export const fromIterator = >, AEff>( iterator: LazyArg> ): Effect.Effect< AEff, [Eff] extends [never] ? never : [Eff] extends [YieldWrap>] ? E : never, [Eff] extends [never] ? never : [Eff] extends [YieldWrap>] ? R : never > => suspend(() => { const effect = new EffectPrimitive(OpCodes.OP_ITERATOR) as any effect.effect_instruction_i0 = iterator() return effect }) /* @internal */ export const gen: typeof Effect.gen = function() { const f = arguments.length === 1 ? arguments[0] : arguments[1].bind(arguments[0]) return fromIterator(() => f(pipe)) } /** @internal */ export const fnUntraced: Effect.fn.Untraced = (body: Function, ...pipeables: Array) => Object.defineProperty( pipeables.length === 0 ? function(this: any, ...args: Array) { return fromIterator(() => body.apply(this, args)) } : function(this: any, ...args: Array) { let effect = fromIterator(() => body.apply(this, args)) for (const x of pipeables) { effect = x(effect, ...args) } return effect }, "length", { value: body.length, configurable: true } ) /* @internal */ export const withConcurrency = dual< (concurrency: number | "unbounded") => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, concurrency: number | "unbounded") => Effect.Effect >(2, (self, concurrency) => fiberRefLocally(self, currentConcurrency, concurrency)) /* @internal */ export const withRequestBatching = dual< (requestBatching: boolean) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, requestBatching: boolean) => Effect.Effect >(2, (self, requestBatching) => fiberRefLocally(self, currentRequestBatching, requestBatching)) /* @internal */ export const withRuntimeFlags = dual< (update: RuntimeFlagsPatch.RuntimeFlagsPatch) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, update: RuntimeFlagsPatch.RuntimeFlagsPatch) => Effect.Effect >(2, (self, update) => { const effect = new EffectPrimitive(OpCodes.OP_UPDATE_RUNTIME_FLAGS) as any effect.effect_instruction_i0 = update effect.effect_instruction_i1 = () => self return effect }) /** @internal */ export const withTracerEnabled = dual< (enabled: boolean) => (effect: Effect.Effect) => Effect.Effect, (effect: Effect.Effect, enabled: boolean) => Effect.Effect >(2, (effect, enabled) => fiberRefLocally( effect, currentTracerEnabled, enabled )) /** @internal */ export const withTracerTiming = dual< (enabled: boolean) => (effect: Effect.Effect) => Effect.Effect, (effect: Effect.Effect, enabled: boolean) => Effect.Effect >(2, (effect, enabled) => fiberRefLocally( effect, currentTracerTimingEnabled, enabled )) /* @internal */ export const yieldNow = (options?: { readonly priority?: number | undefined }): Effect.Effect => { const effect = new EffectPrimitive(OpCodes.OP_YIELD) as any return typeof options?.priority !== "undefined" ? withSchedulingPriority(effect, options.priority) : effect } /* @internal */ export const zip = dual< ( that: Effect.Effect ) => ( self: Effect.Effect ) => Effect.Effect<[A, A2], E | E2, R | R2>, ( self: Effect.Effect, that: Effect.Effect ) => Effect.Effect<[A, A2], E | E2, R | R2> >(2, ( self: Effect.Effect, that: Effect.Effect ): Effect.Effect<[A, A2], E | E2, R | R2> => flatMap(self, (a) => map(that, (b) => [a, b]))) /* @internal */ export const zipFlatten: { ( that: Effect.Effect ): , E, R>( self: Effect.Effect ) => Effect.Effect<[...A, A2], E | E2, R | R2> , E, R, A2, E2, R2>( self: Effect.Effect, that: Effect.Effect ): Effect.Effect<[...A, A2], E | E2, R | R2> } = dual(2, , E, R, A2, E2, R2>( self: Effect.Effect, that: Effect.Effect ): Effect.Effect<[...A, A2], E | E2, R | R2> => flatMap(self, (a) => map(that, (b) => [...a, b]))) /* @internal */ export const zipLeft: { ( that: Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, that: Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, that: Effect.Effect ): Effect.Effect => flatMap(self, (a) => as(that, a))) /* @internal */ export const zipRight: { ( that: Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, that: Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, that: Effect.Effect ): Effect.Effect => flatMap(self, () => that)) /* @internal */ export const zipWith: { ( that: Effect.Effect, f: (a: A, b: A2) => B ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, that: Effect.Effect, f: (a: A, b: A2) => B ): Effect.Effect } = dual(3, ( self: Effect.Effect, that: Effect.Effect, f: (a: A, b: A2) => B ): Effect.Effect => flatMap(self, (a) => map(that, (b) => f(a, b)))) /* @internal */ export const never: Effect.Effect = asyncInterrupt(() => { const interval = setInterval(() => { // }, 2 ** 31 - 1) return sync(() => clearInterval(interval)) }) // ----------------------------------------------------------------------------- // Fiber // ----------------------------------------------------------------------------- /* @internal */ export const interruptFiber = (self: Fiber.Fiber): Effect.Effect> => flatMap(fiberId, (fiberId) => pipe(self, interruptAsFiber(fiberId))) /* @internal */ export const interruptAsFiber = dual< (fiberId: FiberId.FiberId) => (self: Fiber.Fiber) => Effect.Effect>, (self: Fiber.Fiber, fiberId: FiberId.FiberId) => Effect.Effect> >(2, (self, fiberId) => flatMap(self.interruptAsFork(fiberId), () => self.await)) // ----------------------------------------------------------------------------- // LogLevel // ----------------------------------------------------------------------------- /** @internal */ export const logLevelAll: LogLevel.LogLevel = { _tag: "All", syslog: 0, label: "ALL", ordinal: Number.MIN_SAFE_INTEGER, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelFatal: LogLevel.LogLevel = { _tag: "Fatal", syslog: 2, label: "FATAL", ordinal: 50000, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelError: LogLevel.LogLevel = { _tag: "Error", syslog: 3, label: "ERROR", ordinal: 40000, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelWarning: LogLevel.LogLevel = { _tag: "Warning", syslog: 4, label: "WARN", ordinal: 30000, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelInfo: LogLevel.LogLevel = { _tag: "Info", syslog: 6, label: "INFO", ordinal: 20000, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelDebug: LogLevel.LogLevel = { _tag: "Debug", syslog: 7, label: "DEBUG", ordinal: 10000, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelTrace: LogLevel.LogLevel = { _tag: "Trace", syslog: 7, label: "TRACE", ordinal: 0, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const logLevelNone: LogLevel.LogLevel = { _tag: "None", syslog: 7, label: "OFF", ordinal: Number.MAX_SAFE_INTEGER, pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const allLogLevels: ReadonlyArray = [ logLevelAll, logLevelTrace, logLevelDebug, logLevelInfo, logLevelWarning, logLevelError, logLevelFatal, logLevelNone ] // ----------------------------------------------------------------------------- // FiberRef // ----------------------------------------------------------------------------- /** @internal */ const FiberRefSymbolKey = "effect/FiberRef" /** @internal */ export const FiberRefTypeId: FiberRef.FiberRefTypeId = Symbol.for( FiberRefSymbolKey ) as FiberRef.FiberRefTypeId const fiberRefVariance = { /* c8 ignore next */ _A: (_: any) => _ } /* @internal */ export const fiberRefGet = (self: FiberRef.FiberRef): Effect.Effect => withFiberRuntime((fiber) => exitSucceed(fiber.getFiberRef(self))) /* @internal */ export const fiberRefGetAndSet = dual< (value: A) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, value: A) => Effect.Effect >(2, (self, value) => fiberRefModify(self, (v) => [v, value] as const)) /* @internal */ export const fiberRefGetAndUpdate = dual< (f: (a: A) => A) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, f: (a: A) => A) => Effect.Effect >(2, (self, f) => fiberRefModify(self, (v) => [v, f(v)] as const)) /* @internal */ export const fiberRefGetAndUpdateSome = dual< ( pf: (a: A) => Option.Option ) => (self: FiberRef.FiberRef) => Effect.Effect, ( self: FiberRef.FiberRef, pf: (a: A) => Option.Option ) => Effect.Effect >(2, (self, pf) => fiberRefModify(self, (v) => [v, Option.getOrElse(pf(v), () => v)] as const)) /* @internal */ export const fiberRefGetWith = dual< (f: (a: A) => Effect.Effect) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, f: (a: A) => Effect.Effect) => Effect.Effect >(2, (self, f) => flatMap(fiberRefGet(self), f)) /* @internal */ export const fiberRefSet = dual< (value: A) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, value: A) => Effect.Effect >(2, (self, value) => fiberRefModify(self, () => [void 0, value] as const)) /* @internal */ export const fiberRefDelete = (self: FiberRef.FiberRef): Effect.Effect => withFiberRuntime((state) => { state.unsafeDeleteFiberRef(self) return void_ }) /* @internal */ export const fiberRefReset = (self: FiberRef.FiberRef): Effect.Effect => fiberRefSet(self, self.initial) /* @internal */ export const fiberRefModify = dual< (f: (a: A) => readonly [B, A]) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, f: (a: A) => readonly [B, A]) => Effect.Effect >(2, ( self: FiberRef.FiberRef, f: (a: A) => readonly [B, A] ): Effect.Effect => withFiberRuntime((state) => { const [b, a] = f(state.getFiberRef(self) as A) state.setFiberRef(self, a) return succeed(b) })) /* @internal */ export const fiberRefModifySome = ( self: FiberRef.FiberRef, def: B, f: (a: A) => Option.Option ): Effect.Effect => fiberRefModify(self, (v) => Option.getOrElse(f(v), () => [def, v] as const)) /* @internal */ export const fiberRefUpdate = dual< (f: (a: A) => A) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, f: (a: A) => A) => Effect.Effect >(2, (self, f) => fiberRefModify(self, (v) => [void 0, f(v)] as const)) /* @internal */ export const fiberRefUpdateSome = dual< (pf: (a: A) => Option.Option) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, pf: (a: A) => Option.Option) => Effect.Effect >(2, (self, pf) => fiberRefModify(self, (v) => [void 0, Option.getOrElse(pf(v), () => v)] as const)) /* @internal */ export const fiberRefUpdateAndGet = dual< (f: (a: A) => A) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, f: (a: A) => A) => Effect.Effect >(2, (self, f) => fiberRefModify(self, (v) => { const result = f(v) return [result, result] as const })) /* @internal */ export const fiberRefUpdateSomeAndGet = dual< (pf: (a: A) => Option.Option) => (self: FiberRef.FiberRef) => Effect.Effect, (self: FiberRef.FiberRef, pf: (a: A) => Option.Option) => Effect.Effect >(2, (self, pf) => fiberRefModify(self, (v) => { const result = Option.getOrElse(pf(v), () => v) return [result, result] as const })) // circular /** @internal */ const RequestResolverSymbolKey = "effect/RequestResolver" /** @internal */ export const RequestResolverTypeId: RequestResolver.RequestResolverTypeId = Symbol.for( RequestResolverSymbolKey ) as RequestResolver.RequestResolverTypeId const requestResolverVariance = { /* c8 ignore next */ _A: (_: unknown) => _, /* c8 ignore next */ _R: (_: never) => _ } /** @internal */ export class RequestResolverImpl implements RequestResolver.RequestResolver { readonly [RequestResolverTypeId] = requestResolverVariance constructor( readonly runAll: ( requests: Array>> ) => Effect.Effect, readonly target?: unknown ) { } [Hash.symbol](): number { return Hash.cached(this, this.target ? Hash.hash(this.target) : Hash.random(this)) } [Equal.symbol](that: unknown): boolean { return this.target ? isRequestResolver(that) && Equal.equals(this.target, (that as RequestResolverImpl).target) : this === that } identified(...ids: Array): RequestResolver.RequestResolver { return new RequestResolverImpl(this.runAll, Chunk.fromIterable(ids)) } pipe() { return pipeArguments(this, arguments) } } /** @internal */ export const isRequestResolver = (u: unknown): u is RequestResolver.RequestResolver => hasProperty(u, RequestResolverTypeId) // end /** @internal */ export const resolverLocally = dual< ( self: FiberRef.FiberRef, value: A ) => >( use: RequestResolver.RequestResolver ) => RequestResolver.RequestResolver, , A>( use: RequestResolver.RequestResolver, self: FiberRef.FiberRef, value: A ) => RequestResolver.RequestResolver >(3, , A>( use: RequestResolver.RequestResolver, self: FiberRef.FiberRef, value: A ): RequestResolver.RequestResolver => new RequestResolverImpl( (requests) => fiberRefLocally( use.runAll(requests), self, value ), Chunk.make("Locally", use, self, value) )) /** @internal */ export const requestBlockLocally = ( self: BlockedRequests.RequestBlock, ref: FiberRef.FiberRef, value: A ): BlockedRequests.RequestBlock => blockedRequests_.reduce(self, LocallyReducer(ref, value)) const LocallyReducer = ( ref: FiberRef.FiberRef, value: A ): BlockedRequests.RequestBlock.Reducer => ({ emptyCase: () => blockedRequests_.empty, parCase: (left, right) => blockedRequests_.par(left, right), seqCase: (left, right) => blockedRequests_.seq(left, right), singleCase: (dataSource, blockedRequest) => blockedRequests_.single( resolverLocally(dataSource, ref, value), blockedRequest as any ) }) /* @internal */ export const fiberRefLocally: { (self: FiberRef.FiberRef, value: A): (use: Effect.Effect) => Effect.Effect (use: Effect.Effect, self: FiberRef.FiberRef, value: A): Effect.Effect } = dual( 3, (use: Effect.Effect, self: FiberRef.FiberRef, value: A): Effect.Effect => acquireUseRelease( zipLeft(fiberRefGet(self), fiberRefSet(self, value)), () => use, (oldValue) => fiberRefSet(self, oldValue) ) ) /* @internal */ export const fiberRefLocallyWith = dual< (self: FiberRef.FiberRef, f: (a: A) => A) => (use: Effect.Effect) => Effect.Effect, (use: Effect.Effect, self: FiberRef.FiberRef, f: (a: A) => A) => Effect.Effect >(3, (use, self, f) => fiberRefGetWith(self, (a) => fiberRefLocally(use, self, f(a)))) /** @internal */ export const fiberRefUnsafeMake = ( initial: Value, options?: { readonly fork?: ((a: Value) => Value) | undefined readonly join?: ((left: Value, right: Value) => Value) | undefined } ): FiberRef.FiberRef => fiberRefUnsafeMakePatch(initial, { differ: internalDiffer.update(), fork: options?.fork ?? identity, join: options?.join }) /** @internal */ export const fiberRefUnsafeMakeHashSet = ( initial: HashSet.HashSet ): FiberRef.FiberRef> => { const differ = internalDiffer.hashSet() return fiberRefUnsafeMakePatch(initial, { differ, fork: differ.empty }) } /** @internal */ export const fiberRefUnsafeMakeReadonlyArray = ( initial: ReadonlyArray ): FiberRef.FiberRef> => { const differ = internalDiffer.readonlyArray(internalDiffer.update()) return fiberRefUnsafeMakePatch(initial, { differ, fork: differ.empty }) } /** @internal */ export const fiberRefUnsafeMakeContext = ( initial: Context.Context ): FiberRef.FiberRef> => { const differ = internalDiffer.environment() return fiberRefUnsafeMakePatch(initial, { differ, fork: differ.empty }) } /** @internal */ export const fiberRefUnsafeMakePatch = ( initial: Value, options: { readonly differ: Differ.Differ readonly fork: Patch readonly join?: ((oldV: Value, newV: Value) => Value) | undefined } ): FiberRef.FiberRef => { const _fiberRef = { ...CommitPrototype, [FiberRefTypeId]: fiberRefVariance, initial, commit() { return fiberRefGet(this) }, diff: (oldValue: Value, newValue: Value) => options.differ.diff(oldValue, newValue), combine: (first: Patch, second: Patch) => options.differ.combine(first, second), patch: (patch: Patch) => (oldValue: Value) => options.differ.patch(patch, oldValue), fork: options.fork, join: options.join ?? ((_, n) => n) } return _fiberRef } /** @internal */ export const fiberRefUnsafeMakeRuntimeFlags = ( initial: RuntimeFlags.RuntimeFlags ): FiberRef.FiberRef => fiberRefUnsafeMakePatch(initial, { differ: runtimeFlags_.differ, fork: runtimeFlags_.differ.empty }) /** @internal */ export const currentContext: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentContext"), () => fiberRefUnsafeMakeContext(Context.empty()) ) /** @internal */ export const currentSchedulingPriority: FiberRef.FiberRef = globalValue( Symbol.for("effect/FiberRef/currentSchedulingPriority"), () => fiberRefUnsafeMake(0) ) /** @internal */ export const currentMaxOpsBeforeYield: FiberRef.FiberRef = globalValue( Symbol.for("effect/FiberRef/currentMaxOpsBeforeYield"), () => fiberRefUnsafeMake(2048) ) /** @internal */ export const currentLogAnnotations: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentLogAnnotation"), () => fiberRefUnsafeMake(HashMap.empty()) ) /** @internal */ export const currentLogLevel: FiberRef.FiberRef = globalValue( Symbol.for("effect/FiberRef/currentLogLevel"), () => fiberRefUnsafeMake(logLevelInfo) ) /** @internal */ export const currentLogSpan: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentLogSpan"), () => fiberRefUnsafeMake(List.empty()) ) /** @internal */ export const withSchedulingPriority = dual< (priority: number) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, priority: number) => Effect.Effect >(2, (self, scheduler) => fiberRefLocally(self, currentSchedulingPriority, scheduler)) /** @internal */ export const withMaxOpsBeforeYield = dual< (priority: number) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, priority: number) => Effect.Effect >(2, (self, scheduler) => fiberRefLocally(self, currentMaxOpsBeforeYield, scheduler)) /** @internal */ export const currentConcurrency: FiberRef.FiberRef<"unbounded" | number> = globalValue( Symbol.for("effect/FiberRef/currentConcurrency"), () => fiberRefUnsafeMake<"unbounded" | number>("unbounded") ) /** * @internal */ export const currentRequestBatching = globalValue( Symbol.for("effect/FiberRef/currentRequestBatching"), () => fiberRefUnsafeMake(true) ) /** @internal */ export const currentUnhandledErrorLogLevel: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentUnhandledErrorLogLevel"), () => fiberRefUnsafeMake(Option.some(logLevelDebug)) ) /** @internal */ export const currentVersionMismatchErrorLogLevel: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/versionMismatchErrorLogLevel"), () => fiberRefUnsafeMake(Option.some(logLevelWarning)) ) /** @internal */ export const withUnhandledErrorLogLevel = dual< (level: Option.Option) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, level: Option.Option) => Effect.Effect >(2, (self, level) => fiberRefLocally(self, currentUnhandledErrorLogLevel, level)) /** @internal */ export const currentMetricLabels: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentMetricLabels"), () => fiberRefUnsafeMakeReadonlyArray(Arr.empty()) ) /* @internal */ export const metricLabels: Effect.Effect> = fiberRefGet( currentMetricLabels ) /** @internal */ export const currentForkScopeOverride: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentForkScopeOverride"), () => fiberRefUnsafeMake(Option.none(), { fork: () => Option.none() as Option.Option, join: (parent, _) => parent }) ) /** @internal */ export const currentInterruptedCause: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentInterruptedCause"), () => fiberRefUnsafeMake(internalCause.empty, { fork: () => internalCause.empty, join: (parent, _) => parent }) ) /** @internal */ export const currentTracerEnabled: FiberRef.FiberRef = globalValue( Symbol.for("effect/FiberRef/currentTracerEnabled"), () => fiberRefUnsafeMake(true) ) /** @internal */ export const currentTracerTimingEnabled: FiberRef.FiberRef = globalValue( Symbol.for("effect/FiberRef/currentTracerTiming"), () => fiberRefUnsafeMake(true) ) /** @internal */ export const currentTracerSpanAnnotations: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentTracerSpanAnnotations"), () => fiberRefUnsafeMake(HashMap.empty()) ) /** @internal */ export const currentTracerSpanLinks: FiberRef.FiberRef> = globalValue( Symbol.for("effect/FiberRef/currentTracerSpanLinks"), () => fiberRefUnsafeMake(Chunk.empty()) ) // ----------------------------------------------------------------------------- // Scope // ----------------------------------------------------------------------------- /** @internal */ export const ScopeTypeId: Scope.ScopeTypeId = Symbol.for("effect/Scope") as Scope.ScopeTypeId /** @internal */ export const CloseableScopeTypeId: Scope.CloseableScopeTypeId = Symbol.for( "effect/CloseableScope" ) as Scope.CloseableScopeTypeId /* @internal */ export const scopeAddFinalizer = ( self: Scope.Scope, finalizer: Effect.Effect ): Effect.Effect => self.addFinalizer(() => asVoid(finalizer)) /* @internal */ export const scopeAddFinalizerExit = ( self: Scope.Scope, finalizer: Scope.Scope.Finalizer ): Effect.Effect => self.addFinalizer(finalizer) /* @internal */ export const scopeClose = ( self: Scope.Scope.Closeable, exit: Exit.Exit ): Effect.Effect => self.close(exit) /* @internal */ export const scopeFork = ( self: Scope.Scope, strategy: ExecutionStrategy.ExecutionStrategy ): Effect.Effect => self.fork(strategy) // ----------------------------------------------------------------------------- // Cause // ----------------------------------------------------------------------------- /** @internal */ export const causeSquash = (self: Cause.Cause): unknown => { return causeSquashWith(identity)(self) } /** @internal */ export const causeSquashWith = dual< (f: (error: E) => unknown) => (self: Cause.Cause) => unknown, (self: Cause.Cause, f: (error: E) => unknown) => unknown >(2, (self, f) => { const option = pipe(self, internalCause.failureOption, Option.map(f)) switch (option._tag) { case "None": { return pipe( internalCause.defects(self), Chunk.head, Option.match({ onNone: () => { const interrupts = Arr.fromIterable(internalCause.interruptors(self)).flatMap((fiberId) => Arr.fromIterable(FiberId.ids(fiberId)).map((id) => `#${id}`) ) return new InterruptedException(interrupts ? `Interrupted by fibers: ${interrupts.join(", ")}` : void 0) }, onSome: identity }) ) } case "Some": { return option.value } } }) // ----------------------------------------------------------------------------- // Errors // ----------------------------------------------------------------------------- /** @internal */ export const YieldableError: new(message?: string, options?: ErrorOptions) => Cause.YieldableError = (function() { class YieldableError extends globalThis.Error { commit() { return fail(this) } toJSON() { const obj = { ...this } if (this.message) obj.message = this.message if (this.cause) obj.cause = this.cause return obj } [NodeInspectSymbol]() { if (this.toString !== globalThis.Error.prototype.toString) { return this.stack ? `${this.toString()}\n${this.stack.split("\n").slice(1).join("\n")}` : this.toString() } else if ("Bun" in globalThis) { return internalCause.pretty(internalCause.fail(this), { renderErrorCause: true }) } return this } } // @effect-diagnostics-next-line floatingEffect:off Object.assign(YieldableError.prototype, StructuralCommitPrototype) return YieldableError as any })() const makeException = ( proto: Omit, tag: T["_tag"] ): new(message?: string | undefined) => T => { class Base extends YieldableError { readonly _tag = tag } Object.assign(Base.prototype, proto) ;(Base.prototype as any).name = tag return Base as any } /** @internal */ export const RuntimeExceptionTypeId: Cause.RuntimeExceptionTypeId = Symbol.for( "effect/Cause/errors/RuntimeException" ) as Cause.RuntimeExceptionTypeId /** @internal */ export const RuntimeException = makeException({ [RuntimeExceptionTypeId]: RuntimeExceptionTypeId }, "RuntimeException") /** @internal */ export const isRuntimeException = (u: unknown): u is Cause.RuntimeException => hasProperty(u, RuntimeExceptionTypeId) /** @internal */ export const InterruptedExceptionTypeId: Cause.InterruptedExceptionTypeId = Symbol.for( "effect/Cause/errors/InterruptedException" ) as Cause.InterruptedExceptionTypeId /** @internal */ export const InterruptedException = makeException({ [InterruptedExceptionTypeId]: InterruptedExceptionTypeId }, "InterruptedException") /** @internal */ export const isInterruptedException = (u: unknown): u is Cause.InterruptedException => hasProperty(u, InterruptedExceptionTypeId) /** @internal */ export const IllegalArgumentExceptionTypeId: Cause.IllegalArgumentExceptionTypeId = Symbol.for( "effect/Cause/errors/IllegalArgument" ) as Cause.IllegalArgumentExceptionTypeId /** @internal */ export const IllegalArgumentException = makeException({ [IllegalArgumentExceptionTypeId]: IllegalArgumentExceptionTypeId }, "IllegalArgumentException") /** @internal */ export const isIllegalArgumentException = (u: unknown): u is Cause.IllegalArgumentException => hasProperty(u, IllegalArgumentExceptionTypeId) /** @internal */ export const NoSuchElementExceptionTypeId: Cause.NoSuchElementExceptionTypeId = Symbol.for( "effect/Cause/errors/NoSuchElement" ) as Cause.NoSuchElementExceptionTypeId /** @internal */ export const NoSuchElementException = makeException({ [NoSuchElementExceptionTypeId]: NoSuchElementExceptionTypeId }, "NoSuchElementException") /** @internal */ export const isNoSuchElementException = (u: unknown): u is Cause.NoSuchElementException => hasProperty(u, NoSuchElementExceptionTypeId) /** @internal */ export const InvalidPubSubCapacityExceptionTypeId: Cause.InvalidPubSubCapacityExceptionTypeId = Symbol.for( "effect/Cause/errors/InvalidPubSubCapacityException" ) as Cause.InvalidPubSubCapacityExceptionTypeId /** @internal */ export const InvalidPubSubCapacityException = makeException({ [InvalidPubSubCapacityExceptionTypeId]: InvalidPubSubCapacityExceptionTypeId }, "InvalidPubSubCapacityException") /** @internal */ export const ExceededCapacityExceptionTypeId: Cause.ExceededCapacityExceptionTypeId = Symbol.for( "effect/Cause/errors/ExceededCapacityException" ) as Cause.ExceededCapacityExceptionTypeId /** @internal */ export const ExceededCapacityException = makeException({ [ExceededCapacityExceptionTypeId]: ExceededCapacityExceptionTypeId }, "ExceededCapacityException") /** @internal */ export const isExceededCapacityException = (u: unknown): u is Cause.ExceededCapacityException => hasProperty(u, ExceededCapacityExceptionTypeId) /** @internal */ export const isInvalidCapacityError = (u: unknown): u is Cause.InvalidPubSubCapacityException => hasProperty(u, InvalidPubSubCapacityExceptionTypeId) /** @internal */ export const TimeoutExceptionTypeId: Cause.TimeoutExceptionTypeId = Symbol.for( "effect/Cause/errors/Timeout" ) as Cause.TimeoutExceptionTypeId /** @internal */ export const TimeoutException = makeException({ [TimeoutExceptionTypeId]: TimeoutExceptionTypeId }, "TimeoutException") /** @internal */ export const timeoutExceptionFromDuration = (duration: Duration.DurationInput): Cause.TimeoutException => new TimeoutException(`Operation timed out after '${Duration.format(duration)}'`) /** @internal */ export const isTimeoutException = (u: unknown): u is Cause.TimeoutException => hasProperty(u, TimeoutExceptionTypeId) /** @internal */ export const UnknownExceptionTypeId: Cause.UnknownExceptionTypeId = Symbol.for( "effect/Cause/errors/UnknownException" ) as Cause.UnknownExceptionTypeId /** @internal */ export const UnknownException: new(cause: unknown, message?: string | undefined) => Cause.UnknownException = (function() { class UnknownException extends YieldableError { readonly _tag = "UnknownException" readonly error: unknown constructor(cause: unknown, message?: string) { super(message ?? "An unknown error occurred", { cause }) this.error = cause } } Object.assign(UnknownException.prototype, { [UnknownExceptionTypeId]: UnknownExceptionTypeId, name: "UnknownException" }) return UnknownException as any })() /** @internal */ export const isUnknownException = (u: unknown): u is Cause.UnknownException => hasProperty(u, UnknownExceptionTypeId) // ----------------------------------------------------------------------------- // Exit // ----------------------------------------------------------------------------- /** @internal */ export const exitIsExit = (u: unknown): u is Exit.Exit => isEffect(u) && "_tag" in u && (u._tag === "Success" || u._tag === "Failure") /** @internal */ export const exitIsFailure = (self: Exit.Exit): self is Exit.Failure => self._tag === "Failure" /** @internal */ export const exitIsSuccess = (self: Exit.Exit): self is Exit.Success => self._tag === "Success" /** @internal */ export const exitIsInterrupted = (self: Exit.Exit): boolean => { switch (self._tag) { case OpCodes.OP_FAILURE: return internalCause.isInterrupted(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return false } } /** @internal */ export const exitAs = dual< (value: A2) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, value: A2) => Exit.Exit >(2, (self: Exit.Exit, value: A2): Exit.Exit => { switch (self._tag) { case OpCodes.OP_FAILURE: { return exitFailCause(self.effect_instruction_i0) } case OpCodes.OP_SUCCESS: { return exitSucceed(value) as Exit.Exit } } }) /** @internal */ export const exitAsVoid = (self: Exit.Exit): Exit.Exit => exitAs(self, void 0) /** @internal */ export const exitCauseOption = (self: Exit.Exit): Option.Option> => { switch (self._tag) { case OpCodes.OP_FAILURE: return Option.some(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return Option.none() } } /** @internal */ export const exitCollectAll = ( exits: Iterable>, options?: { readonly parallel?: boolean | undefined } ): Option.Option, E>> => exitCollectAllInternal(exits, options?.parallel ? internalCause.parallel : internalCause.sequential) /** @internal */ export const exitDie = (defect: unknown): Exit.Exit => exitFailCause(internalCause.die(defect)) as Exit.Exit /** @internal */ export const exitExists: { (refinement: Refinement, B>): (self: Exit.Exit) => self is Exit.Exit (predicate: Predicate>): (self: Exit.Exit) => boolean (self: Exit.Exit, refinement: Refinement): self is Exit.Exit (self: Exit.Exit, predicate: Predicate): boolean } = dual(2, (self: Exit.Exit, refinement: Refinement): self is Exit.Exit => { switch (self._tag) { case OpCodes.OP_FAILURE: return false case OpCodes.OP_SUCCESS: return refinement(self.effect_instruction_i0) } }) /** @internal */ export const exitFail = (error: E): Exit.Exit => exitFailCause(internalCause.fail(error)) as Exit.Exit /** @internal */ export const exitFailCause = (cause: Cause.Cause): Exit.Exit => { const effect = new EffectPrimitiveFailure(OpCodes.OP_FAILURE) as any effect.effect_instruction_i0 = cause return effect } /** @internal */ export const exitFlatMap = dual< (f: (a: A) => Exit.Exit) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, f: (a: A) => Exit.Exit) => Exit.Exit >(2, (self: Exit.Exit, f: (a: A) => Exit.Exit): Exit.Exit => { switch (self._tag) { case OpCodes.OP_FAILURE: { return exitFailCause(self.effect_instruction_i0) } case OpCodes.OP_SUCCESS: { return f(self.effect_instruction_i0) } } }) /** @internal */ export const exitFlatMapEffect: { ( f: (a: A) => Effect.Effect, E2, R> ): (self: Exit.Exit) => Effect.Effect, E2, R> ( self: Exit.Exit, f: (a: A) => Effect.Effect, E2, R> ): Effect.Effect, E2, R> } = dual(2, ( self: Exit.Exit, f: (a: A) => Effect.Effect, E2, R> ): Effect.Effect, E2, R> => { switch (self._tag) { case OpCodes.OP_FAILURE: { return succeed(exitFailCause(self.effect_instruction_i0)) } case OpCodes.OP_SUCCESS: { return f(self.effect_instruction_i0) } } }) /** @internal */ export const exitFlatten = ( self: Exit.Exit, E2> ): Exit.Exit => pipe(self, exitFlatMap(identity)) /** @internal */ export const exitForEachEffect: { ( f: (a: A) => Effect.Effect ): (self: Exit.Exit) => Effect.Effect, never, R> ( self: Exit.Exit, f: (a: A) => Effect.Effect ): Effect.Effect, never, R> } = dual(2, ( self: Exit.Exit, f: (a: A) => Effect.Effect ): Effect.Effect, never, R> => { switch (self._tag) { case OpCodes.OP_FAILURE: { return succeed(exitFailCause(self.effect_instruction_i0)) } case OpCodes.OP_SUCCESS: { return exit(f(self.effect_instruction_i0)) } } }) /** @internal */ export const exitFromEither = (either: Either.Either): Exit.Exit => { switch (either._tag) { case "Left": return exitFail(either.left) case "Right": return exitSucceed(either.right) } } /** @internal */ export const exitFromOption = (option: Option.Option): Exit.Exit => { switch (option._tag) { case "None": return exitFail(void 0) case "Some": return exitSucceed(option.value) } } /** @internal */ export const exitGetOrElse = dual< (orElse: (cause: Cause.Cause) => A2) => (self: Exit.Exit) => A | A2, (self: Exit.Exit, orElse: (cause: Cause.Cause) => A2) => A | A2 >(2, (self, orElse) => { switch (self._tag) { case OpCodes.OP_FAILURE: return orElse(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return self.effect_instruction_i0 } }) /** @internal */ export const exitInterrupt = (fiberId: FiberId.FiberId): Exit.Exit => exitFailCause(internalCause.interrupt(fiberId)) /** @internal */ export const exitMap = dual< (f: (a: A) => B) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, f: (a: A) => B) => Exit.Exit >(2, (self, f) => { switch (self._tag) { case OpCodes.OP_FAILURE: return exitFailCause(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return exitSucceed(f(self.effect_instruction_i0)) } }) /** @internal */ export const exitMapBoth = dual< ( options: { readonly onFailure: (e: E) => E2 readonly onSuccess: (a: A) => A2 } ) => (self: Exit.Exit) => Exit.Exit, ( self: Exit.Exit, options: { readonly onFailure: (e: E) => E2 readonly onSuccess: (a: A) => A2 } ) => Exit.Exit >(2, (self, { onFailure, onSuccess }) => { switch (self._tag) { case OpCodes.OP_FAILURE: return exitFailCause(pipe(self.effect_instruction_i0, internalCause.map(onFailure))) case OpCodes.OP_SUCCESS: return exitSucceed(onSuccess(self.effect_instruction_i0)) } }) /** @internal */ export const exitMapError = dual< (f: (e: E) => E2) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, f: (e: E) => E2) => Exit.Exit >(2, (self, f) => { switch (self._tag) { case OpCodes.OP_FAILURE: return exitFailCause(pipe(self.effect_instruction_i0, internalCause.map(f))) case OpCodes.OP_SUCCESS: return exitSucceed(self.effect_instruction_i0) } }) /** @internal */ export const exitMapErrorCause = dual< (f: (cause: Cause.Cause) => Cause.Cause) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, f: (cause: Cause.Cause) => Cause.Cause) => Exit.Exit >(2, (self, f) => { switch (self._tag) { case OpCodes.OP_FAILURE: return exitFailCause(f(self.effect_instruction_i0)) case OpCodes.OP_SUCCESS: return exitSucceed(self.effect_instruction_i0) } }) /** @internal */ export const exitMatch = dual< (options: { readonly onFailure: (cause: Cause.Cause) => Z1 readonly onSuccess: (a: A) => Z2 }) => (self: Exit.Exit) => Z1 | Z2, (self: Exit.Exit, options: { readonly onFailure: (cause: Cause.Cause) => Z1 readonly onSuccess: (a: A) => Z2 }) => Z1 | Z2 >(2, (self, { onFailure, onSuccess }) => { switch (self._tag) { case OpCodes.OP_FAILURE: return onFailure(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return onSuccess(self.effect_instruction_i0) } }) /** @internal */ export const exitMatchEffect = dual< ( options: { readonly onFailure: (cause: Cause.Cause) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ) => (self: Exit.Exit) => Effect.Effect, ( self: Exit.Exit, options: { readonly onFailure: (cause: Cause.Cause) => Effect.Effect readonly onSuccess: (a: A) => Effect.Effect } ) => Effect.Effect >(2, (self, { onFailure, onSuccess }) => { switch (self._tag) { case OpCodes.OP_FAILURE: return onFailure(self.effect_instruction_i0) case OpCodes.OP_SUCCESS: return onSuccess(self.effect_instruction_i0) } }) /** @internal */ export const exitSucceed = (value: A): Exit.Exit => { const effect = new EffectPrimitiveSuccess(OpCodes.OP_SUCCESS) as any effect.effect_instruction_i0 = value return effect } /** @internal */ export const exitVoid: Exit.Exit = exitSucceed(void 0) /** @internal */ export const exitZip = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit<[A, A2], E | E2>, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit<[A, A2], E | E2> >(2, (self, that) => exitZipWith(self, that, { onSuccess: (a, a2) => [a, a2], onFailure: internalCause.sequential })) /** @internal */ export const exitZipLeft = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit >(2, (self, that) => exitZipWith(self, that, { onSuccess: (a, _) => a, onFailure: internalCause.sequential })) /** @internal */ export const exitZipRight = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit >(2, (self, that) => exitZipWith(self, that, { onSuccess: (_, a2) => a2, onFailure: internalCause.sequential })) /** @internal */ export const exitZipPar = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit<[A, A2], E | E2>, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit<[A, A2], E | E2> >(2, (self, that) => exitZipWith(self, that, { onSuccess: (a, a2) => [a, a2], onFailure: internalCause.parallel })) /** @internal */ export const exitZipParLeft = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit >(2, (self, that) => exitZipWith(self, that, { onSuccess: (a, _) => a, onFailure: internalCause.parallel })) /** @internal */ export const exitZipParRight = dual< (that: Exit.Exit) => (self: Exit.Exit) => Exit.Exit, (self: Exit.Exit, that: Exit.Exit) => Exit.Exit >(2, (self, that) => exitZipWith(self, that, { onSuccess: (_, a2) => a2, onFailure: internalCause.parallel })) /** @internal */ export const exitZipWith = dual< ( that: Exit.Exit, options: { readonly onSuccess: (a: A, b: B) => C readonly onFailure: (cause: Cause.Cause, cause2: Cause.Cause) => Cause.Cause } ) => (self: Exit.Exit) => Exit.Exit, ( self: Exit.Exit, that: Exit.Exit, options: { readonly onSuccess: (a: A, b: B) => C readonly onFailure: (cause: Cause.Cause, cause2: Cause.Cause) => Cause.Cause } ) => Exit.Exit >(3, ( self, that, { onFailure, onSuccess } ) => { switch (self._tag) { case OpCodes.OP_FAILURE: { switch (that._tag) { case OpCodes.OP_SUCCESS: return exitFailCause(self.effect_instruction_i0) case OpCodes.OP_FAILURE: { return exitFailCause(onFailure(self.effect_instruction_i0, that.effect_instruction_i0)) } } } case OpCodes.OP_SUCCESS: { switch (that._tag) { case OpCodes.OP_SUCCESS: return exitSucceed(onSuccess(self.effect_instruction_i0, that.effect_instruction_i0)) case OpCodes.OP_FAILURE: return exitFailCause(that.effect_instruction_i0) } } } }) const exitCollectAllInternal = ( exits: Iterable>, combineCauses: (causeA: Cause.Cause, causeB: Cause.Cause) => Cause.Cause ): Option.Option, E>> => { const list = Chunk.fromIterable(exits) if (!Chunk.isNonEmpty(list)) { return Option.none() } return pipe( Chunk.tailNonEmpty(list), Arr.reduce( pipe(Chunk.headNonEmpty(list), exitMap>(Chunk.of)), (accumulator, current) => pipe( accumulator, exitZipWith(current, { onSuccess: (list, value) => pipe(list, Chunk.prepend(value)), onFailure: combineCauses }) ) ), exitMap(Chunk.reverse), exitMap((chunk) => Chunk.toReadonlyArray(chunk) as Array), Option.some ) } // ----------------------------------------------------------------------------- // Deferred // ----------------------------------------------------------------------------- /** @internal */ export const deferredUnsafeMake = (fiberId: FiberId.FiberId): Deferred.Deferred => { const _deferred = { ...CommitPrototype, [deferred.DeferredTypeId]: deferred.deferredVariance, state: MutableRef.make(deferred.pending([])), commit() { return deferredAwait(this) }, blockingOn: fiberId } return _deferred } /* @internal */ export const deferredMake = (): Effect.Effect> => flatMap(fiberId, (id) => deferredMakeAs(id)) /* @internal */ export const deferredMakeAs = (fiberId: FiberId.FiberId): Effect.Effect> => sync(() => deferredUnsafeMake(fiberId)) /* @internal */ export const deferredAwait = (self: Deferred.Deferred): Effect.Effect => asyncInterrupt((resume) => { const state = MutableRef.get(self.state) switch (state._tag) { case DeferredOpCodes.OP_STATE_DONE: { return resume(state.effect) } case DeferredOpCodes.OP_STATE_PENDING: { // we can push here as the internal state is mutable state.joiners.push(resume) return deferredInterruptJoiner(self, resume) } } }, self.blockingOn) /* @internal */ export const deferredComplete: { (effect: Effect.Effect): (self: Deferred.Deferred) => Effect.Effect (self: Deferred.Deferred, effect: Effect.Effect): Effect.Effect } = dual( 2, (self: Deferred.Deferred, effect: Effect.Effect): Effect.Effect => intoDeferred(effect, self) ) /* @internal */ export const deferredCompleteWith = dual< (effect: Effect.Effect) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, effect: Effect.Effect) => Effect.Effect >(2, (self, effect) => sync(() => { const state = MutableRef.get(self.state) switch (state._tag) { case DeferredOpCodes.OP_STATE_DONE: { return false } case DeferredOpCodes.OP_STATE_PENDING: { MutableRef.set(self.state, deferred.done(effect)) for (let i = 0, len = state.joiners.length; i < len; i++) { state.joiners[i](effect) } return true } } })) /* @internal */ export const deferredDone = dual< (exit: Exit.Exit) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, exit: Exit.Exit) => Effect.Effect >(2, (self, exit) => deferredCompleteWith(self, exit)) /* @internal */ export const deferredFail = dual< (error: E) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, error: E) => Effect.Effect >(2, (self, error) => deferredCompleteWith(self, fail(error))) /* @internal */ export const deferredFailSync = dual< (evaluate: LazyArg) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, evaluate: LazyArg) => Effect.Effect >(2, (self, evaluate) => deferredCompleteWith(self, failSync(evaluate))) /* @internal */ export const deferredFailCause = dual< (cause: Cause.Cause) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, cause: Cause.Cause) => Effect.Effect >(2, (self, cause) => deferredCompleteWith(self, failCause(cause))) /* @internal */ export const deferredFailCauseSync = dual< (evaluate: LazyArg>) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, evaluate: LazyArg>) => Effect.Effect >(2, (self, evaluate) => deferredCompleteWith(self, failCauseSync(evaluate))) /* @internal */ export const deferredDie = dual< (defect: unknown) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, defect: unknown) => Effect.Effect >(2, (self, defect) => deferredCompleteWith(self, die(defect))) /* @internal */ export const deferredDieSync = dual< (evaluate: LazyArg) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, evaluate: LazyArg) => Effect.Effect >(2, (self, evaluate) => deferredCompleteWith(self, dieSync(evaluate))) /* @internal */ export const deferredInterrupt = (self: Deferred.Deferred): Effect.Effect => flatMap(fiberId, (fiberId) => deferredCompleteWith(self, interruptWith(fiberId))) /* @internal */ export const deferredInterruptWith = dual< (fiberId: FiberId.FiberId) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, fiberId: FiberId.FiberId) => Effect.Effect >(2, (self, fiberId) => deferredCompleteWith(self, interruptWith(fiberId))) /* @internal */ export const deferredIsDone = (self: Deferred.Deferred): Effect.Effect => sync(() => MutableRef.get(self.state)._tag === DeferredOpCodes.OP_STATE_DONE) /* @internal */ export const deferredPoll = ( self: Deferred.Deferred ): Effect.Effect>> => sync(() => { const state = MutableRef.get(self.state) switch (state._tag) { case DeferredOpCodes.OP_STATE_DONE: { return Option.some(state.effect) } case DeferredOpCodes.OP_STATE_PENDING: { return Option.none() } } }) /* @internal */ export const deferredSucceed = dual< (value: A) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, value: A) => Effect.Effect >(2, (self, value) => deferredCompleteWith(self, succeed(value))) /* @internal */ export const deferredSync = dual< (evaluate: LazyArg) => (self: Deferred.Deferred) => Effect.Effect, (self: Deferred.Deferred, evaluate: LazyArg) => Effect.Effect >(2, (self, evaluate) => deferredCompleteWith(self, sync(evaluate))) /** @internal */ export const deferredUnsafeDone = (self: Deferred.Deferred, effect: Effect.Effect): void => { const state = MutableRef.get(self.state) if (state._tag === DeferredOpCodes.OP_STATE_PENDING) { MutableRef.set(self.state, deferred.done(effect)) for (let i = 0, len = state.joiners.length; i < len; i++) { state.joiners[i](effect) } } } const deferredInterruptJoiner = ( self: Deferred.Deferred, joiner: (effect: Effect.Effect) => void ): Effect.Effect => sync(() => { const state = MutableRef.get(self.state) if (state._tag === DeferredOpCodes.OP_STATE_PENDING) { const index = state.joiners.indexOf(joiner) if (index >= 0) { // we can splice here as the internal state is mutable state.joiners.splice(index, 1) } } }) // ----------------------------------------------------------------------------- // Context // ----------------------------------------------------------------------------- const constContext = withFiberRuntime((fiber) => exitSucceed(fiber.currentContext)) /* @internal */ export const context = (): Effect.Effect, never, R> => constContext as any /* @internal */ export const contextWith = ( f: (context: Context.Context) => A ): Effect.Effect => map(context(), f) /* @internal */ export const contextWithEffect = ( f: (context: Context.Context) => Effect.Effect ): Effect.Effect => flatMap(context(), f) /* @internal */ export const provideContext = dual< (context: Context.Context) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, context: Context.Context) => Effect.Effect >(2, (self: Effect.Effect, context: Context.Context) => fiberRefLocally( currentContext, context )(self as Effect.Effect)) /* @internal */ export const provideSomeContext = dual< (context: Context.Context) => (self: Effect.Effect) => Effect.Effect>, (self: Effect.Effect, context: Context.Context) => Effect.Effect> >(2, (self: Effect.Effect, context: Context.Context) => fiberRefLocallyWith( currentContext, (parent) => Context.merge(parent, context) )(self as Effect.Effect)) /* @internal */ export const mapInputContext = dual< ( f: (context: Context.Context) => Context.Context ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, f: (context: Context.Context) => Context.Context ) => Effect.Effect >(2, ( self: Effect.Effect, f: (context: Context.Context) => Context.Context ) => contextWithEffect((context: Context.Context) => provideContext(self, f(context)))) // ----------------------------------------------------------------------------- // Filtering // ----------------------------------------------------------------------------- /** @internal */ export const filterEffectOrElse: { ( options: { readonly predicate: (a: NoInfer) => Effect.Effect readonly orElse: (a: NoInfer) => Effect.Effect } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly predicate: (a: A) => Effect.Effect readonly orElse: (a: A) => Effect.Effect } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly predicate: (a: A) => Effect.Effect readonly orElse: (a: A) => Effect.Effect } ): Effect.Effect => flatMap( self, (a) => flatMap( options.predicate(a), (pass): Effect.Effect => pass ? succeed(a) : options.orElse(a) ) )) /** @internal */ export const filterEffectOrFail: { ( options: { readonly predicate: (a: NoInfer) => Effect.Effect readonly orFailWith: (a: NoInfer) => E3 } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly predicate: (a: A) => Effect.Effect readonly orFailWith: (a: A) => E3 } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly predicate: (a: A) => Effect.Effect readonly orFailWith: (a: A) => E3 } ): Effect.Effect => filterEffectOrElse(self, { predicate: options.predicate, orElse: (a) => fail(options.orFailWith(a)) })) // ----------------------------------------------------------------------------- // Tracing // ----------------------------------------------------------------------------- /** @internal */ export const currentSpanFromFiber = (fiber: Fiber.RuntimeFiber): Option.Option => { const span = fiber.currentSpan return span !== undefined && span._tag === "Span" ? Option.some(span) : Option.none() } const NoopSpanProto: Omit = { _tag: "Span", spanId: "noop", traceId: "noop", sampled: false, status: { _tag: "Ended", startTime: BigInt(0), endTime: BigInt(0), exit: exitVoid }, attributes: new Map(), links: [], kind: "internal", attribute() {}, event() {}, end() {}, addLinks() {} } /** @internal */ export const noopSpan = (options: { readonly name: string readonly parent: Option.Option readonly context: Context.Context }): Tracer.Span => Object.assign(Object.create(NoopSpanProto), options)