import * as Arr from "../Array.js" import type * as Cause from "../Cause.js" import * as Chunk from "../Chunk.js" import * as Clock from "../Clock.js" import * as Context from "../Context.js" import * as Duration from "../Duration.js" import type * as Effect from "../Effect.js" import type { Exit } from "../Exit.js" import type * as Fiber from "../Fiber.js" import type * as FiberId from "../FiberId.js" import type * as FiberRef from "../FiberRef.js" import * as FiberRefs from "../FiberRefs.js" import type * as FiberRefsPatch from "../FiberRefsPatch.js" import type { LazyArg } from "../Function.js" import { constFalse, constTrue, constVoid, dual, identity, pipe } from "../Function.js" import * as HashMap from "../HashMap.js" import * as HashSet from "../HashSet.js" import * as List from "../List.js" import * as LogLevel from "../LogLevel.js" import * as LogSpan from "../LogSpan.js" import type * as Metric from "../Metric.js" import type * as MetricLabel from "../MetricLabel.js" import * as Option from "../Option.js" import * as Predicate from "../Predicate.js" import type * as Random from "../Random.js" import * as Ref from "../Ref.js" import type * as runtimeFlagsPatch from "../RuntimeFlagsPatch.js" import * as Tracer from "../Tracer.js" import type * as Types from "../Types.js" import type { Unify } from "../Unify.js" import { internalCall } from "../Utils.js" import * as internalCause from "./cause.js" import { clockTag } from "./clock.js" import * as core from "./core.js" import * as defaultServices from "./defaultServices.js" import * as doNotation from "./doNotation.js" import * as fiberRefsPatch from "./fiberRefs/patch.js" import type { FiberRuntime } from "./fiberRuntime.js" import * as metricLabel from "./metric/label.js" import * as runtimeFlags from "./runtimeFlags.js" import * as internalTracer from "./tracer.js" /* @internal */ export const annotateLogs = dual< { (key: string, value: unknown): (effect: Effect.Effect) => Effect.Effect ( values: Record ): (effect: Effect.Effect) => Effect.Effect }, { (effect: Effect.Effect, key: string, value: unknown): Effect.Effect (effect: Effect.Effect, values: Record): Effect.Effect } >( (args) => core.isEffect(args[0]), function() { const args = arguments return core.fiberRefLocallyWith( args[0] as Effect.Effect, core.currentLogAnnotations, typeof args[1] === "string" ? HashMap.set(args[1], args[2]) : (annotations) => Object.entries(args[1] as Record).reduce( (acc, [key, value]) => HashMap.set(acc, key, value), annotations ) ) } ) /* @internal */ export const asSome = (self: Effect.Effect): Effect.Effect, E, R> => core.map(self, Option.some) /* @internal */ export const asSomeError = (self: Effect.Effect): Effect.Effect, R> => core.mapError(self, Option.some) /* @internal */ export const try_: { (options: { readonly try: LazyArg readonly catch: (error: unknown) => E }): Effect.Effect (thunk: LazyArg): Effect.Effect } = ( arg: LazyArg | { readonly try: LazyArg readonly catch: (error: unknown) => E } ) => { let evaluate: LazyArg let onFailure: ((error: unknown) => E) | undefined = undefined if (typeof arg === "function") { evaluate = arg } else { evaluate = arg.try onFailure = arg.catch } return core.suspend(() => { try { return core.succeed(internalCall(evaluate)) } catch (error) { return core.fail( onFailure ? internalCall(() => onFailure(error)) : new core.UnknownException(error, "An unknown error occurred in Effect.try") ) } }) } /* @internal */ export const _catch: { ( discriminator: N, options: { readonly failure: K readonly onFailure: (error: Extract) => Effect.Effect } ): (self: Effect.Effect) => Effect.Effect< A | A1, Exclude | E1, R | R1 > ( self: Effect.Effect, discriminator: N, options: { readonly failure: K readonly onFailure: (error: Extract) => Effect.Effect } ): Effect.Effect | E1, R | R1> } = dual( 3, (self, tag, options) => core.catchAll(self, (e) => { if (Predicate.hasProperty(e, tag) && e[tag] === options.failure) { return options.onFailure(e) } return core.fail(e) }) ) /* @internal */ export const catchAllDefect = dual< ( f: (defect: unknown) => Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, f: (defect: unknown) => Effect.Effect ) => Effect.Effect >(2, ( self: Effect.Effect, f: (defect: unknown) => Effect.Effect ): Effect.Effect => core.catchAllCause( self, (cause): Effect.Effect => { const option = internalCause.find(cause, (_) => internalCause.isDieType(_) ? Option.some(_) : Option.none()) switch (option._tag) { case "None": { return core.failCause(cause) } case "Some": { return f(option.value.defect) } } } )) /* @internal */ export const catchSomeCause: { ( f: (cause: Cause.Cause>) => Option.Option> ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, f: (cause: Cause.Cause>) => Option.Option> ): Effect.Effect } = dual( 2, ( self: Effect.Effect, f: (cause: Cause.Cause>) => Option.Option> ): Effect.Effect => core.matchCauseEffect(self, { onFailure: (cause): Effect.Effect => { const option = f(cause) switch (option._tag) { case "None": { return core.failCause(cause) } case "Some": { return option.value } } }, onSuccess: core.succeed }) ) /* @internal */ export const catchSomeDefect = dual< ( pf: (defect: unknown) => Option.Option> ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, pf: (defect: unknown) => Option.Option> ) => Effect.Effect >( 2, ( self: Effect.Effect, pf: (defect: unknown) => Option.Option> ): Effect.Effect => core.catchAllCause( self, (cause): Effect.Effect => { const option = internalCause.find(cause, (_) => internalCause.isDieType(_) ? Option.some(_) : Option.none()) switch (option._tag) { case "None": { return core.failCause(cause) } case "Some": { const optionEffect = pf(option.value.defect) return optionEffect._tag === "Some" ? optionEffect.value : core.failCause(cause) } } } ) ) /* @internal */ export const catchTag: { < E, const K extends Arr.NonEmptyReadonlyArray, A1, E1, R1 >( ...args: [ ...tags: K, f: (e: Extract, { _tag: K[number] }>) => Effect.Effect ] ): (self: Effect.Effect) => Effect.Effect | E1, R | R1> < A, E, R, const K extends Arr.NonEmptyReadonlyArray, A1, E1, R1 >( self: Effect.Effect, ...args: [ ...tags: K, f: (e: Extract, { _tag: K[number] }>) => Effect.Effect ] ): Effect.Effect | E1, R | R1> } = dual( (args: any) => core.isEffect(args[0]), , R1, E1, A1>( self: Effect.Effect, ...args: [ ...tags: K & { [I in keyof K]: E extends { _tag: string } ? E["_tag"] : never }, f: (e: Extract, { _tag: K[number] }>) => Effect.Effect ] ): Effect.Effect | E1, R | R1> => { const f = args[args.length - 1] as any let predicate: Predicate.Predicate if (args.length === 2) { predicate = Predicate.isTagged(args[0] as string) } else { predicate = (e) => { const tag = Predicate.hasProperty(e, "_tag") ? e["_tag"] : undefined if (!tag) return false for (let i = 0; i < args.length - 1; i++) { if (args[i] === tag) return true } return false } } return core.catchIf(self, predicate as Predicate.Refinement>, f) as any } ) as any /** @internal */ export const catchTags: { < E, Cases extends (E extends { _tag: string } ? { [K in E["_tag"]]+?: (error: Extract) => Effect.Effect } : {}) >( cases: Cases ): (self: Effect.Effect) => Effect.Effect< | A | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? A : never }[keyof Cases], | Exclude | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? E : never }[keyof Cases], | R | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? R : never }[keyof Cases] > < R, E, A, Cases extends (E extends { _tag: string } ? { [K in E["_tag"]]+?: (error: Extract) => Effect.Effect } : {}) >( self: Effect.Effect, cases: Cases ): Effect.Effect< | A | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? A : never }[keyof Cases], | Exclude | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? E : never }[keyof Cases], | R | { [K in keyof Cases]: Cases[K] extends ((...args: Array) => Effect.Effect) ? R : never }[keyof Cases] > } = dual(2, (self, cases) => { let keys: Array return core.catchIf( self, (e): e is { readonly _tag: string } => { keys ??= Object.keys(cases) return Predicate.hasProperty(e, "_tag") && Predicate.isString(e["_tag"]) && keys.includes(e["_tag"]) }, (e) => cases[e["_tag"]](e) ) }) /* @internal */ export const cause = (self: Effect.Effect): Effect.Effect, never, R> => core.matchCause(self, { onFailure: identity, onSuccess: () => internalCause.empty }) /* @internal */ export const clockWith: (f: (clock: Clock.Clock) => Effect.Effect) => Effect.Effect = Clock.clockWith /* @internal */ export const clock: Effect.Effect = clockWith(core.succeed) /* @internal */ export const delay = dual< (duration: Duration.DurationInput) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, duration: Duration.DurationInput) => Effect.Effect >(2, (self, duration) => core.zipRight(Clock.sleep(duration), self)) /* @internal */ export const descriptorWith = ( f: (descriptor: Fiber.Fiber.Descriptor) => Effect.Effect ): Effect.Effect => core.withFiberRuntime((state, status) => f({ id: state.id(), status, interruptors: internalCause.interruptors(state.getFiberRef(core.currentInterruptedCause)) }) ) as Effect.Effect /* @internal */ export const allowInterrupt: Effect.Effect = descriptorWith( (descriptor) => HashSet.size(descriptor.interruptors) > 0 ? core.interrupt : core.void ) /* @internal */ export const descriptor: Effect.Effect = descriptorWith(core.succeed) /* @internal */ export const diffFiberRefs = ( self: Effect.Effect ): Effect.Effect<[FiberRefsPatch.FiberRefsPatch, A], E, R> => summarized(self, fiberRefs, fiberRefsPatch.diff) /* @internal */ export const diffFiberRefsAndRuntimeFlags = ( self: Effect.Effect ): Effect.Effect<[[FiberRefsPatch.FiberRefsPatch, runtimeFlagsPatch.RuntimeFlagsPatch], A], E, R> => summarized( self, core.zip(fiberRefs, core.runtimeFlags), ([refs, flags], [refsNew, flagsNew]) => [fiberRefsPatch.diff(refs, refsNew), runtimeFlags.diff(flags, flagsNew)] ) /* @internal */ export const Do: Effect.Effect<{}> = core.succeed({}) /* @internal */ export const bind: { ( name: Exclude, f: (a: Types.NoInfer) => Effect.Effect ): ( self: Effect.Effect ) => Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E1, R2 | R1> ( self: Effect.Effect, name: Exclude, f: (a: Types.NoInfer) => Effect.Effect ): Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E1 | E2, R1 | R2> } = doNotation.bind(core.map, core.flatMap) /* @internal */ export const bindTo: { (name: N): (self: Effect.Effect) => Effect.Effect<{ [K in N]: A }, E, R> (self: Effect.Effect, name: N): Effect.Effect<{ [K in N]: A }, E, R> } = doNotation.bindTo(core.map) /* @internal */ export const let_: { ( name: Exclude, f: (a: Types.NoInfer) => B ): ( self: Effect.Effect ) => Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R> ( self: Effect.Effect, name: Exclude, f: (a: Types.NoInfer) => B ): Effect.Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R> } = doNotation.let_(core.map) /* @internal */ export const dropUntil: { ( predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): (elements: Iterable) => Effect.Effect, E, R> ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect, E, R> } = dual( 2, ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect, E, R> => core.suspend(() => { const iterator = elements[Symbol.iterator]() const builder: Array = [] let next: IteratorResult let dropping: Effect.Effect = core.succeed(false) let i = 0 while ((next = iterator.next()) && !next.done) { const a = next.value const index = i++ dropping = core.flatMap(dropping, (bool) => { if (bool) { builder.push(a) return core.succeed(true) } return predicate(a, index) }) } return core.map(dropping, () => builder) }) ) /* @internal */ export const dropWhile: { ( predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): (elements: Iterable) => Effect.Effect, E, R> ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect, E, R> } = dual( 2, ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect, E, R> => core.suspend(() => { const iterator = elements[Symbol.iterator]() const builder: Array = [] let next let dropping: Effect.Effect = core.succeed(true) let i = 0 while ((next = iterator.next()) && !next.done) { const a = next.value const index = i++ dropping = core.flatMap(dropping, (d) => core.map(d ? predicate(a, index) : core.succeed(false), (b) => { if (!b) { builder.push(a) } return b })) } return core.map(dropping, () => builder) }) ) /* @internal */ export const contextWith = (f: (context: Context.Context) => A): Effect.Effect => core.map(core.context(), f) /* @internal */ export const eventually = (self: Effect.Effect): Effect.Effect => core.orElse(self, () => core.flatMap(core.yieldNow(), () => eventually(self))) /* @internal */ export const filterMap = dual< , B>( pf: (a: Effect.Effect.Success) => Option.Option ) => (elements: Iterable) => Effect.Effect, Effect.Effect.Error, Effect.Effect.Context>, , B>( elements: Iterable, pf: (a: Effect.Effect.Success) => Option.Option ) => Effect.Effect, Effect.Effect.Error, Effect.Effect.Context> >(2, (elements, pf) => core.map( core.forEachSequential(elements, identity), Arr.filterMap(pf) )) /* @internal */ export const filterOrDie: { ( refinement: Predicate.Refinement, B>, orDieWith: (a: Types.EqualsWith>) => unknown ): (self: Effect.Effect) => Effect.Effect ( predicate: Predicate.Predicate>, orDieWith: (a: Types.NoInfer) => unknown ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Predicate.Refinement, orDieWith: (a: Types.EqualsWith>) => unknown ): Effect.Effect ( self: Effect.Effect, predicate: Predicate.Predicate, orDieWith: (a: A) => unknown ): Effect.Effect } = dual( 3, ( self: Effect.Effect, predicate: Predicate.Predicate, orDieWith: (a: A) => unknown ): Effect.Effect => filterOrElse(self, predicate, (a) => core.dieSync(() => orDieWith(a))) ) /* @internal */ export const filterOrDieMessage: { ( refinement: Predicate.Refinement, B>, message: string ): (self: Effect.Effect) => Effect.Effect ( predicate: Predicate.Predicate>, message: string ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Predicate.Refinement, message: string ): Effect.Effect ( self: Effect.Effect, predicate: Predicate.Predicate, message: string ): Effect.Effect } = dual( 3, (self: Effect.Effect, predicate: Predicate.Predicate, message: string): Effect.Effect => filterOrElse(self, predicate, () => core.dieMessage(message)) ) /* @internal */ export const filterOrElse: { ( refinement: Predicate.Refinement, B>, orElse: (a: Types.EqualsWith, Exclude, B>>) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( predicate: Predicate.Predicate>, orElse: (a: Types.NoInfer) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Predicate.Refinement, orElse: (a: Types.EqualsWith>) => Effect.Effect ): Effect.Effect ( self: Effect.Effect, predicate: Predicate.Predicate, orElse: (a: A) => Effect.Effect ): Effect.Effect } = dual(3, ( self: Effect.Effect, predicate: Predicate.Predicate, orElse: (a: A) => Effect.Effect ): Effect.Effect => core.flatMap( self, (a) => predicate(a) ? core.succeed(a) : orElse(a) )) /** @internal */ export const liftPredicate = dual< ( predicate: Predicate.Refinement | Predicate.Predicate, orFailWith: (a: Types.EqualsWith>) => E ) => (a: A) => Effect.Effect, E>, ( self: A, predicate: Predicate.Refinement | Predicate.Predicate, orFailWith: (a: Types.EqualsWith>) => E ) => Effect.Effect >( 3, ( self: A, predicate: Predicate.Refinement | Predicate.Predicate, orFailWith: (a: Types.EqualsWith>) => E ): Effect.Effect => core.suspend(() => predicate(self) ? core.succeed(self as B) : core.fail(orFailWith(self as any))) ) /* @internal */ export const filterOrFail: { ( refinement: Predicate.Refinement, B>, orFailWith: (a: Types.EqualsWith, Exclude, B>>) => E2 ): (self: Effect.Effect) => Effect.Effect, E2 | E, R> ( predicate: Predicate.Predicate>, orFailWith: (a: Types.NoInfer) => E2 ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Predicate.Refinement, orFailWith: (a: Types.EqualsWith>) => E2 ): Effect.Effect, E2 | E, R> ( self: Effect.Effect, predicate: Predicate.Predicate, orFailWith: (a: A) => E2 ): Effect.Effect ( refinement: Predicate.Refinement, B> ): (self: Effect.Effect) => Effect.Effect, Cause.NoSuchElementException | E, R> ( predicate: Predicate.Predicate> ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, refinement: Predicate.Refinement ): Effect.Effect, E | Cause.NoSuchElementException, R> ( self: Effect.Effect, predicate: Predicate.Predicate ): Effect.Effect } = dual((args) => core.isEffect(args[0]), ( self: Effect.Effect, predicate: Predicate.Predicate, orFailWith?: (a: A) => E2 ): Effect.Effect => filterOrElse( self, predicate, (a): Effect.Effect => orFailWith === undefined ? core.fail(new core.NoSuchElementException()) : core.failSync(() => orFailWith(a)) )) /* @internal */ export const findFirst: { ( predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): (elements: Iterable) => Effect.Effect, E, R> ( elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): Effect.Effect, E, R> } = dual( 2, ( elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): Effect.Effect, E, R> => core.suspend(() => { const iterator = elements[Symbol.iterator]() const next = iterator.next() if (!next.done) { return findLoop(iterator, 0, predicate, next.value) } return core.succeed(Option.none()) }) ) const findLoop = ( iterator: Iterator, index: number, f: (a: A, i: number) => Effect.Effect, value: A ): Effect.Effect, E, R> => core.flatMap(f(value, index), (result) => { if (result) { return core.succeed(Option.some(value)) } const next = iterator.next() if (!next.done) { return findLoop(iterator, index + 1, f, next.value) } return core.succeed(Option.none()) }) /* @internal */ export const firstSuccessOf = >( effects: Iterable ): Effect.Effect, Effect.Effect.Error, Effect.Effect.Context> => core.suspend(() => { const list = Chunk.fromIterable(effects) if (!Chunk.isNonEmpty(list)) { return core.dieSync(() => new core.IllegalArgumentException(`Received an empty collection of effects`)) } return pipe( Chunk.tailNonEmpty(list), Arr.reduce(Chunk.headNonEmpty(list), (left, right) => core.orElse(left, () => right) as Eff) ) }) /* @internal */ export const flipWith: { ( f: (effect: Effect.Effect) => Effect.Effect ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, f: (effect: Effect.Effect) => Effect.Effect ): Effect.Effect } = dual(2, ( self: Effect.Effect, f: (effect: Effect.Effect) => Effect.Effect ): Effect.Effect => core.flip(f(core.flip(self)))) /* @internal */ export const match: { ( options: { readonly onFailure: (error: E) => A2 readonly onSuccess: (value: A) => A3 } ): (self: Effect.Effect) => Effect.Effect ( self: Effect.Effect, options: { readonly onFailure: (error: E) => A2 readonly onSuccess: (value: A) => A3 } ): Effect.Effect } = dual(2, ( self: Effect.Effect, options: { readonly onFailure: (error: E) => A2 readonly onSuccess: (value: A) => A3 } ): Effect.Effect => core.matchEffect(self, { onFailure: (e) => core.succeed(options.onFailure(e)), onSuccess: (a) => core.succeed(options.onSuccess(a)) })) /* @internal */ export const every: { ( predicate: (a: A, i: number) => Effect.Effect ): (elements: Iterable) => Effect.Effect ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect } = dual( 2, ( elements: Iterable, predicate: (a: A, i: number) => Effect.Effect ): Effect.Effect => core.suspend(() => forAllLoop(elements[Symbol.iterator](), 0, predicate)) ) const forAllLoop = ( iterator: Iterator, index: number, f: (a: A, i: number) => Effect.Effect ): Effect.Effect => { const next = iterator.next() return next.done ? core.succeed(true) : core.flatMap( f(next.value, index), (b) => b ? forAllLoop(iterator, index + 1, f) : core.succeed(b) ) } /* @internal */ export const forever = (self: Effect.Effect): Effect.Effect => { const loop: Effect.Effect = core.flatMap(core.flatMap(self, () => core.yieldNow()), () => loop) return loop } /* @internal */ export const fiberRefs: Effect.Effect = core.withFiberRuntime((state) => core.succeed(state.getFiberRefs()) ) /* @internal */ export const head = ( self: Effect.Effect, E, R> ): Effect.Effect => core.flatMap(self, (as) => { const iterator = as[Symbol.iterator]() const next = iterator.next() if (next.done) { return core.fail(new core.NoSuchElementException()) } return core.succeed(next.value) }) /* @internal */ export const ignore = (self: Effect.Effect): Effect.Effect => match(self, { onFailure: constVoid, onSuccess: constVoid }) /* @internal */ export const ignoreLogged = (self: Effect.Effect): Effect.Effect => core.matchCauseEffect(self, { onFailure: (cause) => logDebug(cause, "An error was silently ignored because it is not anticipated to be useful"), onSuccess: () => core.void }) /* @internal */ export const inheritFiberRefs = (childFiberRefs: FiberRefs.FiberRefs) => updateFiberRefs((parentFiberId, parentFiberRefs) => FiberRefs.joinAs(parentFiberRefs, parentFiberId, childFiberRefs)) /* @internal */ export const isFailure = (self: Effect.Effect): Effect.Effect => match(self, { onFailure: constTrue, onSuccess: constFalse }) /* @internal */ export const isSuccess = (self: Effect.Effect): Effect.Effect => match(self, { onFailure: constFalse, onSuccess: constTrue }) /* @internal */ export const iterate: { ( initial: A, options: { readonly while: Predicate.Refinement readonly body: (b: B) => Effect.Effect } ): Effect.Effect ( initial: A, options: { readonly while: Predicate.Predicate readonly body: (a: A) => Effect.Effect } ): Effect.Effect } = ( initial: A, options: { readonly while: Predicate.Predicate readonly body: (z: A) => Effect.Effect } ): Effect.Effect => core.suspend(() => { if (options.while(initial)) { return core.flatMap(options.body(initial), (z2) => iterate(z2, options)) } return core.succeed(initial) }) /** @internal */ export const logWithLevel = (level?: LogLevel.LogLevel) => ( ...message: ReadonlyArray ): Effect.Effect => { const levelOption = Option.fromNullable(level) let cause: Cause.Cause | undefined = undefined for (let i = 0, len = message.length; i < len; i++) { const msg = message[i] if (internalCause.isCause(msg)) { if (cause !== undefined) { cause = internalCause.sequential(cause, msg) } else { cause = msg } message = [...message.slice(0, i), ...message.slice(i + 1)] i-- } } if (cause === undefined) { cause = internalCause.empty } return core.withFiberRuntime((fiberState) => { fiberState.log(message, cause, levelOption) return core.void }) } /** @internal */ export const log: (...message: ReadonlyArray) => Effect.Effect = logWithLevel() /** @internal */ export const logTrace: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Trace ) /** @internal */ export const logDebug: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Debug ) /** @internal */ export const logInfo: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Info ) /** @internal */ export const logWarning: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Warning ) /** @internal */ export const logError: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Error ) /** @internal */ export const logFatal: (...message: ReadonlyArray) => Effect.Effect = logWithLevel( LogLevel.Fatal ) /* @internal */ export const withLogSpan = dual< (label: string) => (effect: Effect.Effect) => Effect.Effect, (effect: Effect.Effect, label: string) => Effect.Effect >(2, (effect, label) => core.flatMap(Clock.currentTimeMillis, (now) => core.fiberRefLocallyWith( effect, core.currentLogSpan, List.prepend(LogSpan.make(label, now)) ))) /* @internal */ export const logAnnotations: Effect.Effect> = core .fiberRefGet( core.currentLogAnnotations ) /* @internal */ export const loop: { ( initial: A, options: { readonly while: Predicate.Refinement readonly step: (b: B) => A readonly body: (b: B) => Effect.Effect readonly discard?: false | undefined } ): Effect.Effect, E, R> ( initial: A, options: { readonly while: (a: A) => boolean readonly step: (a: A) => A readonly body: (a: A) => Effect.Effect readonly discard?: false | undefined } ): Effect.Effect, E, R> ( initial: A, options: { readonly while: Predicate.Refinement readonly step: (b: B) => A readonly body: (b: B) => Effect.Effect readonly discard: true } ): Effect.Effect ( initial: A, options: { readonly while: (a: A) => boolean readonly step: (a: A) => A readonly body: (a: A) => Effect.Effect readonly discard: true } ): Effect.Effect } = ( initial: A, options: { readonly while: Predicate.Predicate readonly step: (a: A) => A readonly body: (a: A) => Effect.Effect readonly discard?: boolean | undefined } ): any => options.discard ? loopDiscard(initial, options.while, options.step, options.body) : core.map(loopInternal(initial, options.while, options.step, options.body), Arr.fromIterable) const loopInternal = ( initial: Z, cont: Predicate.Predicate, inc: (z: Z) => Z, body: (z: Z) => Effect.Effect ): Effect.Effect, E, R> => core.suspend(() => cont(initial) ? core.flatMap(body(initial), (a) => core.map( loopInternal(inc(initial), cont, inc, body), List.prepend(a) )) : core.sync(() => List.empty()) ) const loopDiscard = ( initial: S, cont: Predicate.Predicate, inc: (s: S) => S, body: (s: S) => Effect.Effect ): Effect.Effect => core.suspend(() => cont(initial) ? core.flatMap( body(initial), () => loopDiscard(inc(initial), cont, inc, body) ) : core.void ) /* @internal */ export const mapAccum: { = Iterable>( initial: S, f: (state: S, a: A, i: number) => Effect.Effect ): (elements: I) => Effect.Effect<[S, Arr.ReadonlyArray.With], E, R> = Iterable>( elements: I, initial: S, f: (state: S, a: A, i: number) => Effect.Effect ): Effect.Effect<[S, Arr.ReadonlyArray.With], E, R> } = dual(3, = Iterable>( elements: I, initial: S, f: (state: S, a: A, i: number) => Effect.Effect ): Effect.Effect<[S, Array], E, R> => core.suspend(() => { const iterator = elements[Symbol.iterator]() const builder: Array = [] let result: Effect.Effect = core.succeed(initial) let next: IteratorResult let i = 0 while (!(next = iterator.next()).done) { const index = i++ const value = next.value result = core.flatMap(result, (state) => core.map(f(state, value, index), ([z, b]) => { builder.push(b) return z })) } return core.map(result, (z) => [z, builder]) })) /* @internal */ export const mapErrorCause: { ( f: (cause: Cause.Cause) => Cause.Cause ): (self: Effect.Effect) => Effect.Effect (self: Effect.Effect, f: (cause: Cause.Cause) => Cause.Cause): Effect.Effect } = dual( 2, (self: Effect.Effect, f: (cause: Cause.Cause) => Cause.Cause): Effect.Effect => core.matchCauseEffect(self, { onFailure: (c) => core.failCauseSync(() => f(c)), onSuccess: core.succeed }) ) /* @internal */ export const memoize = ( self: Effect.Effect ): Effect.Effect> => pipe( core.deferredMake<[[FiberRefsPatch.FiberRefsPatch, runtimeFlagsPatch.RuntimeFlagsPatch], A], E>(), core.flatMap((deferred) => pipe( diffFiberRefsAndRuntimeFlags(self), core.intoDeferred(deferred), once, core.map((complete) => core.zipRight( complete, pipe( core.deferredAwait(deferred), core.flatMap(([patch, a]) => core.as(core.zip(patchFiberRefs(patch[0]), core.updateRuntimeFlags(patch[1])), a) ) ) ) ) ) ) ) /* @internal */ export const merge = (self: Effect.Effect): Effect.Effect => core.matchEffect(self, { onFailure: (e) => core.succeed(e), onSuccess: core.succeed }) /* @internal */ export const negate = (self: Effect.Effect): Effect.Effect => core.map(self, (b) => !b) /* @internal */ export const none = ( self: Effect.Effect, E, R> ): Effect.Effect => core.flatMap(self, (option) => { switch (option._tag) { case "None": return core.void case "Some": return core.fail(new core.NoSuchElementException()) } }) /* @internal */ export const once = ( self: Effect.Effect ): Effect.Effect> => core.map( Ref.make(true), (ref) => core.asVoid(core.whenEffect(self, Ref.getAndSet(ref, false))) ) /* @internal */ export const option = (self: Effect.Effect): Effect.Effect, never, R> => core.matchEffect(self, { onFailure: () => core.succeed(Option.none()), onSuccess: (a) => core.succeed(Option.some(a)) }) /* @internal */ export const orElseFail = dual< (evaluate: LazyArg) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, evaluate: LazyArg) => Effect.Effect >(2, (self, evaluate) => core.orElse(self, () => core.failSync(evaluate))) /* @internal */ export const orElseSucceed = dual< (evaluate: LazyArg) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, evaluate: LazyArg) => Effect.Effect >(2, (self, evaluate) => core.orElse(self, () => core.sync(evaluate))) /* @internal */ export const parallelErrors = (self: Effect.Effect): Effect.Effect, R> => core.matchCauseEffect(self, { onFailure: (cause) => { const errors = Arr.fromIterable(internalCause.failures(cause)) return errors.length === 0 ? core.failCause(cause as Cause.Cause) : core.fail(errors) }, onSuccess: core.succeed }) /* @internal */ export const patchFiberRefs = (patch: FiberRefsPatch.FiberRefsPatch): Effect.Effect => updateFiberRefs((fiberId, fiberRefs) => pipe(patch, fiberRefsPatch.patch(fiberId, fiberRefs))) /* @internal */ export const promise = (evaluate: (signal: AbortSignal) => PromiseLike): Effect.Effect => evaluate.length >= 1 ? core.async((resolve, signal) => { try { evaluate(signal) .then((a) => resolve(core.succeed(a)), (e) => resolve(core.die(e))) } catch (e) { resolve(core.die(e)) } }) : core.async((resolve) => { try { ;(evaluate as LazyArg>)() .then((a) => resolve(core.succeed(a)), (e) => resolve(core.die(e))) } catch (e) { resolve(core.die(e)) } }) /* @internal */ export const provideService = dual< ( tag: Context.Tag, service: Types.NoInfer ) => (self: Effect.Effect) => Effect.Effect>, ( self: Effect.Effect, tag: Context.Tag, service: Types.NoInfer ) => Effect.Effect> >( 3, ( self: Effect.Effect, tag: Context.Tag, service: Types.NoInfer ): Effect.Effect> => core.contextWithEffect((env) => core.provideContext( self as Effect.Effect>, Context.add(env, tag, service) ) ) ) /* @internal */ export const provideServiceEffect = dual< ( tag: Context.Tag, effect: Effect.Effect, E1, R1> ) => (self: Effect.Effect) => Effect.Effect>, ( self: Effect.Effect, tag: Context.Tag, effect: Effect.Effect, E1, R1> ) => Effect.Effect> >(3, ( self: Effect.Effect, tag: Context.Tag, effect: Effect.Effect, E1, R1> ) => core.contextWithEffect((env: Context.Context>) => core.flatMap( effect, (service) => core.provideContext(self, pipe(env, Context.add(tag, service)) as Context.Context) ) )) /* @internal */ export const random: Effect.Effect = defaultServices.randomWith(core.succeed) /* @internal */ export const reduce = dual< ( zero: Z, f: (z: Z, a: A, i: number) => Effect.Effect ) => (elements: Iterable) => Effect.Effect, ( elements: Iterable, zero: Z, f: (z: Z, a: A, i: number) => Effect.Effect ) => Effect.Effect >( 3, ( elements: Iterable, zero: Z, f: (z: Z, a: A, i: number) => Effect.Effect ) => Arr.fromIterable(elements).reduce( (acc, el, i) => core.flatMap(acc, (a) => f(a, el, i)), core.succeed(zero) as Effect.Effect ) ) /* @internal */ export const reduceRight = dual< ( zero: Z, f: (a: A, z: Z, i: number) => Effect.Effect ) => (elements: Iterable) => Effect.Effect, ( elements: Iterable, zero: Z, f: (a: A, z: Z, i: number) => Effect.Effect ) => Effect.Effect >( 3, (elements: Iterable, zero: Z, f: (a: A, z: Z, i: number) => Effect.Effect) => Arr.fromIterable(elements).reduceRight( (acc, el, i) => core.flatMap(acc, (a) => f(el, a, i)), core.succeed(zero) as Effect.Effect ) ) /* @internal */ export const reduceWhile = dual< ( zero: Z, options: { readonly while: Predicate.Predicate readonly body: (s: Z, a: A, i: number) => Effect.Effect } ) => (elements: Iterable) => Effect.Effect, ( elements: Iterable, zero: Z, options: { readonly while: Predicate.Predicate readonly body: (s: Z, a: A, i: number) => Effect.Effect } ) => Effect.Effect >(3, ( elements: Iterable, zero: Z, options: { readonly while: Predicate.Predicate readonly body: (s: Z, a: A, i: number) => Effect.Effect } ) => core.flatMap( core.sync(() => elements[Symbol.iterator]()), (iterator) => reduceWhileLoop(iterator, 0, zero, options.while, options.body) )) const reduceWhileLoop = ( iterator: Iterator, index: number, state: Z, predicate: Predicate.Predicate, f: (s: Z, a: A, i: number) => Effect.Effect ): Effect.Effect => { const next = iterator.next() if (!next.done && predicate(state)) { return core.flatMap( f(state, next.value, index), (nextState) => reduceWhileLoop(iterator, index + 1, nextState, predicate, f) ) } return core.succeed(state) } /* @internal */ export const repeatN = dual< (n: number) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, n: number) => Effect.Effect >(2, (self, n) => core.suspend(() => repeatNLoop(self, n))) /* @internal */ const repeatNLoop = (self: Effect.Effect, n: number): Effect.Effect => core.flatMap(self, (a) => n <= 0 ? core.succeed(a) : core.zipRight(core.yieldNow(), repeatNLoop(self, n - 1))) /* @internal */ export const sandbox = (self: Effect.Effect): Effect.Effect, R> => core.matchCauseEffect(self, { onFailure: core.fail, onSuccess: core.succeed }) /* @internal */ export const setFiberRefs = (fiberRefs: FiberRefs.FiberRefs): Effect.Effect => core.suspend(() => FiberRefs.setAll(fiberRefs)) /* @internal */ export const sleep: (duration: Duration.DurationInput) => Effect.Effect = Clock.sleep /* @internal */ export const succeedNone: Effect.Effect> = core.succeed(Option.none()) /* @internal */ export const succeedSome = (value: A): Effect.Effect> => core.succeed(Option.some(value)) /* @internal */ export const summarized: { ( summary: Effect.Effect, f: (start: B, end: B) => C ): (self: Effect.Effect) => Effect.Effect<[C, A], E2 | E, R2 | R> ( self: Effect.Effect, summary: Effect.Effect, f: (start: B, end: B) => C ): Effect.Effect<[C, A], E2 | E, R2 | R> } = dual( 3, ( self: Effect.Effect, summary: Effect.Effect, f: (start: B, end: B) => C ): Effect.Effect<[C, A], E2 | E, R2 | R> => core.flatMap( summary, (start) => core.flatMap(self, (value) => core.map(summary, (end) => [f(start, end), value])) ) ) /* @internal */ export const tagMetrics = dual< { (key: string, value: string): (effect: Effect.Effect) => Effect.Effect ( values: Record ): (effect: Effect.Effect) => Effect.Effect }, { (effect: Effect.Effect, key: string, value: string): Effect.Effect (effect: Effect.Effect, values: Record): Effect.Effect } >((args) => core.isEffect(args[0]), function() { return labelMetrics( arguments[0], typeof arguments[1] === "string" ? [metricLabel.make(arguments[1], arguments[2])] : Object.entries(arguments[1]).map(([k, v]) => metricLabel.make(k, v)) ) }) /* @internal */ export const labelMetrics = dual< (labels: Iterable) => (self: Effect.Effect) => Effect.Effect, (self: Effect.Effect, labels: Iterable) => Effect.Effect >( 2, (self, labels) => core.fiberRefLocallyWith(self, core.currentMetricLabels, (old) => Arr.union(old, labels)) ) /* @internal */ export const takeUntil: { ( predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): (elements: Iterable) => Effect.Effect, E, R> ( elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): Effect.Effect, E, R> } = dual( 2, ( elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect ): Effect.Effect, E, R> => core.suspend(() => { const iterator = elements[Symbol.iterator]() const builder: Array = [] let next: IteratorResult let effect: Effect.Effect = core.succeed(false) let i = 0 while ((next = iterator.next()) && !next.done) { const a = next.value const index = i++ effect = core.flatMap(effect, (bool) => { if (bool) { return core.succeed(true) } builder.push(a) return predicate(a, index) }) } return core.map(effect, () => builder) }) ) /* @internal */ export const takeWhile = dual< ( predicate: (a: Types.NoInfer, i: number) => Effect.Effect ) => (elements: Iterable) => Effect.Effect, E, R>, ( elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect ) => Effect.Effect, E, R> >( 2, (elements: Iterable, predicate: (a: Types.NoInfer, i: number) => Effect.Effect) => core.suspend(() => { const iterator = elements[Symbol.iterator]() const builder: Array = [] let next: IteratorResult let taking: Effect.Effect = core.succeed(true) let i = 0 while ((next = iterator.next()) && !next.done) { const a = next.value const index = i++ taking = core.flatMap(taking, (taking) => pipe( taking ? predicate(a, index) : core.succeed(false), core.map((bool) => { if (bool) { builder.push(a) } return bool }) )) } return core.map(taking, () => builder) }) ) /* @internal */ export const tapBoth = dual< ( options: { readonly onFailure: (e: Types.NoInfer) => Effect.Effect readonly onSuccess: (a: Types.NoInfer) => 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 >(2, (self, { onFailure, onSuccess }) => core.matchCauseEffect(self, { onFailure: (cause) => { const either = internalCause.failureOrCause(cause) switch (either._tag) { case "Left": { return core.zipRight(onFailure(either.left as any), core.failCause(cause)) } case "Right": { return core.failCause(cause) } } }, onSuccess: (a) => core.as(onSuccess(a as any), a) })) /* @internal */ export const tapDefect = 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) => core.catchAllCause(self, (cause) => Option.match(internalCause.keepDefects(cause), { onNone: () => core.failCause(cause), onSome: (a) => core.zipRight(f(a), core.failCause(cause)) }))) /* @internal */ export const tapError = dual< ( f: (e: Types.NoInfer) => Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, f: (e: E) => Effect.Effect ) => Effect.Effect >(2, (self, f) => core.matchCauseEffect(self, { onFailure: (cause) => { const either = internalCause.failureOrCause(cause) switch (either._tag) { case "Left": return core.zipRight(f(either.left as any), core.failCause(cause)) case "Right": return core.failCause(cause) } }, onSuccess: core.succeed })) /* @internal */ export const tapErrorTag = dual< ( k: K, f: (e: Extract) => Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, k: K, f: (e: Extract) => Effect.Effect ) => Effect.Effect >(3, (self, k, f) => tapError(self, (e) => { if (Predicate.isTagged(e, k)) { return f(e as any) } return core.void as any })) /* @internal */ export const tapErrorCause = 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) => core.matchCauseEffect(self, { onFailure: (cause) => core.zipRight(f(cause), core.failCause(cause)), onSuccess: core.succeed })) /* @internal */ export const timed = ( self: Effect.Effect ): Effect.Effect<[duration: Duration.Duration, result: A], E, R> => timedWith(self, Clock.currentTimeNanos) /* @internal */ export const timedWith = dual< ( nanoseconds: Effect.Effect ) => (self: Effect.Effect) => Effect.Effect<[Duration.Duration, A], E | E1, R | R1>, ( self: Effect.Effect, nanoseconds: Effect.Effect ) => Effect.Effect<[Duration.Duration, A], E | E1, R | R1> >( 2, (self, nanos) => summarized(self, nanos, (start, end) => Duration.nanos(end - start)) ) /* @internal */ export const tracerWith: (f: (tracer: Tracer.Tracer) => Effect.Effect) => Effect.Effect = Tracer.tracerWith /** @internal */ export const tracer: Effect.Effect = tracerWith(core.succeed) /* @internal */ export const tryPromise: { ( options: { readonly try: (signal: AbortSignal) => PromiseLike readonly catch: (error: unknown) => E } ): Effect.Effect (evaluate: (signal: AbortSignal) => PromiseLike): Effect.Effect } = ( arg: ((signal: AbortSignal) => PromiseLike) | { readonly try: (signal: AbortSignal) => PromiseLike readonly catch: (error: unknown) => E } ): Effect.Effect => { let evaluate: (signal?: AbortSignal) => PromiseLike let catcher: ((error: unknown) => E) | undefined = undefined if (typeof arg === "function") { evaluate = arg as (signal?: AbortSignal) => PromiseLike } else { evaluate = arg.try as (signal?: AbortSignal) => PromiseLike catcher = arg.catch } const fail = (e: unknown) => catcher ? core.failSync(() => catcher(e)) : core.fail(new core.UnknownException(e, "An unknown error occurred in Effect.tryPromise")) if (evaluate.length >= 1) { return core.async((resolve, signal) => { try { evaluate(signal).then( (a) => resolve(core.succeed(a)), (e) => resolve(fail(e)) ) } catch (e) { resolve(fail(e)) } }) } return core.async((resolve) => { try { evaluate() .then( (a) => resolve(core.succeed(a)), (e) => resolve(fail(e)) ) } catch (e) { resolve(fail(e)) } }) } /* @internal */ export const tryMap = dual< ( options: { readonly try: (a: A) => B readonly catch: (error: unknown) => E1 } ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, options: { readonly try: (a: A) => B readonly catch: (error: unknown) => E1 } ) => Effect.Effect >(2, (self, options) => core.flatMap(self, (a) => try_({ try: () => options.try(a), catch: options.catch }))) /* @internal */ export const tryMapPromise = dual< ( options: { readonly try: (a: A, signal: AbortSignal) => PromiseLike readonly catch: (error: unknown) => E1 } ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, options: { readonly try: (a: A, signal: AbortSignal) => PromiseLike readonly catch: (error: unknown) => E1 } ) => Effect.Effect >(2, ( self: Effect.Effect, options: { readonly try: (a: A, signal: AbortSignal) => PromiseLike readonly catch: (error: unknown) => E1 } ) => core.flatMap(self, (a) => tryPromise({ try: options.try.length >= 1 ? (signal) => options.try(a, signal) : () => (options.try as (a: A) => PromiseLike)(a), catch: options.catch }))) /* @internal */ export const unless = dual< (condition: LazyArg) => (self: Effect.Effect) => Effect.Effect, E, R>, (self: Effect.Effect, condition: LazyArg) => Effect.Effect, E, R> >(2, (self, condition) => core.suspend(() => condition() ? succeedNone : asSome(self) )) /* @internal */ export const unlessEffect = dual< ( condition: Effect.Effect ) => (self: Effect.Effect) => Effect.Effect, E | E2, R | R2>, ( self: Effect.Effect, condition: Effect.Effect ) => Effect.Effect, E | E2, R | R2> >(2, (self, condition) => core.flatMap(condition, (b) => (b ? succeedNone : asSome(self)))) /* @internal */ export const unsandbox = (self: Effect.Effect, R>) => mapErrorCause(self, internalCause.flatten) /* @internal */ export const updateFiberRefs = ( f: (fiberId: FiberId.Runtime, fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs ): Effect.Effect => core.withFiberRuntime((state) => { state.setFiberRefs(f(state.id(), state.getFiberRefs())) return core.void }) /* @internal */ export const updateService = dual< ( tag: Context.Tag, f: (service: Types.NoInfer) => Types.NoInfer ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, tag: Context.Tag, f: (service: Types.NoInfer) => Types.NoInfer ) => Effect.Effect >(3, ( self: Effect.Effect, tag: Context.Tag, f: (service: Types.NoInfer) => Types.NoInfer ) => core.mapInputContext(self, (context) => Context.add( context, tag, f(Context.unsafeGet(context, tag)) )) as Effect.Effect) /* @internal */ export const when = dual< (condition: LazyArg) => (self: Effect.Effect) => Effect.Effect, E, R>, (self: Effect.Effect, condition: LazyArg) => Effect.Effect, E, R> >(2, (self, condition) => core.suspend(() => condition() ? core.map(self, Option.some) : core.succeed(Option.none()) )) /* @internal */ export const whenFiberRef = dual< ( fiberRef: FiberRef.FiberRef, predicate: Predicate.Predicate ) => (self: Effect.Effect) => Effect.Effect<[S, Option.Option], E, R>, ( self: Effect.Effect, fiberRef: FiberRef.FiberRef, predicate: Predicate.Predicate ) => Effect.Effect<[S, Option.Option], E, R> >( 3, ( self: Effect.Effect, fiberRef: FiberRef.FiberRef, predicate: Predicate.Predicate ) => core.flatMap(core.fiberRefGet(fiberRef), (s) => predicate(s) ? core.map(self, (a) => [s, Option.some(a)]) : core.succeed<[S, Option.Option]>([s, Option.none()])) ) /* @internal */ export const whenRef = dual< ( ref: Ref.Ref, predicate: Predicate.Predicate ) => (self: Effect.Effect) => Effect.Effect<[S, Option.Option], E, R>, ( self: Effect.Effect, ref: Ref.Ref, predicate: Predicate.Predicate ) => Effect.Effect<[S, Option.Option], E, R> >( 3, (self: Effect.Effect, ref: Ref.Ref, predicate: Predicate.Predicate) => core.flatMap(Ref.get(ref), (s) => predicate(s) ? core.map(self, (a) => [s, Option.some(a)]) : core.succeed<[S, Option.Option]>([s, Option.none()])) ) /* @internal */ export const withMetric = dual< ( metric: Metric.Metric ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, metric: Metric.Metric ) => Effect.Effect >(2, (self, metric) => metric(self)) /** @internal */ export const serviceFunctionEffect = , Args extends Array, A, E, R>( getService: T, f: (_: Effect.Effect.Success) => (...args: Args) => Effect.Effect ) => (...args: Args): Effect.Effect, R | Effect.Effect.Context> => core.flatMap(getService, (a) => f(a)(...args)) /** @internal */ export const serviceFunction = , Args extends Array, A>( getService: T, f: (_: Effect.Effect.Success) => (...args: Args) => A ) => (...args: Args): Effect.Effect, Effect.Effect.Context> => core.map(getService, (a) => f(a)(...args)) /** @internal */ export const serviceFunctions = ( getService: Effect.Effect ): { [k in keyof S as S[k] extends (...args: Array) => Effect.Effect ? k : never]: S[k] extends (...args: infer Args) => Effect.Effect ? (...args: Args) => Effect.Effect : never } => new Proxy({} as any, { get(_target: any, prop: any, _receiver) { return (...args: Array) => core.flatMap(getService, (s: any) => s[prop](...args)) } }) /** @internal */ export const serviceConstants = ( getService: Effect.Effect ): { [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect.Effect ? Effect.Effect : Effect.Effect } => new Proxy({} as any, { get(_target: any, prop: any, _receiver) { return core.flatMap(getService, (s: any) => core.isEffect(s[prop]) ? s[prop] : core.succeed(s[prop])) } }) /** @internal */ export const serviceMembers = (getService: Effect.Effect): { functions: { [k in keyof S as S[k] extends (...args: Array) => Effect.Effect ? k : never]: S[k] extends (...args: infer Args) => Effect.Effect ? (...args: Args) => Effect.Effect : never } constants: { [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect.Effect ? Effect.Effect : Effect.Effect } } => ({ functions: serviceFunctions(getService) as any, constants: serviceConstants(getService) }) /** @internal */ export const serviceOption = (tag: Context.Tag) => core.map(core.context(), Context.getOption(tag)) /** @internal */ export const serviceOptional = (tag: Context.Tag) => core.flatMap(core.context(), Context.getOption(tag)) // ----------------------------------------------------------------------------- // tracing // ----------------------------------------------------------------------------- /* @internal */ export const annotateCurrentSpan: { (key: string, value: unknown): Effect.Effect (values: Record): Effect.Effect } = function(): Effect.Effect { const args = arguments return ignore(core.flatMap( currentSpan, (span) => core.sync(() => { if (typeof args[0] === "string") { span.attribute(args[0], args[1]) } else { for (const key in args[0]) { span.attribute(key, args[0][key]) } } }) )) } /* @internal */ export const linkSpanCurrent: { (span: Tracer.AnySpan, attributes?: Readonly> | undefined): Effect.Effect (links: ReadonlyArray): Effect.Effect } = function(): Effect.Effect { const args = arguments const links: ReadonlyArray = Array.isArray(args[0]) ? args[0] : [{ _tag: "SpanLink", span: args[0], attributes: args[1] ?? {} }] return ignore(core.flatMap( currentSpan, (span) => core.sync(() => span.addLinks(links)) )) } /* @internal */ export const annotateSpans = dual< { (key: string, value: unknown): (effect: Effect.Effect) => Effect.Effect ( values: Record ): (effect: Effect.Effect) => Effect.Effect }, { (effect: Effect.Effect, key: string, value: unknown): Effect.Effect (effect: Effect.Effect, values: Record): Effect.Effect } >( (args) => core.isEffect(args[0]), function() { const args = arguments return core.fiberRefLocallyWith( args[0] as Effect.Effect, core.currentTracerSpanAnnotations, typeof args[1] === "string" ? HashMap.set(args[1], args[2]) : (annotations) => Object.entries(args[1] as Record).reduce( (acc, [key, value]) => HashMap.set(acc, key, value), annotations ) ) } ) /** @internal */ export const currentParentSpan: Effect.Effect = serviceOptional( internalTracer.spanTag ) /** @internal */ export const currentSpan: Effect.Effect = core.flatMap( core.context(), (context) => { const span = context.unsafeMap.get(internalTracer.spanTag.key) as Tracer.AnySpan | undefined return span !== undefined && span._tag === "Span" ? core.succeed(span) : core.fail(new core.NoSuchElementException()) } ) /* @internal */ export const linkSpans = dual< ( span: Tracer.AnySpan, attributes?: Record ) => (self: Effect.Effect) => Effect.Effect, ( self: Effect.Effect, span: Tracer.AnySpan, attributes?: Record ) => Effect.Effect >( (args) => core.isEffect(args[0]), (self, span, attributes) => core.fiberRefLocallyWith( self, core.currentTracerSpanLinks, Chunk.append( { _tag: "SpanLink", span, attributes: attributes ?? {} } as const ) ) ) const bigint0 = BigInt(0) const filterDisablePropagation: (self: Option.Option) => Option.Option = Option.flatMap( (span) => Context.get(span.context, internalTracer.DisablePropagation) ? span._tag === "Span" ? filterDisablePropagation(span.parent) : Option.none() : Option.some(span) ) /** @internal */ export const unsafeMakeSpan = ( fiber: FiberRuntime, name: string, options: Tracer.SpanOptions ) => { const disablePropagation = !fiber.getFiberRef(core.currentTracerEnabled) || (options.context && Context.get(options.context, internalTracer.DisablePropagation)) const context = fiber.getFiberRef(core.currentContext) const parent = options.parent ? Option.some(options.parent) : options.root ? Option.none() : filterDisablePropagation(Context.getOption(context, internalTracer.spanTag)) let span: Tracer.Span if (disablePropagation) { span = core.noopSpan({ name, parent, context: Context.add(options.context ?? Context.empty(), internalTracer.DisablePropagation, true) }) } else { const services = fiber.getFiberRef(defaultServices.currentServices) const tracer = Context.get(services, internalTracer.tracerTag) const clock = Context.get(services, Clock.Clock) const timingEnabled = fiber.getFiberRef(core.currentTracerTimingEnabled) const fiberRefs = fiber.getFiberRefs() const annotationsFromEnv = FiberRefs.get(fiberRefs, core.currentTracerSpanAnnotations) const linksFromEnv = FiberRefs.get(fiberRefs, core.currentTracerSpanLinks) const links = linksFromEnv._tag === "Some" ? options.links !== undefined ? [ ...Chunk.toReadonlyArray(linksFromEnv.value), ...(options.links ?? []) ] : Chunk.toReadonlyArray(linksFromEnv.value) : options.links ?? Arr.empty() span = tracer.span( name, parent, options.context ?? Context.empty(), links, timingEnabled ? clock.unsafeCurrentTimeNanos() : bigint0, options.kind ?? "internal", options ) if (annotationsFromEnv._tag === "Some") { HashMap.forEach(annotationsFromEnv.value, (value, key) => span.attribute(key, value)) } if (options.attributes !== undefined) { Object.entries(options.attributes).forEach(([k, v]) => span.attribute(k, v)) } } if (typeof options.captureStackTrace === "function") { internalCause.spanToTrace.set(span, options.captureStackTrace) } return span } /** @internal */ export const makeSpan = ( name: string, options?: Tracer.SpanOptions ): Effect.Effect => { options = internalTracer.addSpanStackTrace(options) return core.withFiberRuntime((fiber) => core.succeed(unsafeMakeSpan(fiber, name, options))) } /* @internal */ export const spanAnnotations: Effect.Effect> = core .fiberRefGet(core.currentTracerSpanAnnotations) /* @internal */ export const spanLinks: Effect.Effect> = core .fiberRefGet(core.currentTracerSpanLinks) /** @internal */ export const endSpan = (span: Tracer.Span, exit: Exit, clock: Clock.Clock, timingEnabled: boolean) => core.sync(() => { if (span.status._tag === "Ended") { return } if (core.exitIsFailure(exit) && internalCause.spanToTrace.has(span)) { // https://opentelemetry.io/docs/specs/semconv/registry/attributes/code/#code-stacktrace span.attribute("code.stacktrace", internalCause.spanToTrace.get(span)!()) } span.end(timingEnabled ? clock.unsafeCurrentTimeNanos() : bigint0, exit) }) /** @internal */ export const useSpan: { (name: string, evaluate: (span: Tracer.Span) => Effect.Effect): Effect.Effect ( name: string, options: Tracer.SpanOptions, evaluate: (span: Tracer.Span) => Effect.Effect ): Effect.Effect } = ( name: string, ...args: [evaluate: (span: Tracer.Span) => Effect.Effect] | [ options: any, evaluate: (span: Tracer.Span) => Effect.Effect ] ) => { const options = internalTracer.addSpanStackTrace(args.length === 1 ? undefined : args[0]) const evaluate: (span: Tracer.Span) => Effect.Effect = args[args.length - 1] return core.withFiberRuntime((fiber) => { const span = unsafeMakeSpan(fiber, name, options) const timingEnabled = fiber.getFiberRef(core.currentTracerTimingEnabled) const clock = Context.get(fiber.getFiberRef(defaultServices.currentServices), clockTag) return core.onExit(evaluate(span), (exit) => endSpan(span, exit, clock, timingEnabled)) }) } /** @internal */ export const withParentSpan = dual< ( span: Tracer.AnySpan ) => (self: Effect.Effect) => Effect.Effect>, (self: Effect.Effect, span: Tracer.AnySpan) => Effect.Effect> >(2, (self, span) => provideService(self, internalTracer.spanTag, span)) /** @internal */ export const withSpan: { ( name: string, options?: Tracer.SpanOptions | undefined ): (self: Effect.Effect) => Effect.Effect> ( self: Effect.Effect, name: string, options?: Tracer.SpanOptions | undefined ): Effect.Effect> } = function() { const dataFirst = typeof arguments[0] !== "string" const name = dataFirst ? arguments[1] : arguments[0] const options = internalTracer.addSpanStackTrace(dataFirst ? arguments[2] : arguments[1]) if (dataFirst) { const self = arguments[0] return useSpan(name, options, (span) => withParentSpan(self, span)) } return (self: Effect.Effect) => useSpan(name, options, (span) => withParentSpan(self, span)) } as any export const functionWithSpan = , Ret extends Effect.Effect>( options: { readonly body: (...args: Args) => Ret readonly options: Effect.FunctionWithSpanOptions | ((...args: Args) => Effect.FunctionWithSpanOptions) readonly captureStackTrace?: boolean | undefined } ): (...args: Args) => Unify => (function(this: any) { let captureStackTrace: LazyArg | boolean = options.captureStackTrace ?? false if (options.captureStackTrace !== false) { const limit = Error.stackTraceLimit Error.stackTraceLimit = 2 const error = new Error() Error.stackTraceLimit = limit let cache: false | string = false captureStackTrace = () => { if (cache !== false) { return cache } if (error.stack) { const stack = error.stack.trim().split("\n") cache = stack.slice(2).join("\n").trim() return cache } } } return core.suspend(() => { const opts = typeof options.options === "function" ? options.options.apply(null, arguments as any) : options.options return withSpan( core.suspend(() => internalCall(() => options.body.apply(this, arguments as any))), opts.name, { ...opts, captureStackTrace } ) }) }) as any // ------------------------------------------------------------------------------------- // optionality // ------------------------------------------------------------------------------------- /* @internal */ export const fromNullable = (value: A): Effect.Effect, Cause.NoSuchElementException> => value == null ? core.fail(new core.NoSuchElementException()) : core.succeed(value as NonNullable) /* @internal */ export const optionFromOptional = ( self: Effect.Effect ): Effect.Effect, Exclude, R> => core.catchAll( core.map(self, Option.some), (error) => core.isNoSuchElementException(error) ? succeedNone : core.fail(error as Exclude) )