EdgeAIG's picture
download
raw
110 kB
import * as Arr from "../Array.js";
import * as Context from "../Context.js";
import * as Duration from "../Duration.js";
import * as Equal from "../Equal.js";
import * as Filter from "../Filter.js";
import { formatJson } from "../Formatter.js";
import { constant, constFalse, constTrue, constUndefined, constVoid, dual, identity } from "../Function.js";
import * as Hash from "../Hash.js";
import { toJson, toStringUnknown } from "../Inspectable.js";
import * as Iterable from "../Iterable.js";
import * as Option from "../Option.js";
import * as Order from "../Order.js";
import { pipeArguments } from "../Pipeable.js";
import { hasProperty, isIterable, isString, isTagged } from "../Predicate.js";
import { currentFiberTypeId, redact } from "../Redactable.js";
import * as Result from "../Result.js";
import * as Scheduler from "../Scheduler.js";
import * as Tracer from "../Tracer.js";
import { internalCall } from "../Utils.js";
import { args, causeAnnotate, causeEmpty, causeFromReasons, CauseImpl, constEmptyAnnotations, contA, contAll, contE, evaluate, exitDie, exitFail, exitFailCause, exitSucceed, ExitTypeId, Fail, InterruptorStackTrace, isCause, isDieReason, isEffect, isFailReason, isInterruptReason, isNoSuchElementError, makePrimitive, makePrimitiveProto, NoSuchElementError, ReasonBase, StackTraceKey as CauseStackTrace, TaggedError, withFiber, Yield } from "./core.js";
import * as doNotation from "./doNotation.js";
import * as InternalMetric from "./metric.js";
import { CurrentConcurrency, CurrentErrorReporters, CurrentLogAnnotations, CurrentLogLevel, CurrentLogSpans, CurrentStackFrame, MinimumLogLevel, TracerEnabled, TracerSpanAnnotations, TracerSpanLinks, TracerTimingEnabled } from "./references.js";
import { addSpanStackTrace, makeStackCleaner } from "./tracer.js";
import { version } from "./version.js";
// ----------------------------------------------------------------------------
// Cause
// ----------------------------------------------------------------------------
/** @internal */
export class Interrupt extends ReasonBase {
fiberId;
constructor(fiberId, annotations = constEmptyAnnotations) {
super("Interrupt", annotations, "Interrupted");
this.fiberId = fiberId;
}
toString() {
return `Interrupt(${this.fiberId})`;
}
toJSON() {
return {
_tag: "Interrupt",
fiberId: this.fiberId
};
}
[Equal.symbol](that) {
return isInterruptReason(that) && this.fiberId === that.fiberId && this.annotations === that.annotations;
}
[Hash.symbol]() {
return Hash.combine(Hash.string(`${this._tag}:${this.fiberId}`))(Hash.random(this.annotations));
}
}
/** @internal */
export const makeInterruptReason = fiberId => new Interrupt(fiberId);
/** @internal */
export const causeInterrupt = fiberId => new CauseImpl([new Interrupt(fiberId)]);
/** @internal */
export const hasFails = self => self.reasons.some(isFailReason);
/** @internal */
export const findFail = self => {
const reason = self.reasons.find(isFailReason);
return reason ? Result.succeed(reason) : Result.fail(self);
};
/** @internal */
export const findError = self => {
for (let i = 0; i < self.reasons.length; i++) {
const reason = self.reasons[i];
if (reason._tag === "Fail") {
return Result.succeed(reason.error);
}
}
return Result.fail(self);
};
/** @internal */
export const findErrorOption = /*#__PURE__*/Filter.toOption(findError);
/** @internal */
export const hasDies = self => self.reasons.some(isDieReason);
/** @internal */
export const findDie = self => {
const reason = self.reasons.find(isDieReason);
return reason ? Result.succeed(reason) : Result.fail(self);
};
/** @internal */
export const findDefect = self => {
const reason = self.reasons.find(isDieReason);
return reason ? Result.succeed(reason.defect) : Result.fail(self);
};
/** @internal */
export const hasInterrupts = self => self.reasons.some(isInterruptReason);
/** @internal */
export const findInterrupt = self => {
const reason = self.reasons.find(isInterruptReason);
return reason ? Result.succeed(reason) : Result.fail(self);
};
/** @internal */
export const causeFilterInterruptors = self => {
let interruptors;
for (let i = 0; i < self.reasons.length; i++) {
const f = self.reasons[i];
if (f._tag !== "Interrupt") continue;
interruptors ??= new Set();
if (f.fiberId !== undefined) {
interruptors.add(f.fiberId);
}
}
return interruptors ? Result.succeed(interruptors) : Result.fail(self);
};
/** @internal */
export const causeInterruptors = self => {
const result = causeFilterInterruptors(self);
return Result.isFailure(result) ? emptySet : result.success;
};
const emptySet = /*#__PURE__*/new Set();
/** @internal */
export const hasInterruptsOnly = self => self.reasons.length > 0 && self.reasons.every(isInterruptReason);
/** @internal */
export const reasonAnnotations = self => Context.makeUnsafe(self.annotations);
/** @internal */
export const causeAnnotations = self => {
const map = new Map();
for (const f of self.reasons) {
if (f.annotations.size > 0) {
for (const [key, value] of f.annotations) {
map.set(key, value);
}
}
}
return Context.makeUnsafe(map);
};
/** @internal */
export const causeCombine = /*#__PURE__*/dual(2, (self, that) => {
if (self.reasons.length === 0) {
return that;
} else if (that.reasons.length === 0) {
return self;
}
const newCause = new CauseImpl(Arr.union(self.reasons, that.reasons));
return Equal.equals(self, newCause) ? self : newCause;
});
/** @internal */
export const causeMap = /*#__PURE__*/dual(2, (self, f) => {
let hasFail = false;
const failures = self.reasons.map(failure => {
if (isFailReason(failure)) {
hasFail = true;
return new Fail(f(failure.error));
}
return failure;
});
return hasFail ? causeFromReasons(failures) : self;
});
/** @internal */
export const causePartition = self => {
const obj = {
Fail: [],
Die: [],
Interrupt: []
};
for (let i = 0; i < self.reasons.length; i++) {
obj[self.reasons[i]._tag].push(self.reasons[i]);
}
return obj;
};
/** @internal */
export const causeSquash = self => {
const partitioned = causePartition(self);
if (partitioned.Fail.length > 0) {
return partitioned.Fail[0].error;
} else if (partitioned.Die.length > 0) {
return partitioned.Die[0].defect;
} else if (partitioned.Interrupt.length > 0) {
return new globalThis.Error("All fibers interrupted without error");
}
return new globalThis.Error("Empty cause");
};
/** @internal */
export const causePrettyErrors = self => {
const errors = [];
const interrupts = [];
if (self.reasons.length === 0) return errors;
const prevStackLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 1;
for (const failure of self.reasons) {
if (failure._tag === "Interrupt") {
interrupts.push(failure);
continue;
}
errors.push(causePrettyError(failure._tag === "Die" ? failure.defect : failure.error, failure.annotations));
}
if (errors.length === 0) {
const cause = new Error("The fiber was interrupted by:");
cause.name = "InterruptCause";
cause.stack = interruptCauseStack(cause, interrupts);
const error = new globalThis.Error("All fibers interrupted without error", {
cause
});
error.name = "InterruptError";
error.stack = `${error.name}: ${error.message}`;
errors.push(causePrettyError(error, interrupts[0].annotations));
}
;
Error.stackTraceLimit = prevStackLimit;
return errors;
};
/** @internal */
export const causePrettyError = (original, annotations) => {
const kind = typeof original;
let error;
if (original && kind === "object") {
error = new globalThis.Error(causePrettyMessage(original), {
cause: original.cause ? causePrettyError(original.cause) : undefined
});
if (typeof original.name === "string") {
error.name = original.name;
}
if (typeof original.stack === "string") {
error.stack = cleanErrorStack(original.stack, error, annotations);
} else {
const stack = `${error.name}: ${error.message}`;
error.stack = annotations ? addStackAnnotations(stack, annotations) : stack;
}
for (const key of Object.keys(original)) {
if (!(key in error)) {
;
error[key] = original[key];
}
}
} else {
error = new globalThis.Error(!original ? `Unknown error: ${original}` : kind === "string" ? original : formatJson(original));
}
return error;
};
const causePrettyMessage = u => {
if (typeof u.message === "string") {
return u.message;
} else if (typeof u.toString === "function" && u.toString !== Object.prototype.toString && u.toString !== Array.prototype.toString) {
try {
return u.toString();
} catch {
// something's off, rollback to json
}
}
return formatJson(u);
};
const locationRegExp = /\((.*)\)/g;
const cleanErrorStack = (stack, error, annotations) => {
const message = `${error.name}: ${error.message}`;
const lines = (stack.startsWith(message) ? stack.slice(message.length) : stack).split("\n");
const out = [message];
for (let i = 1; i < lines.length; i++) {
if (/(?:Generator\.next|~effect\/Effect)/.test(lines[i])) {
break;
}
out.push(lines[i]);
}
return annotations ? addStackAnnotations(out.join("\n"), annotations) : out.join("\n");
};
const addStackAnnotations = (stack, annotations) => {
const frame = annotations?.get(CauseStackTrace.key);
if (frame) {
stack = `${stack}\n${currentStackTrace(frame)}`;
}
return stack;
};
const interruptCauseStack = (error, interrupts) => {
const out = [`${error.name}: ${error.message}`];
for (const current of interrupts) {
const fiberId = current.fiberId !== undefined ? `#${current.fiberId}` : "unknown";
const frame = current.annotations.get(InterruptorStackTrace.key);
out.push(` at fiber (${fiberId})`);
if (frame) out.push(currentStackTrace(frame));
}
return out.join("\n");
};
const currentStackTrace = frame => {
const out = [];
let current = frame;
let i = 0;
while (current && i < 10) {
const stack = current.stack();
if (stack) {
const locationMatchAll = stack.matchAll(locationRegExp);
let match = false;
for (const [, location] of locationMatchAll) {
match = true;
out.push(` at ${current.name} (${location})`);
}
if (!match) {
out.push(` at ${current.name} (${stack.replace(/^at /, "")})`);
}
} else {
out.push(` at ${current.name}`);
}
current = current.parent;
i++;
}
return out.join("\n");
};
/** @internal */
export const causePretty = cause => causePrettyErrors(cause).map(e => e.cause ? `${e.stack} {\n${renderErrorCause(e.cause, " ")}\n}` : e.stack).join("\n");
const renderErrorCause = (cause, prefix) => {
const lines = cause.stack.split("\n");
let stack = `${prefix}[cause]: ${lines[0]}`;
for (let i = 1, len = lines.length; i < len; i++) {
stack += `\n${prefix}${lines[i]}`;
}
if (cause.cause) {
stack += ` {\n${renderErrorCause(cause.cause, `${prefix} `)}\n${prefix}}`;
}
return stack;
};
// ----------------------------------------------------------------------------
// Fiber
// ----------------------------------------------------------------------------
/** @internal */
export const FiberTypeId = `~effect/Fiber/${version}`;
const fiberVariance = {
_A: identity,
_E: identity
};
const fiberIdStore = {
id: 0
};
/** @internal */
export const getCurrentFiber = () => globalThis[currentFiberTypeId];
/** @internal */
export class FiberImpl {
constructor(context, interruptible = true) {
this[FiberTypeId] = fiberVariance;
this.setContext(context);
this.id = ++fiberIdStore.id;
this.currentOpCount = 0;
this.currentLoopCount = 0;
this.interruptible = interruptible;
this._stack = [];
this._observers = [];
this._exit = undefined;
this._children = undefined;
this._interruptedCause = undefined;
this._yielded = undefined;
this.runtimeMetrics?.recordFiberStart(this.context);
}
[FiberTypeId];
id;
interruptible;
currentOpCount;
currentLoopCount;
_stack;
_observers;
_exit;
_currentExit;
_children;
_interruptedCause;
_yielded;
// set in setContext
context;
currentScheduler;
currentTracerContext;
currentSpan;
currentLogLevel;
minimumLogLevel;
currentStackFrame;
runtimeMetrics;
maxOpsBeforeYield;
currentPreventYield;
_dispatcher = undefined;
get currentDispatcher() {
return this._dispatcher ??= this.currentScheduler.makeDispatcher();
}
getRef(ref) {
return Context.getReferenceUnsafe(this.context, ref);
}
addObserver(cb) {
if (this._exit) {
cb(this._exit);
return constVoid;
}
this._observers.push(cb);
return () => {
const index = this._observers.indexOf(cb);
if (index >= 0) {
this._observers.splice(index, 1);
}
};
}
interruptUnsafe(fiberId, annotations) {
if (this._exit) {
return;
}
let cause = causeInterrupt(fiberId);
if (this.currentStackFrame) {
cause = causeAnnotate(cause, Context.make(CauseStackTrace, this.currentStackFrame));
}
if (annotations) {
cause = causeAnnotate(cause, annotations);
}
this._interruptedCause = this._interruptedCause ? causeCombine(this._interruptedCause, cause) : cause;
if (this.interruptible) {
this.evaluate(failCause(this._interruptedCause));
}
}
pollUnsafe() {
return this._exit;
}
evaluate(effect) {
if (this._exit) {
return;
} else if (this._yielded !== undefined) {
const yielded = this._yielded;
this._yielded = undefined;
yielded();
}
const exit = this.runLoop(effect);
if (exit === Yield) {
return;
}
// the interruptChildren middleware is added in Effect.forkChild, so it can be
// tree-shaken if not used
const interruptChildren = fiberMiddleware.interruptChildren && fiberMiddleware.interruptChildren(this);
if (interruptChildren !== undefined) {
return this.evaluate(flatMap(interruptChildren, () => exit));
}
this._exit = exit;
this.runtimeMetrics?.recordFiberEnd(this.context, this._exit);
for (let i = 0; i < this._observers.length; i++) {
this._observers[i](exit);
}
this._observers.length = 0;
}
runLoop(effect) {
const prevFiber = globalThis[currentFiberTypeId];
globalThis[currentFiberTypeId] = this;
let yielding = false;
let current = effect;
this.currentOpCount = 0;
const currentLoop = ++this.currentLoopCount;
try {
while (true) {
this.currentOpCount++;
if (!yielding && !this.currentPreventYield && this.currentScheduler.shouldYield(this)) {
yielding = true;
const prev = current;
current = flatMap(yieldNow, () => prev);
}
current = this.currentTracerContext ? this.currentTracerContext(current, this) : current[evaluate](this);
if (currentLoop !== this.currentLoopCount) {
// another effect has taken over the loop,
return Yield;
} else if (current === Yield) {
const yielded = this._yielded;
if (ExitTypeId in yielded) {
this._yielded = undefined;
return yielded;
}
return Yield;
}
}
} catch (error) {
if (!hasProperty(current, evaluate)) {
return exitDie(`Fiber.runLoop: Not a valid effect: ${String(current)}`);
}
return this.runLoop(exitDie(error));
} finally {
;
globalThis[currentFiberTypeId] = prevFiber;
}
}
getCont(symbol) {
while (true) {
const op = this._stack.pop();
if (!op) return undefined;
const cont = op[contAll] && op[contAll](this);
if (cont) {
;
cont[symbol] = cont;
return cont;
}
if (op[symbol]) return op;
}
}
yieldWith(value) {
this._yielded = value;
return Yield;
}
children() {
return this._children ??= new Set();
}
pipe() {
return pipeArguments(this, arguments);
}
setContext(context) {
this.context = context;
const scheduler = this.getRef(Scheduler.Scheduler);
if (scheduler !== this.currentScheduler) {
this.currentScheduler = scheduler;
this._dispatcher = undefined;
}
this.currentSpan = context.mapUnsafe.get(Tracer.ParentSpanKey);
this.currentLogLevel = this.getRef(CurrentLogLevel);
this.minimumLogLevel = this.getRef(MinimumLogLevel);
this.currentStackFrame = context.mapUnsafe.get(CurrentStackFrame.key);
this.maxOpsBeforeYield = this.getRef(Scheduler.MaxOpsBeforeYield);
this.currentPreventYield = this.getRef(Scheduler.PreventSchedulerYield);
this.runtimeMetrics = context.mapUnsafe.get(InternalMetric.FiberRuntimeMetricsKey);
const currentTracer = context.mapUnsafe.get(Tracer.TracerKey);
this.currentTracerContext = currentTracer ? currentTracer["context"] : undefined;
}
get currentSpanLocal() {
return this.currentSpan?._tag === "Span" ? this.currentSpan : undefined;
}
}
const fiberMiddleware = {
interruptChildren: undefined
};
const fiberStackAnnotations = fiber => {
if (!fiber.currentStackFrame) return undefined;
const annotations = new Map();
annotations.set(CauseStackTrace.key, fiber.currentStackFrame);
return Context.makeUnsafe(annotations);
};
const fiberInterruptChildren = fiber => {
if (fiber._children === undefined || fiber._children.size === 0) {
return undefined;
}
return fiberInterruptAll(fiber._children);
};
/** @internal */
export const fiberAwait = self => {
const impl = self;
if (impl._exit) return succeed(impl._exit);
return callback(resume => {
if (impl._exit) return resume(succeed(impl._exit));
return sync(self.addObserver(exit => resume(succeed(exit))));
});
};
/** @internal */
export const fiberAwaitAll = self => callback(resume => {
const iter = self[Symbol.iterator]();
const exits = [];
let cancel = undefined;
function loop() {
let result = iter.next();
while (!result.done) {
if (result.value._exit) {
exits.push(result.value._exit);
result = iter.next();
continue;
}
cancel = result.value.addObserver(exit => {
exits.push(exit);
loop();
});
return;
}
resume(succeed(exits));
}
loop();
return sync(() => cancel?.());
});
/** @internal */
export const fiberJoin = self => {
const impl = self;
if (impl._exit) return impl._exit;
return callback(resume => {
if (impl._exit) return resume(impl._exit);
return sync(self.addObserver(resume));
});
};
/** @internal */
export const fiberJoinAll = self => callback(resume => {
const fibers = Array.from(self);
if (fibers.length === 0) return resume(succeed(Arr.empty()));
const out = new Array(fibers.length);
const cancels = Arr.empty();
let done = 0;
let failed = false;
for (let i = 0; i < fibers.length; i++) {
if (failed) break;
cancels.push(fibers[i].addObserver(exit => {
done++;
if (exit._tag === "Failure") {
failed = true;
cancels.forEach(cancel => cancel());
return resume(exit);
}
out[i] = exit.value;
if (done === fibers.length) {
resume(succeed(out));
}
}));
}
});
/** @internal */
export const fiberInterrupt = self => withFiber(fiber => fiberInterruptAs(self, fiber.id));
/** @internal */
export const fiberInterruptAs = /*#__PURE__*/dual(args => hasProperty(args[0], FiberTypeId), (self, fiberId, annotations) => withFiber(parent => {
let ann = fiberStackAnnotations(parent);
ann = ann && annotations ? Context.merge(ann, annotations) : ann ?? annotations;
self.interruptUnsafe(fiberId, ann);
return asVoid(fiberAwait(self));
}));
/** @internal */
export const fiberInterruptAll = fibers => withFiber(parent => {
const annotations = fiberStackAnnotations(parent);
for (const fiber of fibers) {
fiber.interruptUnsafe(parent.id, annotations);
}
return asVoid(fiberAwaitAll(fibers));
});
/** @internal */
export const fiberInterruptAllAs = /*#__PURE__*/dual(2, (fibers, fiberId) => withFiber(parent => {
const annotations = fiberStackAnnotations(parent);
for (const fiber of fibers) fiber.interruptUnsafe(fiberId, annotations);
return asVoid(fiberAwaitAll(fibers));
}));
/** @internal */
export const succeed = exitSucceed;
/** @internal */
export const failCause = exitFailCause;
/** @internal */
export const fail = exitFail;
/** @internal */
export const sync = /*#__PURE__*/makePrimitive({
op: "Sync",
[evaluate](fiber) {
const value = this[args]();
const cont = fiber.getCont(contA);
return cont ? cont[contA](value, fiber) : fiber.yieldWith(exitSucceed(value));
}
});
/** @internal */
export const suspend = /*#__PURE__*/makePrimitive({
op: "Suspend",
[evaluate](_fiber) {
return this[args]();
}
});
/** @internal */
export const fromOption = /*#__PURE__*/Option.match({
onNone: () => fail(new NoSuchElementError("Effect.fromOption: Option.none")),
onSome: succeed
});
/** @internal */
export const fromResult = /*#__PURE__*/Result.match({
onFailure: fail,
onSuccess: succeed
});
/** @internal */
export const fromNullishOr = value => value == null ? fail(new NoSuchElementError()) : succeed(value);
/** @internal */
export const yieldNowWith = /*#__PURE__*/makePrimitive({
op: "Yield",
[evaluate](fiber) {
let resumed = false;
fiber.currentDispatcher.scheduleTask(() => {
if (resumed) return;
fiber.evaluate(exitVoid);
}, this[args] ?? 0);
return fiber.yieldWith(() => {
resumed = true;
});
}
});
/** @internal */
export const yieldNow = /*#__PURE__*/yieldNowWith(0);
/** @internal */
export const succeedSome = a => succeed(Option.some(a));
/** @internal */
export const succeedNone = /*#__PURE__*/succeed(/*#__PURE__*/Option.none());
/** @internal */
export const failCauseSync = evaluate => suspend(() => failCause(internalCall(evaluate)));
/** @internal */
export const die = defect => exitDie(defect);
/** @internal */
export const failSync = error => suspend(() => fail(internalCall(error)));
/** @internal */
const void_ = /*#__PURE__*/succeed(void 0);
/** @internal */
export { void_ as void };
/** @internal */
const try_ = options => suspend(() => {
try {
return succeed(internalCall(options.try));
} catch (err) {
return fail(internalCall(() => options.catch(err)));
}
});
/** @internal */
export { try_ as try };
/** @internal */
export const promise = evaluate => callbackOptions(function (resume, signal) {
internalCall(() => evaluate(signal)).then(a => resume(succeed(a)), e => resume(die(e)));
}, evaluate.length !== 0);
/** @internal */
export const tryPromise = options => {
const f = typeof options === "function" ? options : options.try;
const catcher = typeof options === "function" ? cause => new UnknownError(cause, "An error occurred in Effect.tryPromise") : options.catch;
return callbackOptions(function (resume, signal) {
try {
internalCall(() => f(signal)).then(a => resume(succeed(a)), e => resume(fail(internalCall(() => catcher(e)))));
} catch (err) {
resume(fail(internalCall(() => catcher(err))));
}
}, eval.length !== 0);
};
/** @internal */
export const withFiberId = f => withFiber(fiber => f(fiber.id));
/** @internal */
export const fiber = /*#__PURE__*/withFiber(succeed);
/** @internal */
export const fiberId = /*#__PURE__*/withFiberId(succeed);
const callbackOptions = /*#__PURE__*/makePrimitive({
op: "Async",
single: false,
[evaluate](fiber) {
const register = internalCall(() => this[args][0].bind(fiber.currentScheduler));
let resumed = false;
let yielded = false;
const controller = this[args][1] ? new AbortController() : undefined;
const onCancel = register(effect => {
if (resumed) return;
resumed = true;
if (yielded) {
fiber.evaluate(effect);
} else {
yielded = effect;
}
}, controller?.signal);
if (yielded !== false) return yielded;
yielded = true;
fiber._yielded = () => {
resumed = true;
};
if (controller === undefined && onCancel === undefined) {
return Yield;
}
fiber._stack.push(asyncFinalizer(() => {
resumed = true;
controller?.abort();
return onCancel ?? exitVoid;
}));
return Yield;
}
});
const asyncFinalizer = /*#__PURE__*/makePrimitive({
op: "AsyncFinalizer",
[contAll](fiber) {
if (fiber.interruptible) {
fiber.interruptible = false;
fiber._stack.push(setInterruptibleTrue);
}
},
[contE](cause, _fiber) {
return hasInterrupts(cause) ? flatMap(this[args](), () => failCause(cause)) : failCause(cause);
}
});
/** @internal */
export const callback = register => callbackOptions(register, register.length >= 2);
/** @internal */
export const never = /*#__PURE__*/callback(constVoid);
/** @internal */
export const gen = (...args) => suspend(() => fromIteratorUnsafe(args.length === 1 ? args[0]() : args[1].call(args[0].self)));
/** @internal */
export const fnUntraced = (body, ...pipeables) => {
const fn = pipeables.length === 0 ? function () {
return suspend(() => fromIteratorUnsafe(body.apply(this, arguments)));
} : function () {
let effect = suspend(() => fromIteratorUnsafe(body.apply(this, arguments)));
for (let i = 0; i < pipeables.length; i++) {
effect = pipeables[i](effect, ...arguments);
}
return effect;
};
return defineFunctionLength(body.length, fn);
};
const defineFunctionLength = (length, fn) => Object.defineProperty(fn, "length", {
value: length,
configurable: true
});
const fnStackCleaner = /*#__PURE__*/makeStackCleaner(2);
/** @internal */
export const fn = function () {
const nameFirst = typeof arguments[0] === "string";
const name = nameFirst ? arguments[0] : "Effect.fn";
const spanOptions = nameFirst ? arguments[1] : undefined;
const prevLimit = globalThis.Error.stackTraceLimit;
globalThis.Error.stackTraceLimit = 2;
const defError = new globalThis.Error();
globalThis.Error.stackTraceLimit = prevLimit;
if (nameFirst) {
return (body, ...pipeables) => makeFn(name, body, defError, pipeables, nameFirst, spanOptions);
}
return makeFn(name, arguments[0], defError, Array.prototype.slice.call(arguments, 1), nameFirst, spanOptions);
};
const makeFn = (name, bodyOrOptions, defError, pipeables, addSpan, spanOptions) => {
const body = typeof bodyOrOptions === "function" ? bodyOrOptions : pipeables.pop().bind(bodyOrOptions.self);
return defineFunctionLength(body.length, function (...args) {
let result = suspend(() => {
const iter = body.apply(this, arguments);
return isEffect(iter) ? iter : fromIteratorUnsafe(iter);
});
for (let i = 0; i < pipeables.length; i++) {
result = pipeables[i](result, ...args);
}
if (!isEffect(result)) {
return result;
}
const prevLimit = globalThis.Error.stackTraceLimit;
globalThis.Error.stackTraceLimit = 2;
const callError = new globalThis.Error();
globalThis.Error.stackTraceLimit = prevLimit;
return updateService(addSpan ? useSpan(name, spanOptions, span => provideParentSpan(result, span)) : result, CurrentStackFrame, prev => ({
name,
stack: fnStackCleaner(() => callError.stack),
parent: {
name: `${name} (definition)`,
stack: fnStackCleaner(() => defError.stack),
parent: prev
}
}));
});
};
/** @internal */
export const fnUntracedEager = (body, ...pipeables) => defineFunctionLength(body.length, pipeables.length === 0 ? function () {
return fromIteratorEagerUnsafe(() => body.apply(this, arguments));
} : function () {
let effect = fromIteratorEagerUnsafe(() => body.apply(this, arguments));
for (const pipeable of pipeables) {
effect = pipeable(effect);
}
return effect;
});
const fromIteratorEagerUnsafe = evaluate => {
try {
const iterator = evaluate();
let value = undefined;
// Try to resolve synchronously in a loop
while (true) {
const state = iterator.next(value);
if (state.done) {
return succeed(state.value);
}
const primitive = state.value;
if (primitive && primitive._tag === "Success") {
value = primitive.value;
continue;
} else if (primitive && primitive._tag === "Failure") {
return state.value;
} else {
let isFirstExecution = true;
return suspend(() => {
if (isFirstExecution) {
isFirstExecution = false;
return flatMap(state.value, value => fromIteratorUnsafe(iterator, value));
} else {
return suspend(() => fromIteratorUnsafe(evaluate()));
}
});
}
}
} catch (error) {
return die(error);
}
};
const fromIteratorUnsafe = /*#__PURE__*/makePrimitive({
op: "Iterator",
single: false,
[contA](value, fiber) {
const iter = this[args][0];
while (true) {
const state = iter.next(value);
if (state.done) return succeed(state.value);
if (!effectIsExit(state.value)) {
fiber._stack.push(this);
return state.value;
} else if (state.value._tag === "Failure") {
return state.value;
}
value = state.value.value;
}
},
[evaluate](fiber) {
return this[contA](this[args][1], fiber);
}
});
// ----------------------------------------------------------------------------
// mapping & sequencing
// ----------------------------------------------------------------------------
/** @internal */
export const as = /*#__PURE__*/dual(2, (self, value) => {
const b = succeed(value);
return flatMap(self, _ => b);
});
/** @internal */
export const asSome = self => map(self, Option.some);
/** @internal */
export const flip = self => matchEffect(self, {
onFailure: succeed,
onSuccess: fail
});
/** @internal */
export const andThen = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => isEffect(f) ? f : internalCall(() => f(a))));
/** @internal */
export const tap = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => as(isEffect(f) ? f : internalCall(() => f(a)), a)));
/** @internal */
export const asVoid = self => flatMap(self, _ => exitVoid);
/** @internal */
export const sandbox = self => catchCause(self, fail);
/** @internal */
export const raceAll = (all, options) => withFiber(parent => callback(resume => {
const effects = Arr.fromIterable(all);
const len = effects.length;
let doneCount = 0;
let done = false;
const fibers = new Set();
const failures = [];
const onExit = (exit, fiber, i) => {
doneCount++;
if (exit._tag === "Failure") {
failures.push(...exit.cause.reasons);
if (doneCount >= len) {
resume(failCause(causeFromReasons(failures)));
}
return;
}
const isWinner = !done;
done = true;
resume(fibers.size === 0 ? exit : flatMap(uninterruptible(fiberInterruptAll(fibers)), () => exit));
if (isWinner && options?.onWinner) {
options.onWinner({
fiber,
index: i,
parentFiber: parent
});
}
};
for (let i = 0; i < len; i++) {
const fiber = forkUnsafe(parent, effects[i], true, true, false);
fibers.add(fiber);
fiber.addObserver(exit => {
fibers.delete(fiber);
onExit(exit, fiber, i);
});
if (done) break;
}
return fiberInterruptAll(fibers);
}));
/** @internal */
export const raceAllFirst = (all, options) => withFiber(parent => callback(resume => {
let done = false;
const fibers = new Set();
const onExit = exit => {
done = true;
resume(fibers.size === 0 ? exit : flatMap(uninterruptible(fiberInterruptAll(fibers)), () => exit));
};
let i = 0;
for (const effect of all) {
if (done) break;
const index = i++;
const fiber = forkUnsafe(parent, effect, true, true, false);
fibers.add(fiber);
fiber.addObserver(exit => {
fibers.delete(fiber);
const isWinner = !done;
onExit(exit);
if (isWinner && options?.onWinner) {
options.onWinner({
fiber,
index,
parentFiber: parent
});
}
});
}
return fiberInterruptAll(fibers);
}));
/** @internal */
export const race = /*#__PURE__*/dual(args => isEffect(args[1]), (self, that, options) => raceAll([self, that], options));
/** @internal */
export const raceFirst = /*#__PURE__*/dual(args => isEffect(args[1]), (self, that, options) => raceAllFirst([self, that], options));
/** @internal */
export const flatMap = /*#__PURE__*/dual(2, (self, f) => {
const onSuccess = Object.create(OnSuccessProto);
onSuccess[args] = self;
onSuccess[contA] = f.length !== 1 ? a => f(a) : f;
return onSuccess;
});
const OnSuccessProto = /*#__PURE__*/makePrimitiveProto({
op: "OnSuccess",
[evaluate](fiber) {
fiber._stack.push(this);
return this[args];
}
});
/** @internal */
export const matchCauseEffectEager = /*#__PURE__*/dual(2, (self, options) => {
if (effectIsExit(self)) {
return self._tag === "Success" ? options.onSuccess(self.value) : options.onFailure(self.cause);
}
return matchCauseEffect(self, options);
});
/** @internal */
export const effectIsExit = effect => ExitTypeId in effect;
/** @internal */
export const flatMapEager = /*#__PURE__*/dual(2, (self, f) => {
if (effectIsExit(self)) {
return self._tag === "Success" ? f(self.value) : self;
}
return flatMap(self, f);
});
// ----------------------------------------------------------------------------
// mapping & sequencing
// ----------------------------------------------------------------------------
/** @internal */
export const flatten = self => flatMap(self, identity);
/** @internal */
export const map = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => succeed(internalCall(() => f(a)))));
/** @internal */
export const mapEager = /*#__PURE__*/dual(2, (self, f) => effectIsExit(self) ? exitMap(self, f) : map(self, f));
/** @internal */
export const mapErrorEager = /*#__PURE__*/dual(2, (self, f) => effectIsExit(self) ? exitMapError(self, f) : mapError(self, f));
/** @internal */
export const mapBothEager = /*#__PURE__*/dual(2, (self, options) => effectIsExit(self) ? exitMapBoth(self, options) : mapBoth(self, options));
/** @internal */
export const catchEager = /*#__PURE__*/dual(2, (self, f) => {
if (effectIsExit(self)) {
if (self._tag === "Success") return self;
const error = findError(self.cause);
if (Result.isFailure(error)) return self;
return f(error.success);
}
return catch_(self, f);
});
// ----------------------------------------------------------------------------
// Exit
// ----------------------------------------------------------------------------
/** @internal */
export const exitInterrupt = fiberId => exitFailCause(causeInterrupt(fiberId));
/** @internal */
export const exitIsSuccess = self => self._tag === "Success";
/** @internal */
export const exitFilterSuccess = self => self._tag === "Success" ? Result.succeed(self) : Result.fail(self);
/** @internal */
export const exitFilterValue = self => self._tag === "Success" ? Result.succeed(self.value) : Result.fail(self);
/** @internal */
export const exitIsFailure = self => self._tag === "Failure";
/** @internal */
export const exitFilterFailure = self => self._tag === "Failure" ? Result.succeed(self) : Result.fail(self);
/** @internal */
export const exitFilterCause = self => self._tag === "Failure" ? Result.succeed(self.cause) : Result.fail(self);
/** @internal */
export const exitFindError = /*#__PURE__*/Filter.composePassthrough(exitFilterCause, findError);
/** @internal */
export const exitFindDefect = /*#__PURE__*/Filter.composePassthrough(exitFilterCause, findDefect);
/** @internal */
export const exitHasInterrupts = self => self._tag === "Failure" && hasInterrupts(self.cause);
/** @internal */
export const exitHasDies = self => self._tag === "Failure" && hasDies(self.cause);
/** @internal */
export const exitHasFails = self => self._tag === "Failure" && hasFails(self.cause);
/** @internal */
export const exitVoid = /*#__PURE__*/exitSucceed(void 0);
/** @internal */
export const exitMap = /*#__PURE__*/dual(2, (self, f) => self._tag === "Success" ? exitSucceed(f(self.value)) : self);
/** @internal */
export const exitMapError = /*#__PURE__*/dual(2, (self, f) => {
if (self._tag === "Success") return self;
const error = findError(self.cause);
if (Result.isFailure(error)) return self;
return exitFail(f(error.success));
});
/** @internal */
export const exitMapBoth = /*#__PURE__*/dual(2, (self, options) => {
if (self._tag === "Success") return exitSucceed(options.onSuccess(self.value));
const error = findError(self.cause);
if (Result.isFailure(error)) return self;
return exitFail(options.onFailure(error.success));
});
/** @internal */
export const exitAs = /*#__PURE__*/dual(2, (self, b) => exitIsSuccess(self) ? exitSucceed(b) : self);
/** @internal */
export const exitZipRight = /*#__PURE__*/dual(2, (self, that) => exitIsSuccess(self) ? that : self);
/** @internal */
export const exitMatch = /*#__PURE__*/dual(2, (self, options) => exitIsSuccess(self) ? options.onSuccess(self.value) : options.onFailure(self.cause));
/** @internal */
export const exitAsVoid = /*#__PURE__*/exitAs(void 0);
/** @internal */
export const exitAsVoidAll = exits => {
const failures = [];
for (const exit of exits) {
if (exit._tag === "Failure") {
failures.push(...exit.cause.reasons);
}
}
return failures.length === 0 ? exitVoid : exitFailCause(causeFromReasons(failures));
};
/** @internal */
export const exitGetSuccess = self => exitIsSuccess(self) ? Option.some(self.value) : Option.none();
/** @internal */
export const exitGetCause = self => exitIsFailure(self) ? Option.some(self.cause) : Option.none();
/** @internal */
export const exitFindErrorOption = self => {
const error = exitFindError(self);
return Result.isFailure(error) ? Option.none() : Option.some(error.success);
};
// ----------------------------------------------------------------------------
// environment
// ----------------------------------------------------------------------------
/** @internal */
export const service = service => service;
/** @internal */
export const serviceOption = service => withFiber(fiber => succeed(Context.getOption(fiber.context, service)));
/** @internal */
export const serviceOptional = service => withFiber(fiber => fiber.context.mapUnsafe.has(service.key) ? succeed(Context.getUnsafe(fiber.context, service)) : fail(new NoSuchElementError()));
/** @internal */
export const updateContext = /*#__PURE__*/dual(2, (self, f) => withFiber(fiber => {
const prevContext = fiber.context;
const nextContext = f(prevContext);
if (prevContext === nextContext) return self;
fiber.setContext(nextContext);
return onExitPrimitive(self, () => {
fiber.setContext(prevContext);
return undefined;
});
}));
/** @internal */
export const updateService = /*#__PURE__*/dual(3, (self, service, f) => updateContext(self, s => {
const prev = Context.getUnsafe(s, service);
const next = f(prev);
if (prev === next) return s;
return Context.add(s, service, next);
}));
/** @internal */
export const context = () => getContext;
const getContext = /*#__PURE__*/withFiber(fiber => succeed(fiber.context));
/** @internal */
export const contextWith = f => withFiber(fiber => f(fiber.context));
/** @internal */
export const provideContext = /*#__PURE__*/dual(2, (self, context) => {
if (effectIsExit(self)) return self;
return updateContext(self, Context.merge(context));
});
/** @internal */
export const provideService = function () {
if (arguments.length === 1) {
return dual(2, (self, impl) => provideServiceImpl(self, arguments[0], impl));
}
return dual(3, (self, service, impl) => provideServiceImpl(self, service, impl)).apply(this, arguments);
};
const provideServiceImpl = (self, service, implementation) => updateContext(self, s => {
const prev = s.mapUnsafe.get(service.key);
if (prev === implementation) return s;
return Context.add(s, service, implementation);
});
/** @internal */
export const provideServiceEffect = /*#__PURE__*/dual(3, (self, service, acquire) => flatMap(acquire, implementation => provideService(self, service, implementation)));
/** @internal */
export const withConcurrency = /*#__PURE__*/provideService(CurrentConcurrency);
// ----------------------------------------------------------------------------
// zipping
// ----------------------------------------------------------------------------
/** @internal */
export const zip = /*#__PURE__*/dual(args => isEffect(args[1]), (self, that, options) => zipWith(self, that, (a, a2) => [a, a2], options));
/** @internal */
export const zipWith = /*#__PURE__*/dual(args => isEffect(args[1]), (self, that, f, options) => options?.concurrent
// Use `all` exclusively for concurrent cases, as it introduces additional overhead due to the management of concurrency
? map(all([self, that], {
concurrency: 2
}), ([a, a2]) => internalCall(() => f(a, a2))) : flatMap(self, a => map(that, a2 => internalCall(() => f(a, a2)))));
// ----------------------------------------------------------------------------
// filtering & conditionals
// ----------------------------------------------------------------------------
/* @internal */
export const filterOrFail = /*#__PURE__*/dual(args => isEffect(args[0]), (self, predicate, orFailWith) => filterOrElse(self, predicate, orFailWith ? a => fail(orFailWith(a)) : () => fail(new NoSuchElementError())));
/** @internal */
export const when = /*#__PURE__*/dual(2, (self, condition) => flatMap(condition, pass => pass ? asSome(self) : succeedNone));
// ----------------------------------------------------------------------------
// repetition
// ----------------------------------------------------------------------------
/** @internal */
export const replicate = /*#__PURE__*/dual(2, (self, n) => Array.from({
length: n
}, () => self));
/** @internal */
export const replicateEffect = /*#__PURE__*/dual(args => isEffect(args[0]), (self, n, options) => all(replicate(self, n), options));
/** @internal */
export const forever = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => whileLoop({
while: constTrue,
body: constant(options?.disableYield ? self : flatMap(self, _ => yieldNow)),
step: constVoid
}));
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
/** @internal */
export const catchCause = /*#__PURE__*/dual(2, (self, f) => {
const onFailure = Object.create(OnFailureProto);
onFailure[args] = self;
onFailure[contE] = f.length !== 1 ? cause => f(cause) : f;
return onFailure;
});
const OnFailureProto = /*#__PURE__*/makePrimitiveProto({
op: "OnFailure",
[evaluate](fiber) {
fiber._stack.push(this);
return this[args];
}
});
/** @internal */
export const catchCauseIf = /*#__PURE__*/dual(3, (self, predicate, f) => catchCause(self, cause => {
if (!predicate(cause)) {
return failCause(cause);
}
return internalCall(() => f(cause));
}));
/** @internal */
export const catchCauseFilter = /*#__PURE__*/dual(3, (self, filter, f) => catchCause(self, cause => {
const eb = filter(cause);
return Result.isFailure(eb) ? failCause(eb.failure) : internalCall(() => f(eb.success, cause));
}));
/** @internal */
export const catch_ = /*#__PURE__*/dual(2, (self, f) => catchCauseFilter(self, findError, e => f(e)));
/** @internal */
export const catchNoSuchElement = self => matchEffect(self, {
onFailure: error => isNoSuchElementError(error) ? succeedNone : fail(error),
onSuccess: succeedSome
});
/** @internal */
export const catchDefect = /*#__PURE__*/dual(2, (self, f) => catchCauseFilter(self, findDefect, f));
/** @internal */
export const tapCause = /*#__PURE__*/dual(2, (self, f) => catchCause(self, cause => andThen(internalCall(() => f(cause)), failCause(cause))));
/** @internal */
export const tapCauseIf = /*#__PURE__*/dual(3, (self, predicate, f) => catchCauseIf(self, predicate, cause => andThen(internalCall(() => f(cause)), failCause(cause))));
/** @internal */
export const tapCauseFilter = /*#__PURE__*/dual(3, (self, filter, f) => catchCause(self, cause => {
const result = filter(cause);
if (Result.isFailure(result)) {
return failCause(cause);
}
return andThen(internalCall(() => f(result.success, cause)), failCause(cause));
}));
/** @internal */
export const tapError = /*#__PURE__*/dual(2, (self, f) => tapCauseFilter(self, findError, e => f(e)));
/** @internal */
export const tapErrorTag = /*#__PURE__*/dual(3, (self, k, f) => {
const predicate = Array.isArray(k) ? e => hasProperty(e, "_tag") && k.includes(e._tag) : isTagged(k);
return tapError(self, error => predicate(error) ? f(error) : void_);
});
/** @internal */
export const tapDefect = /*#__PURE__*/dual(2, (self, f) => tapCauseFilter(self, findDefect, _ => f(_)));
/** @internal */
export const catchIf = /*#__PURE__*/dual(args => isEffect(args[0]), (self, predicate, f, orElse) => catchCause(self, cause => {
const error = findError(cause);
if (Result.isFailure(error)) return failCause(error.failure);
if (!predicate(error.success)) {
return orElse ? internalCall(() => orElse(error.success)) : failCause(cause);
}
return internalCall(() => f(error.success));
}));
/** @internal */
export const catchFilter = /*#__PURE__*/dual(args => isEffect(args[0]), (self, filter, f, orElse) => catchCause(self, cause => {
const error = findError(cause);
if (Result.isFailure(error)) return failCause(error.failure);
const result = filter(error.success);
if (Result.isFailure(result)) {
return orElse ? internalCall(() => orElse(result.failure)) : failCause(cause);
}
return internalCall(() => f(result.success));
}));
/** @internal */
export const catchTag = /*#__PURE__*/dual(args => isEffect(args[0]), (self, k, f, orElse) => {
const pred = Array.isArray(k) ? e => hasProperty(e, "_tag") && k.includes(e._tag) : isTagged(k);
return catchIf(self, pred, f, orElse);
});
/** @internal */
export const catchTags = /*#__PURE__*/dual(args => isEffect(args[0]), (self, cases, orElse) => {
let keys;
return catchFilter(self, e => {
keys ??= Object.keys(cases);
return hasProperty(e, "_tag") && isString(e["_tag"]) && keys.includes(e["_tag"]) ? Result.succeed(e) : Result.fail(e);
}, e => internalCall(() => cases[e["_tag"]](e)), orElse);
});
/** @internal */
export const catchReason = /*#__PURE__*/dual(args => isEffect(args[0]), (self, errorTag, reasonTag, f, orElse) => catchIf(self, e => isTagged(e, errorTag) && hasProperty(e, "reason"), e => {
const reason = e.reason;
if (isTagged(reason, reasonTag)) return f(reason, e);
return orElse ? internalCall(() => orElse(reason, e)) : fail(e);
}));
/** @internal */
export const catchReasons = /*#__PURE__*/dual(args => isEffect(args[0]), (self, errorTag, cases, orElse) => {
let keys;
return catchIf(self, e => isTagged(e, errorTag) && hasProperty(e, "reason") && hasProperty(e.reason, "_tag") && isString(e.reason._tag), e => {
const reason = e.reason;
keys ??= Object.keys(cases);
if (keys.includes(reason._tag)) {
return internalCall(() => cases[reason._tag](reason, e));
}
return orElse ? internalCall(() => orElse(reason, e)) : fail(e);
});
});
/** @internal */
export const unwrapReason = /*#__PURE__*/dual(2, (self, errorTag) => catchFilter(self, e => {
if (isTagged(e, errorTag) && hasProperty(e, "reason")) {
return Result.succeed(e.reason);
}
return Result.fail(e);
}, fail));
/** @internal */
export const mapErrorCause = /*#__PURE__*/dual(2, (self, f) => catchCause(self, cause => failCauseSync(() => f(cause))));
/** @internal */
export const mapError = /*#__PURE__*/dual(2, (self, f) => catch_(self, error => failSync(() => f(error))));
/* @internal */
export const mapBoth = /*#__PURE__*/dual(2, (self, options) => matchEffect(self, {
onFailure: e => failSync(() => options.onFailure(e)),
onSuccess: a => sync(() => options.onSuccess(a))
}));
/** @internal */
export const orDie = self => catch_(self, die);
/** @internal */
export const orElseSucceed = /*#__PURE__*/dual(2, (self, f) => catch_(self, _ => sync(f)));
/** @internal */
export const firstSuccessOf = effects => suspend(() => {
const iterator = effects[Symbol.iterator]();
let state = iterator.next();
if (state.done) {
return die(new Error("Received an empty collection of effects"));
}
function loop(current) {
const next = iterator.next();
if (next.done) return current.value;
return catch_(current.value, _ => loop(next));
}
return loop(state);
});
/** @internal */
export const eventually = self => catch_(self, _ => flatMap(yieldNow, () => eventually(self)));
/** @internal */
export const ignore = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => {
if (!options?.log) {
return matchEffect(self, {
onFailure: _ => void_,
onSuccess: _ => void_
});
}
const logEffect = logWithLevel(options.log === true ? undefined : options.log);
return matchCauseEffect(self, {
onFailure(cause) {
const failure = findFail(cause);
return Result.isFailure(failure) ? failCause(failure.failure) : options.message === undefined ? logEffect(cause) : logEffect(options.message, cause);
},
onSuccess: _ => void_
});
});
/** @internal */
export const ignoreCause = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => {
if (!options?.log) {
return matchCauseEffect(self, {
onFailure: _ => void_,
onSuccess: _ => void_
});
}
const logEffect = logWithLevel(options.log === true ? undefined : options.log);
return matchCauseEffect(self, {
onFailure: cause => options.message === undefined ? logEffect(cause) : logEffect(options.message, cause),
onSuccess: _ => void_
});
});
/** @internal */
export const option = self => match(self, {
onFailure: Option.none,
onSuccess: Option.some
});
/** @internal */
export const result = self => matchEager(self, {
onFailure: Result.fail,
onSuccess: Result.succeed
});
// ----------------------------------------------------------------------------
// pattern matching
// ----------------------------------------------------------------------------
/** @internal */
export const matchCauseEffect = /*#__PURE__*/dual(2, (self, options) => {
const primitive = Object.create(OnSuccessAndFailureProto);
primitive[args] = self;
primitive[contA] = options.onSuccess.length !== 1 ? a => options.onSuccess(a) : options.onSuccess;
primitive[contE] = options.onFailure.length !== 1 ? cause => options.onFailure(cause) : options.onFailure;
return primitive;
});
const OnSuccessAndFailureProto = /*#__PURE__*/makePrimitiveProto({
op: "OnSuccessAndFailure",
[evaluate](fiber) {
fiber._stack.push(this);
return this[args];
}
});
/** @internal */
export const matchCause = /*#__PURE__*/dual(2, (self, options) => matchCauseEffect(self, {
onFailure: cause => sync(() => options.onFailure(cause)),
onSuccess: value => sync(() => options.onSuccess(value))
}));
/** @internal */
export const matchEffect = /*#__PURE__*/dual(2, (self, options) => matchCauseEffect(self, {
onFailure: cause => {
const fail = cause.reasons.find(isFailReason);
return fail ? internalCall(() => options.onFailure(fail.error)) : failCause(cause);
},
onSuccess: options.onSuccess
}));
/** @internal */
export const match = /*#__PURE__*/dual(2, (self, options) => matchEffect(self, {
onFailure: error => sync(() => options.onFailure(error)),
onSuccess: value => sync(() => options.onSuccess(value))
}));
/** @internal */
export const matchEager = /*#__PURE__*/dual(2, (self, options) => {
if (effectIsExit(self)) {
if (self._tag === "Success") return exitSucceed(options.onSuccess(self.value));
const error = findError(self.cause);
if (Result.isFailure(error)) return self;
return exitSucceed(options.onFailure(error.success));
}
return match(self, options);
});
/** @internal */
export const matchCauseEager = /*#__PURE__*/dual(2, (self, options) => {
if (effectIsExit(self)) {
if (self._tag === "Success") return exitSucceed(options.onSuccess(self.value));
return exitSucceed(options.onFailure(self.cause));
}
return matchCause(self, options);
});
/** @internal */
export const exit = self => effectIsExit(self) ? exitSucceed(self) : exitPrimitive(self);
const exitPrimitive = /*#__PURE__*/makePrimitive({
op: "Exit",
[evaluate](fiber) {
fiber._stack.push(this);
return this[args];
},
[contA](value, _, exit) {
return succeed(exit ?? exitSucceed(value));
},
[contE](cause, _, exit) {
return succeed(exit ?? exitFailCause(cause));
}
});
// ----------------------------------------------------------------------------
// Condition checking
// ----------------------------------------------------------------------------
/** @internal */
export const isFailure = /*#__PURE__*/matchEager({
onFailure: () => true,
onSuccess: () => false
});
/** @internal */
export const isSuccess = /*#__PURE__*/matchEager({
onFailure: () => false,
onSuccess: () => true
});
// ----------------------------------------------------------------------------
// delays & timeouts
// ----------------------------------------------------------------------------
/** @internal */
export const delay = /*#__PURE__*/dual(2, (self, duration) => andThen(sleep(duration), self));
/** @internal */
export const timeoutOrElse = /*#__PURE__*/dual(2, (self, options) => raceFirst(self, flatMap(sleep(options.duration), options.orElse)));
/** @internal */
export const timeout = /*#__PURE__*/dual(2, (self, duration) => timeoutOrElse(self, {
duration,
orElse: () => fail(new TimeoutError())
}));
/** @internal */
export const timeoutOption = /*#__PURE__*/dual(2, (self, duration) => raceFirst(asSome(self), as(sleep(duration), Option.none())));
/** @internal */
export const timed = self => clockWith(clock => {
const start = clock.currentTimeNanosUnsafe();
return map(self, a => [Duration.nanos(clock.currentTimeNanosUnsafe() - start), a]);
});
// ----------------------------------------------------------------------------
// resources & finalization
// ----------------------------------------------------------------------------
/** @internal */
export const ScopeTypeId = "~effect/Scope";
/** @internal */
export const ScopeCloseableTypeId = "~effect/Scope/Closeable";
/** @internal */
export const scopeTag = /*#__PURE__*/Context.Service("effect/Scope");
/** @internal */
export const scopeClose = (self, exit_) => suspend(() => scopeCloseUnsafe(self, exit_) ?? void_);
/** @internal */
export const scopeCloseUnsafe = (self, exit_) => {
if (self.state._tag === "Closed") return;
const closed = {
_tag: "Closed",
exit: exit_
};
if (self.state._tag === "Empty") {
self.state = closed;
return;
}
const {
finalizers
} = self.state;
self.state = closed;
if (finalizers.size === 0) {
return;
} else if (finalizers.size === 1) {
return finalizers.values().next().value(exit_);
}
return scopeCloseFinalizers(self, finalizers, exit_);
};
const scopeCloseFinalizers = /*#__PURE__*/fnUntraced(function* (self, finalizers, exit_) {
let exits = [];
const fibers = [];
const arr = Array.from(finalizers.values());
const parent = getCurrentFiber();
for (let i = arr.length - 1; i >= 0; i--) {
const finalizer = arr[i];
if (self.strategy === "sequential") {
exits.push(yield* exit(finalizer(exit_)));
} else {
fibers.push(forkUnsafe(parent, finalizer(exit_), true, true, "inherit"));
}
}
if (fibers.length > 0) {
exits = yield* fiberAwaitAll(fibers);
}
return yield* exitAsVoidAll(exits);
});
/** @internal */
export const scopeFork = (scope, finalizerStrategy) => sync(() => scopeForkUnsafe(scope, finalizerStrategy));
/** @internal */
export const scopeForkUnsafe = (scope, finalizerStrategy) => {
const newScope = scopeMakeUnsafe(finalizerStrategy);
if (scope.state._tag === "Closed") {
newScope.state = scope.state;
return newScope;
}
const key = {};
scopeAddFinalizerUnsafe(scope, key, exit => scopeClose(newScope, exit));
scopeAddFinalizerUnsafe(newScope, key, _ => sync(() => scopeRemoveFinalizerUnsafe(scope, key)));
return newScope;
};
/** @internal */
export const scopeAddFinalizerExit = (scope, finalizer) => {
return suspend(() => {
if (scope.state._tag === "Closed") {
return finalizer(scope.state.exit);
}
scopeAddFinalizerUnsafe(scope, {}, finalizer);
return void_;
});
};
/** @internal */
export const scopeAddFinalizer = (scope, finalizer) => scopeAddFinalizerExit(scope, constant(finalizer));
/** @internal */
export const scopeAddFinalizerUnsafe = (scope, key, finalizer) => {
if (scope.state._tag === "Empty") {
scope.state = {
_tag: "Open",
finalizers: new Map([[key, finalizer]])
};
} else if (scope.state._tag === "Open") {
scope.state.finalizers.set(key, finalizer);
}
};
/** @internal */
export const scopeRemoveFinalizerUnsafe = (scope, key) => {
if (scope.state._tag === "Open") {
scope.state.finalizers.delete(key);
}
};
/** @internal */
export const scopeMakeUnsafe = (finalizerStrategy = "sequential") => ({
[ScopeCloseableTypeId]: ScopeCloseableTypeId,
[ScopeTypeId]: ScopeTypeId,
strategy: finalizerStrategy,
state: constScopeEmpty
});
const constScopeEmpty = {
_tag: "Empty"
};
/** @internal */
export const scopeMake = finalizerStrategy => sync(() => scopeMakeUnsafe(finalizerStrategy));
/** @internal */
export const scope = scopeTag;
/** @internal */
export const provideScope = /*#__PURE__*/provideService(scopeTag);
/** @internal */
export const scoped = self => withFiber(fiber => {
const prev = fiber.context;
const scope = scopeMakeUnsafe();
fiber.setContext(Context.add(fiber.context, scopeTag, scope));
return onExitPrimitive(self, exit => {
fiber.setContext(prev);
return scopeCloseUnsafe(scope, exit);
});
});
/** @internal */
export const scopeUse = /*#__PURE__*/dual(2, (self, scope) => onExit(provideScope(self, scope), exit => suspend(() => scopeCloseUnsafe(scope, exit) ?? void_)));
/** @internal */
export const scopedWith = f => suspend(() => {
const scope = scopeMakeUnsafe();
return onExit(f(scope), exit => suspend(() => scopeCloseUnsafe(scope, exit) ?? void_));
});
/** @internal */
export const acquireRelease = (acquire, release, options) => contextWith(context => uninterruptibleMask(restore => flatMap(scope, scope => tap(options?.interruptible ? restore(acquire) : acquire, a => scopeAddFinalizerExit(scope, exit => provideContext(release(a, exit), context))))));
/** @internal */
export const addFinalizer = finalizer => flatMap(scope, scope => contextWith(context => scopeAddFinalizerExit(scope, exit => provideContext(finalizer(exit), context))));
/** @internal */
export const onExitPrimitive = /*#__PURE__*/makePrimitive({
op: "OnExit",
single: false,
[evaluate](fiber) {
fiber._stack.push(this);
return this[args][0];
},
[contAll](fiber) {
if (fiber.interruptible && this[args][2] !== true) {
fiber._stack.push(setInterruptibleTrue);
fiber.interruptible = false;
}
},
[contA](value, _, exit) {
exit ??= exitSucceed(value);
const eff = this[args][1](exit);
return eff ? flatMap(eff, _ => exit) : exit;
},
[contE](cause, _, exit) {
exit ??= exitFailCause(cause);
const eff = this[args][1](exit);
return eff ? flatMap(eff, _ => exit) : exit;
}
});
/** @internal */
export const onExit = /*#__PURE__*/dual(2, onExitPrimitive);
/** @internal */
export const ensuring = /*#__PURE__*/dual(2, (self, finalizer) => onExit(self, _ => finalizer));
/** @internal */
export const onExitIf = /*#__PURE__*/dual(3, (self, predicate, f) => onExit(self, exit => {
if (!predicate(exit)) {
return void_;
}
return f(exit);
}));
/** @internal */
export const onExitFilter = /*#__PURE__*/dual(3, (self, filter, f) => onExit(self, exit => {
const b = filter(exit);
return Result.isFailure(b) ? void_ : f(b.success, exit);
}));
/** @internal */
export const onError = /*#__PURE__*/dual(2, (self, f) => onExitFilter(self, exitFilterCause, f));
/** @internal */
export const onErrorIf = /*#__PURE__*/dual(3, (self, predicate, f) => onExitIf(self, exit => {
if (exit._tag !== "Failure") {
return false;
}
return predicate(exit.cause);
}, exit => f(exit.cause)));
/** @internal */
export const onErrorFilter = /*#__PURE__*/dual(3, (self, filter, f) => onExit(self, exit => {
if (exit._tag !== "Failure") {
return void_;
}
const result = filter(exit.cause);
return Result.isFailure(result) ? void_ : f(result.success, exit.cause);
}));
/** @internal */
export const onInterrupt = /*#__PURE__*/dual(2, (self, finalizer) => onErrorFilter(causeFilterInterruptors, finalizer)(self));
/** @internal */
export const acquireUseRelease = (acquire, use, release) => uninterruptibleMask(restore => flatMap(acquire, a => onExitPrimitive(restore(use(a)), exit => release(a, exit), true)));
/** @internal */
export const acquireDisposable = acquire => acquireRelease(acquire, resource => hasProperty(resource, Symbol.asyncDispose) ? promise(() => resource[Symbol.asyncDispose]()) : sync(() => resource[Symbol.dispose]()));
// ----------------------------------------------------------------------------
// Caching
// ----------------------------------------------------------------------------
/** @internal */
export const cachedInvalidateWithTTL = /*#__PURE__*/dual(2, (self, ttl) => sync(() => {
const ttlMillis = Duration.toMillis(Duration.fromInputUnsafe(ttl));
const isFinite = Number.isFinite(ttlMillis);
const latch = makeLatchUnsafe(false);
let expiresAt = 0;
let running = false;
let exit;
const wait = flatMap(latch.await, () => exit);
return [withFiber(fiber => {
const clock = fiber.getRef(ClockRef);
const now = isFinite ? clock.currentTimeMillisUnsafe() : 0;
if (running || now < expiresAt) return exit ?? wait;
running = true;
latch.closeUnsafe();
exit = undefined;
return onExit(self, exit_ => sync(() => {
running = false;
expiresAt = clock.currentTimeMillisUnsafe() + ttlMillis;
exit = exit_;
latch.openUnsafe();
}));
}), sync(() => {
expiresAt = 0;
latch.closeUnsafe();
exit = undefined;
})];
}));
/** @internal */
export const cachedWithTTL = /*#__PURE__*/dual(2, (self, timeToLive) => map(cachedInvalidateWithTTL(self, timeToLive), tuple => tuple[0]));
/** @internal */
export const cached = self => cachedWithTTL(self, Duration.infinity);
// ----------------------------------------------------------------------------
// interruption
// ----------------------------------------------------------------------------
/** @internal */
export const interrupt = /*#__PURE__*/withFiber(fiber => failCause(causeInterrupt(fiber.id)));
/** @internal */
export const uninterruptible = self => withFiber(fiber => {
if (!fiber.interruptible) return self;
fiber.interruptible = false;
fiber._stack.push(setInterruptibleTrue);
return self;
});
const setInterruptible = /*#__PURE__*/makePrimitive({
op: "SetInterruptible",
[contAll](fiber) {
fiber.interruptible = this[args];
if (fiber._interruptedCause && fiber.interruptible) {
return () => failCause(fiber._interruptedCause);
}
}
});
const setInterruptibleTrue = /*#__PURE__*/setInterruptible(true);
const setInterruptibleFalse = /*#__PURE__*/setInterruptible(false);
/** @internal */
export const interruptible = self => withFiber(fiber => {
if (fiber.interruptible) return self;
fiber.interruptible = true;
fiber._stack.push(setInterruptibleFalse);
if (fiber._interruptedCause) return failCause(fiber._interruptedCause);
return self;
});
/** @internal */
export const uninterruptibleMask = f => withFiber(fiber => {
if (!fiber.interruptible) return f(identity);
fiber.interruptible = false;
fiber._stack.push(setInterruptibleTrue);
return f(interruptible);
});
/** @internal */
export const interruptibleMask = f => withFiber(fiber => {
if (fiber.interruptible) return f(identity);
fiber.interruptible = true;
fiber._stack.push(setInterruptibleFalse);
return f(uninterruptible);
});
/** @internal */
export const abortSignal = /*#__PURE__*/map(/*#__PURE__*/acquireRelease(/*#__PURE__*/sync(() => new AbortController()), controller => sync(() => controller.abort())), _ => _.signal);
// ========================================================================
// collecting & elements
// ========================================================================
/** @internal */
export const all = (arg, options) => {
if (isIterable(arg)) {
return options?.mode === "result" ? forEach(arg, result, options) : forEach(arg, identity, options);
} else if (options?.discard) {
return options.mode === "result" ? forEach(Object.values(arg), result, options) : forEach(Object.values(arg), identity, options);
}
return suspend(() => {
const out = {};
return as(forEach(Object.entries(arg), ([key, effect]) => map(options?.mode === "result" ? result(effect) : effect, value => {
out[key] = value;
}), {
discard: true,
concurrency: options?.concurrency
}), out);
});
};
/** @internal */
export const partition = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, f, options) => map(forEach(elements, (a, i) => result(f(a, i)), options), results => Arr.partition(results, identity)));
/** @internal */
export const validate = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, f, options) => flatMap(partition(elements, f, {
concurrency: options?.concurrency
}), ([excluded, satisfying]) => {
if (Arr.isArrayNonEmpty(excluded)) {
return fail(excluded);
}
return options?.discard ? void_ : succeed(satisfying);
}));
/** @internal */
export const findFirst = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, predicate) => suspend(() => {
const iterator = elements[Symbol.iterator]();
const next = iterator.next();
if (!next.done) {
return findFirstLoop(iterator, 0, predicate, next.value);
}
return succeed(Option.none());
}));
const findFirstLoop = (iterator, index, predicate, value) => flatMap(predicate(value, index), keep => {
if (keep) {
return succeed(Option.some(value));
}
const next = iterator.next();
if (!next.done) {
return findFirstLoop(iterator, index + 1, predicate, next.value);
}
return succeed(Option.none());
});
/** @internal */
export const findFirstFilter = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, filter) => suspend(() => {
const iterator = elements[Symbol.iterator]();
const next = iterator.next();
if (!next.done) {
return findFirstFilterLoop(iterator, 0, filter, next.value);
}
return succeed(Option.none());
}));
const findFirstFilterLoop = (iterator, index, filter, value) => flatMap(filter(value, index), result => {
if (Result.isSuccess(result)) {
return succeed(Option.some(result.success));
}
const next = iterator.next();
if (!next.done) {
return findFirstFilterLoop(iterator, index + 1, filter, next.value);
}
return succeed(Option.none());
});
/** @internal */
export const whileLoop = /*#__PURE__*/makePrimitive({
op: "While",
[contA](value, fiber) {
this[args].step(value);
if (this[args].while()) {
fiber._stack.push(this);
return this[args].body();
}
return exitVoid;
},
[evaluate](fiber) {
if (this[args].while()) {
fiber._stack.push(this);
return this[args].body();
}
return exitVoid;
}
});
/** @internal */
export const forEach = /*#__PURE__*/dual(args => typeof args[1] === "function", (iterable, f, options) => withFiber(parent => {
const concurrencyOption = options?.concurrency === "inherit" ? parent.getRef(CurrentConcurrency) : options?.concurrency ?? 1;
const concurrency = concurrencyOption === "unbounded" ? Number.POSITIVE_INFINITY : Math.max(1, concurrencyOption);
if (concurrency === 1) {
return forEachSequential(iterable, f, options);
}
const items = Arr.fromIterable(iterable);
let length = items.length;
if (length === 0) {
return options?.discard ? void_ : succeed([]);
}
const out = options?.discard ? undefined : new Array(length);
const eff = forEachConcurrent({
f,
out
}, items, {
concurrency
});
return eff ? as(eff, out) : succeed(out);
}));
const forEachSequential = (iterable, f, options) => suspend(() => {
const out = options?.discard ? undefined : [];
const iterator = iterable[Symbol.iterator]();
let state = iterator.next();
let index = 0;
return as(whileLoop({
while: () => !state.done,
body: () => f(state.value, index++),
step: b => {
if (out) out.push(b);
state = iterator.next();
}
}), out);
});
const iterateEagerImpl = options => {
const onItem = options.onItem;
const step = options.step;
return (state, items, opts) => {
let index = opts?.start ?? 0;
const end = opts?.end ?? items.length;
const concurrency = opts?.concurrency ?? 1;
let done = false;
let parentFiber;
let fibers;
let resume;
let interrupted = false;
let terminal;
let effect;
const go = () => {
let paused = false;
for (; !terminal && index < end; index++) {
const item = items[index];
const eff = effect ?? onItem(state, item, index);
// fast case (already an exit)
if (effectIsExit(eff)) {
terminal = step(state, item, eff, index);
if (terminal) break;
// Use flatMap for concurrency of 1
} else if (concurrency === 1) {
return flatMap(exit(eff), exit => {
terminal = step(state, item, exit, index);
index++;
return terminal ?? go() ?? void_;
});
// We have an effect, so enter "async" mode
} else if (!parentFiber) {
return callback(cb => {
parentFiber = getCurrentFiber();
effect = eff;
resume = cb;
const result = go();
if (result) return cb(result);
return suspend(() => {
terminal = exitVoid;
interrupted = true;
return fibers ? fiberInterruptAll(fibers) : void_;
});
});
// Fork the effect with concurrency > 1
} else {
// Clear the temporary effect from capturing the parentFiber
effect = undefined;
const fiber = forkUnsafe(parentFiber, eff, true, true, "inherit");
if (fiber._exit) {
terminal = step(state, item, fiber._exit, index);
if (terminal) break;
continue;
}
// Add the fiber to the Set
if (fibers) fibers.add(fiber);else fibers = new Set([fiber]);
const currentIndex = index;
fiber.addObserver(exit => {
fibers.delete(fiber);
if (terminal) {
if (!interrupted && exit._tag === "Failure") {
for (const reason of exit.cause.reasons) {
if (reason._tag === "Interrupt") continue;else if (terminal._tag === "Failure") {
;
terminal.cause.reasons.push(reason);
} else {
terminal = exitFailCause(causeFromReasons([reason]));
}
}
}
} else {
const result = step(state, item, exit, currentIndex);
if (result) {
terminal = result._tag === "Failure" ? exitFailCause(causeFromReasons(result.cause.reasons.slice())) : result;
go();
}
}
if (paused) {
const eff = go();
if (eff) resume(eff);
} else if (done && fibers.size === 0) {
resume(terminal ?? void_);
}
});
// Check if we have reached the concurrency limit
if (fibers.size < concurrency) continue;
paused = true;
index++;
return;
}
}
done = true;
if (terminal) {
if (fibers && fibers.size > 0) {
const annotations = fiberStackAnnotations(parentFiber);
fibers.forEach(f => f.interruptUnsafe(parentFiber.id, annotations));
return;
}
if (resume || terminal._tag === "Failure") {
return terminal;
}
} else if (resume) {
if (!fibers) {
return exitVoid;
} else if (fibers.size === 0) {
resume(void_);
}
}
};
return go();
};
};
/** @internal */
export const iterateEager = () => iterateEagerImpl;
const forEachConcurrent = /*#__PURE__*/iterateEagerImpl({
onItem(state, item, index) {
return state.f(item, index);
},
step(state, _, exit, index) {
if (exit._tag === "Failure") return exit;else if (state.out) {
state.out[index] = exit.value;
}
}
});
/* @internal */
export const filterOrElse = /*#__PURE__*/dual(3, (self, predicate, orElse) => flatMap(self, a => predicate(a) ? succeed(a) : orElse(a)));
/** @internal */
export const filterMapOrElse = /*#__PURE__*/dual(3, (self, filter, orElse) => flatMap(self, a => {
const result = filter(a);
return Result.isFailure(result) ? orElse(result.failure) : succeed(result.success);
}));
/* @internal */
export const filterMapOrFail = /*#__PURE__*/dual(args => isEffect(args[0]), (self, filter, orFailWith) => filterMapOrElse(self, filter, orFailWith ? x => fail(orFailWith(x)) : () => fail(new NoSuchElementError())));
/** @internal */
export const filter = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, predicate, options) => suspend(() => {
const out = [];
return as(forEach(elements, (a, i) => {
const result = predicate(a, i);
if (typeof result === "boolean") {
if (result) out.push(a);
return void_;
}
return map(result, keep => {
if (keep) {
out.push(a);
}
});
}, {
discard: true,
concurrency: options?.concurrency
}), out);
}));
/** @internal */
export const filterMap = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, filter) => suspend(() => {
const out = [];
for (const a of elements) {
const result = filter(a);
if (Result.isSuccess(result)) {
out.push(result.success);
}
}
return succeed(out);
}));
/** @internal */
export const filterMapEffect = /*#__PURE__*/dual(args => isIterable(args[0]) && !isEffect(args[0]), (elements, filter, options) => suspend(() => {
const out = [];
return as(forEach(elements, a => map(filter(a), result => {
if (Result.isSuccess(result)) {
out.push(result.success);
}
}), {
discard: true,
concurrency: options?.concurrency
}), out);
}));
// ----------------------------------------------------------------------------
// do notation
// ----------------------------------------------------------------------------
/** @internal */
export const Do = /*#__PURE__*/succeed({});
/** @internal */
export const bindTo = /*#__PURE__*/doNotation.bindTo(map);
/** @internal */
export const bind = /*#__PURE__*/doNotation.bind(map, flatMap);
/** @internal */
const let_ = /*#__PURE__*/doNotation.let_(map);
/** @internal */
export { let_ as let };
// ----------------------------------------------------------------------------
// fibers & forking
// ----------------------------------------------------------------------------
/** @internal */
export const forkChild = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => withFiber(fiber => {
interruptChildrenPatch();
return succeed(forkUnsafe(fiber, self, options?.startImmediately, false, options?.uninterruptible ?? false));
}));
/** @internal */
export const forkUnsafe = (parent, effect, immediate = false, daemon = false, uninterruptible = false) => {
const interruptible = uninterruptible === "inherit" ? parent.interruptible : !uninterruptible;
const child = new FiberImpl(parent.context, interruptible);
if (immediate) {
child.evaluate(effect);
} else {
parent.currentDispatcher.scheduleTask(() => child.evaluate(effect), 0);
}
if (!daemon && !child._exit) {
parent.children().add(child);
child.addObserver(() => parent._children.delete(child));
}
return child;
};
/** @internal */
export const forkDetach = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => withFiber(fiber => succeed(forkUnsafe(fiber, self, options?.startImmediately, true, options?.uninterruptible))));
/** @internal */
export const awaitAllChildren = self => withFiber(fiber => {
const initialChildren = fiber._children && Arr.fromIterable(fiber._children);
return onExit(self, _ => {
let children = fiber._children;
if (children === undefined || children.size === 0) {
return void_;
} else if (initialChildren) {
children = Iterable.filter(children, child => !initialChildren.includes(child));
}
return asVoid(fiberAwaitAll(children));
});
});
/** @internal */
export const forkIn = /*#__PURE__*/dual(args => isEffect(args[0]), (self, scope, options) => withFiber(parent => {
const fiber = forkUnsafe(parent, self, options?.startImmediately, true, options?.uninterruptible);
if (!fiber._exit) {
if (scope.state._tag !== "Closed") {
const key = {};
const finalizer = () => withFiberId(interruptor => interruptor === fiber.id ? void_ : fiberInterrupt(fiber));
scopeAddFinalizerUnsafe(scope, key, finalizer);
fiber.addObserver(() => scopeRemoveFinalizerUnsafe(scope, key));
} else {
fiber.interruptUnsafe(parent.id, fiberStackAnnotations(parent));
}
}
return succeed(fiber);
}));
/** @internal */
export const forkScoped = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => flatMap(scope, scope => forkIn(self, scope, options)));
// ----------------------------------------------------------------------------
// execution
// ----------------------------------------------------------------------------
/** @internal */
export const runForkWith = context => (effect, options) => {
const fiber = new FiberImpl(options?.scheduler ? Context.add(context, Scheduler.Scheduler, options.scheduler) : context, options?.uninterruptible !== true);
fiber.evaluate(effect);
if (fiber._exit) return fiber;
if (options?.signal) {
if (options.signal.aborted) {
fiber.interruptUnsafe();
} else {
const abort = () => fiber.interruptUnsafe();
options.signal.addEventListener("abort", abort, {
once: true
});
fiber.addObserver(() => options.signal.removeEventListener("abort", abort));
}
}
if (options?.onFiberStart) {
options.onFiberStart(fiber);
}
return fiber;
};
/** @internal */
export const fiberRunIn = /*#__PURE__*/dual(2, (self, scope) => {
if (self._exit) {
return self;
} else if (scope.state._tag === "Closed") {
self.interruptUnsafe(self.id);
return self;
}
const key = {};
scopeAddFinalizerUnsafe(scope, key, () => fiberInterrupt(self));
self.addObserver(() => scopeRemoveFinalizerUnsafe(scope, key));
return self;
});
/** @internal */
export const runFork = /*#__PURE__*/runForkWith(/*#__PURE__*/Context.empty());
/** @internal */
export const runCallbackWith = context => {
const runFork = runForkWith(context);
return (effect, options) => {
const fiber = runFork(effect, options);
if (options?.onExit) {
fiber.addObserver(options.onExit);
}
return interruptor => {
return fiber.interruptUnsafe(interruptor);
};
};
};
/** @internal */
export const runCallback = /*#__PURE__*/runCallbackWith(/*#__PURE__*/Context.empty());
/** @internal */
export const runPromiseExitWith = context => {
const runFork = runForkWith(context);
return (effect, options) => {
const fiber = runFork(effect, options);
return new Promise(resolve => {
fiber.addObserver(exit => resolve(exit));
});
};
};
/** @internal */
export const runPromiseExit = /*#__PURE__*/runPromiseExitWith(/*#__PURE__*/Context.empty());
/** @internal */
export const runPromiseWith = context => {
const runPromiseExit = runPromiseExitWith(context);
return (effect, options) => runPromiseExit(effect, options).then(exit => {
if (exit._tag === "Failure") {
throw causeSquash(exit.cause);
}
return exit.value;
});
};
/** @internal */
export const runPromise = /*#__PURE__*/runPromiseWith(/*#__PURE__*/Context.empty());
/** @internal */
export const runSyncExitWith = context => {
const runFork = runForkWith(context);
return effect => {
if (effectIsExit(effect)) return effect;
const scheduler = new Scheduler.MixedScheduler("sync");
const fiber = runFork(effect, {
scheduler
});
fiber.currentDispatcher?.flush();
return fiber._exit ?? exitDie(new AsyncFiberError(fiber));
};
};
/** @internal */
export const runSyncExit = /*#__PURE__*/runSyncExitWith(/*#__PURE__*/Context.empty());
/** @internal */
export const runSyncWith = context => {
const runSyncExit = runSyncExitWith(context);
return effect => {
const exit = runSyncExit(effect);
if (exit._tag === "Failure") throw causeSquash(exit.cause);
return exit.value;
};
};
/** @internal */
export const runSync = /*#__PURE__*/runSyncWith(/*#__PURE__*/Context.empty());
const succeedTrue = /*#__PURE__*/succeed(true);
const succeedFalse = /*#__PURE__*/succeed(false);
class Latch {
waiters = [];
scheduled = false;
isOpen;
constructor(isOpen) {
this.isOpen = isOpen;
}
scheduleUnsafe(fiber) {
if (this.scheduled || this.waiters.length === 0) {
return succeedTrue;
}
this.scheduled = true;
fiber.currentDispatcher.scheduleTask(this.flushWaiters, 0);
return succeedTrue;
}
flushWaiters = () => {
this.scheduled = false;
const waiters = this.waiters;
this.waiters = [];
for (let i = 0; i < waiters.length; i++) {
waiters[i](exitVoid);
}
};
open = /*#__PURE__*/withFiber(fiber => {
if (this.isOpen) return succeedFalse;
this.isOpen = true;
return this.scheduleUnsafe(fiber);
});
release = /*#__PURE__*/withFiber(fiber => this.isOpen ? succeedFalse : this.scheduleUnsafe(fiber));
openUnsafe() {
if (this.isOpen) return false;
this.isOpen = true;
this.flushWaiters();
return true;
}
await = /*#__PURE__*/callback(resume => {
if (this.isOpen) {
return resume(void_);
}
this.waiters.push(resume);
return sync(() => {
const index = this.waiters.indexOf(resume);
if (index !== -1) {
this.waiters.splice(index, 1);
}
});
});
closeUnsafe() {
if (!this.isOpen) return false;
this.isOpen = false;
return true;
}
close = /*#__PURE__*/sync(() => this.closeUnsafe());
whenOpen = self => flatMap(this.await, () => self);
}
/** @internal */
export const makeLatchUnsafe = open => new Latch(open ?? false);
/** @internal */
export const makeLatch = open => sync(() => makeLatchUnsafe(open));
// ----------------------------------------------------------------------------
// Tracer
// ----------------------------------------------------------------------------
/** @internal */
export const tracer = /*#__PURE__*/withFiber(fiber => succeed(fiber.getRef(Tracer.Tracer)));
/** @internal */
export const withTracer = /*#__PURE__*/dual(2, (effect, tracer) => provideService(effect, Tracer.Tracer, tracer));
/** @internal */
export const withTracerEnabled = /*#__PURE__*/provideService(TracerEnabled);
/** @internal */
export const withTracerTiming = /*#__PURE__*/provideService(TracerTimingEnabled);
const bigint0 = /*#__PURE__*/BigInt(0);
const NoopSpanProto = {
_tag: "Span",
spanId: "noop",
traceId: "noop",
sampled: false,
status: {
_tag: "Ended",
startTime: bigint0,
endTime: bigint0,
exit: exitVoid
},
attributes: /*#__PURE__*/new Map(),
links: [],
kind: "internal",
attribute() {},
event() {},
end() {},
addLinks() {}
};
/** @internal */
export const noopSpan = options => Object.assign(Object.create(NoopSpanProto), options);
const filterDisablePropagation = span => {
if (!span) return Option.none();
return Context.get(span.annotations, Tracer.DisablePropagation) ? span._tag === "Span" ? filterDisablePropagation(Option.getOrUndefined(span.parent)) : Option.none() : Option.some(span);
};
/** @internal */
export const makeSpanUnsafe = (fiber, name, options) => {
const disablePropagation = !fiber.getRef(TracerEnabled) || options?.annotations && Context.get(options.annotations, Tracer.DisablePropagation);
const parent = options?.parent !== undefined ? Option.some(options.parent) : options?.root ? Option.none() : filterDisablePropagation(fiber.currentSpan);
let span;
if (disablePropagation) {
span = noopSpan({
name,
parent,
annotations: Context.add(options?.annotations ?? Context.empty(), Tracer.DisablePropagation, true)
});
} else {
const tracer = fiber.getRef(Tracer.Tracer);
const clock = fiber.getRef(ClockRef);
const timingEnabled = fiber.getRef(TracerTimingEnabled);
const annotationsFromEnv = fiber.getRef(TracerSpanAnnotations);
const linksFromEnv = fiber.getRef(TracerSpanLinks);
const level = options?.level ?? fiber.getRef(Tracer.CurrentTraceLevel);
const links = options?.links !== undefined ? [...linksFromEnv, ...options.links] : linksFromEnv.slice();
span = tracer.span({
name,
parent,
annotations: options?.annotations ?? Context.empty(),
links,
startTime: timingEnabled ? clock.currentTimeNanosUnsafe() : BigInt(0),
kind: options?.kind ?? "internal",
root: options?.root ?? Option.isNone(parent),
sampled: options?.sampled ?? (Option.isSome(parent) && parent.value.sampled === false ? false : !isLogLevelGreaterThan(fiber.getRef(Tracer.MinimumTraceLevel), level))
});
for (const [key, value] of Object.entries(annotationsFromEnv)) {
span.attribute(key, value);
}
if (options?.attributes !== undefined) {
for (const [key, value] of Object.entries(options.attributes)) {
span.attribute(key, value);
}
}
}
return span;
};
/** @internal */
export const makeSpan = (name, options) => withFiber(fiber => succeed(makeSpanUnsafe(fiber, name, options)));
/** @internal */
export const makeSpanScoped = (name, options) => uninterruptible(withFiber(fiber => {
const scope = Context.getUnsafe(fiber.context, scopeTag);
const span = makeSpanUnsafe(fiber, name, options ?? {});
const clock = fiber.getRef(ClockRef);
const timingEnabled = fiber.getRef(TracerTimingEnabled);
return as(scopeAddFinalizerExit(scope, exit => endSpan(span, exit, clock, timingEnabled)), span);
}));
/** @internal */
export const withSpanScoped = function () {
const dataFirst = typeof arguments[0] !== "string";
const name = dataFirst ? arguments[1] : arguments[0];
const options = addSpanStackTrace(dataFirst ? arguments[2] : arguments[1]);
if (dataFirst) {
const self = arguments[0];
return flatMap(makeSpanScoped(name, options), span => withParentSpan(self, span, options));
}
return self => flatMap(makeSpanScoped(name, options), span => withParentSpan(self, span, options));
};
const provideSpanStackFrame = (name, stack) => {
stack = typeof stack === "function" ? stack : constUndefined;
return updateService(CurrentStackFrame, parent => ({
name,
stack,
parent
}));
};
/** @internal */
export const spanAnnotations = TracerSpanAnnotations;
/** @internal */
export const spanLinks = TracerSpanLinks;
/** @internal */
export const linkSpans = /*#__PURE__*/dual(args => isEffect(args[0]), (self, span, attributes = {}) => {
const spans = Array.isArray(span) ? span : [span];
const links = spans.map(span => ({
span,
attributes
}));
return updateService(self, TracerSpanLinks, current => [...current, ...links]);
});
/** @internal */
export const endSpan = (span, exit, clock, timingEnabled) => sync(() => {
if (span.status._tag === "Ended") return;
span.end(timingEnabled ? clock.currentTimeNanosUnsafe() : bigint0, exit);
});
/** @internal */
export const useSpan = (name, ...args) => {
const options = args.length === 1 ? undefined : args[0];
const evaluate = args[args.length - 1];
return withFiber(fiber => {
const span = makeSpanUnsafe(fiber, name, options);
const clock = fiber.getRef(ClockRef);
return onExit(internalCall(() => evaluate(span)), exit => sync(() => {
if (span.status._tag === "Ended") return;
span.end(clock.currentTimeNanosUnsafe(), exit);
}));
});
};
const provideParentSpan = /*#__PURE__*/provideService(Tracer.ParentSpan);
/** @internal */
export const withParentSpan = function () {
const dataFirst = isEffect(arguments[0]);
const span = dataFirst ? arguments[1] : arguments[0];
let options = dataFirst ? arguments[2] : arguments[1];
let provideStackFrame = identity;
if (span._tag === "Span") {
options = addSpanStackTrace(options);
provideStackFrame = provideSpanStackFrame(span.name, options?.captureStackTrace);
}
if (dataFirst) {
return provideParentSpan(provideStackFrame(arguments[0]), span);
}
return self => provideParentSpan(provideStackFrame(self), span);
};
/** @internal */
export const withSpan = function () {
const dataFirst = typeof arguments[0] !== "string";
const name = dataFirst ? arguments[1] : arguments[0];
const traceOptions = addSpanStackTrace(arguments[2]);
if (dataFirst) {
const self = arguments[0];
return useSpan(name, arguments[2], span => withParentSpan(self, span, traceOptions));
}
const fnArg = typeof arguments[1] === "function" ? arguments[1] : undefined;
const options = fnArg ? undefined : arguments[1];
return (self, ...args) => useSpan(name, fnArg ? fnArg(...args) : options, span => withParentSpan(self, span, traceOptions));
};
/** @internal */
export const annotateSpans = /*#__PURE__*/dual(args => isEffect(args[0]), (effect, ...args) => updateService(effect, TracerSpanAnnotations, annotations => {
const newAnnotations = {
...annotations
};
if (args.length === 1) {
Object.assign(newAnnotations, args[0]);
} else {
newAnnotations[args[0]] = args[1];
}
return newAnnotations;
}));
/** @internal */
export const annotateCurrentSpan = (...args) => withFiber(fiber => {
const span = fiber.currentSpanLocal;
if (span) {
if (args.length === 1) {
for (const [key, value] of Object.entries(args[0])) {
span.attribute(key, value);
}
} else {
span.attribute(args[0], args[1]);
}
}
return void_;
});
/** @internal */
export const currentSpan = /*#__PURE__*/withFiber(fiber => {
const span = fiber.currentSpanLocal;
return span ? succeed(span) : fail(new NoSuchElementError());
});
/** @internal */
export const currentParentSpan = /*#__PURE__*/serviceOptional(Tracer.ParentSpan);
// ----------------------------------------------------------------------------
// Clock
// ----------------------------------------------------------------------------
/** @internal */
export const ClockRef = /*#__PURE__*/Context.Reference("effect/Clock", {
defaultValue: () => new ClockImpl()
});
const MAX_TIMER_MILLIS = 2 ** 31 - 1;
class ClockImpl {
currentTimeMillisUnsafe() {
return Date.now();
}
currentTimeMillis = /*#__PURE__*/sync(() => this.currentTimeMillisUnsafe());
currentTimeNanosUnsafe() {
return processOrPerformanceNow();
}
currentTimeNanos = /*#__PURE__*/sync(() => this.currentTimeNanosUnsafe());
sleep(duration) {
const millis = Duration.toMillis(duration);
if (millis <= 0) return yieldNow;
return callback(resume => {
if (millis > MAX_TIMER_MILLIS) return;
const handle = setTimeout(() => resume(void_), millis);
return sync(() => clearTimeout(handle));
});
}
}
const performanceNowNanos = /*#__PURE__*/function () {
const bigint1e6 = /*#__PURE__*/BigInt(1_000_000);
if (typeof performance === "undefined" || typeof performance.now === "undefined") {
return () => BigInt(Date.now()) * bigint1e6;
} else if (typeof performance.timeOrigin === "number" && performance.timeOrigin === 0) {
return () => BigInt(Math.round(performance.now() * 1_000_000));
}
const origin = /*#__PURE__*/BigInt(/*#__PURE__*/Date.now()) * bigint1e6 - /*#__PURE__*/BigInt(/*#__PURE__*/Math.round(/*#__PURE__*/performance.now() * 1_000_000));
return () => origin + BigInt(Math.round(performance.now() * 1_000_000));
}();
const processOrPerformanceNow = /*#__PURE__*/function () {
const processHrtime = typeof process === "object" && "hrtime" in process && typeof process.hrtime.bigint === "function" ? process.hrtime : undefined;
if (!processHrtime) {
return performanceNowNanos;
}
const origin = /*#__PURE__*/performanceNowNanos() - /*#__PURE__*/processHrtime.bigint();
return () => origin + processHrtime.bigint();
}();
/** @internal */
export const clockWith = f => withFiber(fiber => f(fiber.getRef(ClockRef)));
/** @internal */
export const sleep = duration => clockWith(clock => clock.sleep(Duration.fromInputUnsafe(duration)));
/** @internal */
export const currentTimeMillis = /*#__PURE__*/clockWith(clock => clock.currentTimeMillis);
/** @internal */
export const currentTimeNanos = /*#__PURE__*/clockWith(clock => clock.currentTimeNanos);
// ----------------------------------------------------------------------------
// Errors
// ----------------------------------------------------------------------------
/** @internal */
export const TimeoutErrorTypeId = "~effect/Cause/TimeoutError";
/** @internal */
export const isTimeoutError = u => hasProperty(u, TimeoutErrorTypeId);
/** @internal */
export class TimeoutError extends /*#__PURE__*/TaggedError("TimeoutError") {
[TimeoutErrorTypeId] = TimeoutErrorTypeId;
constructor(message) {
super({
message
});
}
}
/** @internal */
export const IllegalArgumentErrorTypeId = "~effect/Cause/IllegalArgumentError";
/** @internal */
export const isIllegalArgumentError = u => hasProperty(u, IllegalArgumentErrorTypeId);
/** @internal */
export class IllegalArgumentError extends /*#__PURE__*/TaggedError("IllegalArgumentError") {
[IllegalArgumentErrorTypeId] = IllegalArgumentErrorTypeId;
constructor(message) {
super({
message
});
}
}
/** @internal */
export const ExceededCapacityErrorTypeId = "~effect/Cause/ExceededCapacityError";
/** @internal */
export const isExceededCapacityError = u => hasProperty(u, ExceededCapacityErrorTypeId);
/** @internal */
export class ExceededCapacityError extends /*#__PURE__*/TaggedError("ExceededCapacityError") {
[ExceededCapacityErrorTypeId] = ExceededCapacityErrorTypeId;
constructor(message) {
super({
message
});
}
}
/** @internal */
export const AsyncFiberErrorTypeId = "~effect/Cause/AsyncFiberError";
/** @internal */
export const isAsyncFiberError = u => hasProperty(u, AsyncFiberErrorTypeId);
/** @internal */
export class AsyncFiberError extends /*#__PURE__*/TaggedError("AsyncFiberError") {
[AsyncFiberErrorTypeId] = AsyncFiberErrorTypeId;
constructor(fiber) {
super({
message: "An asynchronous Effect was executed with Effect.runSync",
fiber
});
}
}
/** @internal */
export const UnknownErrorTypeId = "~effect/Cause/UnknownError";
/** @internal */
export const isUnknownError = u => hasProperty(u, UnknownErrorTypeId);
/** @internal */
export class UnknownError extends /*#__PURE__*/TaggedError("UnknownError") {
[UnknownErrorTypeId] = UnknownErrorTypeId;
constructor(cause, message) {
super({
message,
cause
});
}
}
// ----------------------------------------------------------------------------
// Console
// ----------------------------------------------------------------------------
/** @internal */
export const ConsoleRef = /*#__PURE__*/Context.Reference("effect/Console/CurrentConsole", {
defaultValue: () => globalThis.console
});
// ----------------------------------------------------------------------------
// LogLevel
// ----------------------------------------------------------------------------
/** @internal */
export const logLevelToOrder = level => {
switch (level) {
case "All":
return Number.MIN_SAFE_INTEGER;
case "Fatal":
return 50_000;
case "Error":
return 40_000;
case "Warn":
return 30_000;
case "Info":
return 20_000;
case "Debug":
return 10_000;
case "Trace":
return 0;
case "None":
return Number.MAX_SAFE_INTEGER;
}
};
/** @internal */
export const LogLevelOrder = /*#__PURE__*/Order.mapInput(Order.Number, logLevelToOrder);
/** @internal */
export const isLogLevelGreaterThan = /*#__PURE__*/Order.isGreaterThan(LogLevelOrder);
// ----------------------------------------------------------------------------
// Logger
// ----------------------------------------------------------------------------
/** @internal */
export const CurrentLoggers = /*#__PURE__*/Context.Reference("effect/Loggers/CurrentLoggers", {
defaultValue: () => new Set([defaultLogger, tracerLogger])
});
/** @internal */
export const LogToStderr = /*#__PURE__*/Context.Reference("effect/Logger/LogToStderr", {
defaultValue: constFalse
});
/** @internal */
export const annotateLogsScoped = function () {
const entries = typeof arguments[0] === "string" ? [[arguments[0], arguments[1]]] : Object.entries(arguments[0]);
return uninterruptible(withFiber(fiber => {
const prev = fiber.getRef(CurrentLogAnnotations);
const next = {
...prev
};
for (let i = 0; i < entries.length; i++) {
const [key, value] = entries[i];
next[key] = value;
}
fiber.setContext(Context.add(fiber.context, CurrentLogAnnotations, next));
return scopeAddFinalizerExit(Context.getUnsafe(fiber.context, scopeTag), _ => {
const current = fiber.getRef(CurrentLogAnnotations);
const next = {
...current
};
for (let i = 0; i < entries.length; i++) {
const [key, value] = entries[i];
if (current[key] !== value) continue;
if (key in prev) {
next[key] = prev[key];
} else {
delete next[key];
}
}
fiber.setContext(Context.add(fiber.context, CurrentLogAnnotations, next));
return void_;
});
}));
};
/** @internal */
export const LoggerTypeId = "~effect/Logger";
const LoggerProto = {
[LoggerTypeId]: {
_Message: identity,
_Output: identity
},
pipe() {
return pipeArguments(this, arguments);
}
};
/** @internal */
export const loggerMake = log => {
const self = Object.create(LoggerProto);
self.log = log;
return self;
};
/**
* Sanitize a given string by replacing spaces, equal signs, and double quotes
* with underscores.
*
* @internal
*/
export const formatLabel = key => key.replace(/[\s="]/g, "_");
/**
* Formats a log span into a `<label>=<value>ms` string.
*
* @internal
*/
export const formatLogSpan = (self, now) => {
const label = formatLabel(self[0]);
return `${label}=${now - self[1]}ms`;
};
/** @internal */
export const structuredMessage = u => {
switch (typeof u) {
case "bigint":
case "function":
case "symbol":
{
return String(u);
}
default:
{
return toJson(u);
}
}
};
/** @internal */
export const logWithLevel = level => (...message) => {
let cause = undefined;
for (let i = 0, len = message.length; i < len; i++) {
const msg = message[i];
if (isCause(msg)) {
if (cause) {
;
message.splice(i, 1);
} else {
message = message.slice(0, i).concat(message.slice(i + 1));
}
cause = cause ? causeFromReasons(cause.reasons.concat(msg.reasons)) : msg;
i--;
}
}
if (cause === undefined) {
cause = causeEmpty;
}
return withFiber(fiber => {
const logLevel = level ?? fiber.currentLogLevel;
if (isLogLevelGreaterThan(fiber.minimumLogLevel, logLevel)) {
return void_;
}
const clock = fiber.getRef(ClockRef);
const loggers = fiber.getRef(CurrentLoggers);
if (loggers.size > 0) {
const date = new Date(clock.currentTimeMillisUnsafe());
for (const logger of loggers) {
logger.log({
cause,
fiber,
date,
logLevel,
message
});
}
}
return void_;
});
};
const withColor = (text, ...colors) => {
let out = "";
for (let i = 0; i < colors.length; i++) {
out += `\x1b[${colors[i]}m`;
}
return out + text + "\x1b[0m";
};
const withColorNoop = (text, ..._colors) => text;
const colors = {
bold: "1",
red: "31",
green: "32",
yellow: "33",
blue: "34",
cyan: "36",
white: "37",
gray: "90",
black: "30",
bgBrightRed: "101"
};
const logLevelColors = {
None: [],
All: [],
Trace: [colors.gray],
Debug: [colors.blue],
Info: [colors.green],
Warn: [colors.yellow],
Error: [colors.red],
Fatal: [colors.bgBrightRed, colors.black]
};
const logLevelStyle = {
None: "",
All: "",
Trace: "color:gray",
Debug: "color:blue",
Info: "color:green",
Warn: "color:orange",
Error: "color:red",
Fatal: "background-color:red;color:white"
};
const defaultDateFormat = date => `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}.${date.getMilliseconds().toString().padStart(3, "0")}`;
/** @internal */
export const consolePretty = options => {
// evaluated lazily so the module-level bundle stays free of `process`
// property accesses, which bundlers must retain as possible side effects
const hasProcessStdout = typeof process === "object" && process !== null && typeof process.stdout === "object" && process.stdout !== null;
const processStdoutIsTTY = hasProcessStdout && process.stdout.isTTY === true;
const hasProcessStdoutOrDeno = hasProcessStdout || "Deno" in globalThis;
const mode_ = options?.mode ?? "auto";
const mode = mode_ === "auto" ? hasProcessStdoutOrDeno ? "tty" : "browser" : mode_;
const isBrowser = mode === "browser";
const showColors = typeof options?.colors === "boolean" ? options.colors : processStdoutIsTTY || isBrowser;
const formatDate = options?.formatDate ?? defaultDateFormat;
return isBrowser ? prettyLoggerBrowser({
colors: showColors,
formatDate
}) : prettyLoggerTty({
colors: showColors,
formatDate
});
};
const prettyLoggerTty = options => {
const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true;
const color = options.colors ? withColor : withColorNoop;
return loggerMake(({
cause,
date,
fiber,
logLevel,
message: message_
}) => {
const console = fiber.getRef(ConsoleRef);
// oxlint-disable-next-line no-console
const log = fiber.getRef(LogToStderr) ? console.error : console.log;
const message = Array.isArray(message_) ? message_.slice() : [message_];
let firstLine = color(`[${options.formatDate(date)}]`, colors.white) + ` ${color(logLevel.toUpperCase(), ...logLevelColors[logLevel])}` + ` (#${fiber.id})`;
const now = date.getTime();
const spans = fiber.getRef(CurrentLogSpans);
for (const span of spans) {
firstLine += " " + formatLogSpan(span, now);
}
firstLine += ":";
let messageIndex = 0;
if (message.length > 0) {
const firstMaybeString = structuredMessage(message[0]);
if (typeof firstMaybeString === "string") {
firstLine += " " + color(firstMaybeString, colors.bold, colors.cyan);
messageIndex++;
}
}
log(firstLine);
// oxlint-disable-next-line no-console
if (!processIsBun) console.group();
if (cause.reasons.length > 0) {
log(causePretty(cause));
}
if (messageIndex < message.length) {
for (; messageIndex < message.length; messageIndex++) {
log(redact(message[messageIndex]));
}
}
const annotations = fiber.getRef(CurrentLogAnnotations);
for (const [key, value] of Object.entries(annotations)) {
log(color(`${key}:`, colors.bold, colors.white), redact(value));
}
// oxlint-disable-next-line no-console
if (!processIsBun) console.groupEnd();
});
};
const prettyLoggerBrowser = options => {
const color = options.colors ? "%c" : "";
return loggerMake(({
cause,
date,
fiber,
logLevel,
message: message_
}) => {
const console = fiber.getRef(ConsoleRef);
const message = Array.isArray(message_) ? message_.slice() : [message_];
let firstLine = `${color}[${options.formatDate(date)}]`;
const firstParams = [];
if (options.colors) {
firstParams.push("color:gray");
}
firstLine += ` ${color}${logLevel.toUpperCase()}${color} (#${fiber.id})`;
if (options.colors) {
firstParams.push(logLevelStyle[logLevel], "");
}
const now = date.getTime();
const spans = fiber.getRef(CurrentLogSpans);
for (const span of spans) {
firstLine += " " + formatLogSpan(span, now);
}
firstLine += ":";
let messageIndex = 0;
if (message.length > 0) {
const firstMaybeString = structuredMessage(message[0]);
if (typeof firstMaybeString === "string") {
firstLine += ` ${color}${firstMaybeString}`;
if (options.colors) {
firstParams.push("color:deepskyblue");
}
messageIndex++;
}
}
// oxlint-disable-next-line no-console
console.groupCollapsed(firstLine, ...firstParams);
if (cause.reasons.length > 0) {
// oxlint-disable-next-line no-console
console.error(causePretty(cause));
}
if (messageIndex < message.length) {
for (; messageIndex < message.length; messageIndex++) {
// oxlint-disable-next-line no-console
console.log(redact(message[messageIndex]));
}
}
const annotations = fiber.getRef(CurrentLogAnnotations);
for (const [key, value] of Object.entries(annotations)) {
const redacted = redact(value);
if (options.colors) {
// oxlint-disable-next-line no-console
console.log(`%c${key}:`, "color:gray", redacted);
} else {
// oxlint-disable-next-line no-console
console.log(`${key}:`, redacted);
}
}
// oxlint-disable-next-line no-console
console.groupEnd();
});
};
/** @internal */
export const defaultLogger = /*#__PURE__*/loggerMake(({
cause,
date,
fiber,
logLevel,
message
}) => {
const message_ = Array.isArray(message) ? message.slice() : [message];
if (cause.reasons.length > 0) {
message_.push(causePretty(cause));
}
const now = date.getTime();
const spans = fiber.getRef(CurrentLogSpans);
let spanString = "";
for (const span of spans) {
spanString += ` ${formatLogSpan(span, now)}`;
}
const annotations = fiber.getRef(CurrentLogAnnotations);
if (Object.keys(annotations).length > 0) {
message_.push(annotations);
}
const console = fiber.getRef(ConsoleRef);
// oxlint-disable-next-line no-console
const log = fiber.getRef(LogToStderr) ? console.error : console.log;
log(`[${defaultDateFormat(date)}] ${logLevel.toUpperCase()} (#${fiber.id})${spanString}:`, ...message_);
});
/** @internal */
export const tracerLogger = /*#__PURE__*/loggerMake(({
cause,
fiber,
logLevel,
message
}) => {
const clock = fiber.getRef(ClockRef);
const annotations = fiber.getRef(CurrentLogAnnotations);
const span = fiber.currentSpan;
if (span === undefined || span._tag === "ExternalSpan") return;
const attributes = {};
for (const [key, value] of Object.entries(annotations)) {
attributes[key] = value;
}
attributes["effect.fiberId"] = fiber.id;
attributes["effect.logLevel"] = logLevel.toUpperCase();
if (cause.reasons.length > 0) {
attributes["effect.cause"] = causePretty(cause);
}
span.event(toStringUnknown(Array.isArray(message) && message.length === 1 ? message[0] : message), clock.currentTimeNanosUnsafe(), attributes);
});
/** @internal */
export function interruptChildrenPatch() {
fiberMiddleware.interruptChildren ??= fiberInterruptChildren;
}
/** @internal */
const undefined_ = /*#__PURE__*/succeed(undefined);
/** @internal */
export { undefined_ as undefined };
// ----------------------------------------------------------------------------
// ErrorReporter
// ----------------------------------------------------------------------------
/** @internal */
export const withErrorReporting = /*#__PURE__*/dual(args => isEffect(args[0]), (self, options) => onError(self, cause => withFiber(fiber => {
reportCauseUnsafe(fiber, cause, options?.defectsOnly);
return void_;
})));
/** @internal */
export const reportCauseUnsafe = (fiber, cause, defectsOnly) => {
const reporters = fiber.getRef(CurrentErrorReporters);
if (reporters.size === 0) return;
if (defectsOnly && !hasDies(cause)) return;
const opts = {
cause,
fiber,
timestamp: fiber.getRef(ClockRef).currentTimeNanosUnsafe()
};
reporters.forEach(reporter => reporter.report(opts));
};
//# sourceMappingURL=effect.js.map

Xet Storage Details

Size:
110 kB
·
Xet hash:
3ddacc50e47d68669a0293df146b924106060b1fc24ae42eae5152159336c42e

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.