effect
Version:
The missing standard library for TypeScript, for writing production-grade software.
1,567 lines (1,565 loc) • 81 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.onExit = exports.onError = exports.never = exports.matchEffect = exports.matchCauseEffect = exports.matchCause = exports.match = exports.mapErrorCause = exports.mapError = exports.map = exports.let = exports.isMicroExit = exports.isMicroCause = exports.isMicro = exports.interruptible = exports.interrupt = exports.ignoreLogged = exports.ignore = exports.gen = exports.fromOption = exports.fromEither = exports.forkScoped = exports.forkIn = exports.forkDaemon = exports.fork = exports.forever = exports.forEach = exports.flip = exports.flatten = exports.flatMap = exports.filterOrFailCause = exports.filterOrFail = exports.filterMap = exports.filter = exports.fiberJoin = exports.fiberInterruptAll = exports.fiberInterrupt = exports.fiberAwait = exports.failSync = exports.failCauseSync = exports.failCause = exports.fail = exports.exitVoidAll = exports.exitVoid = exports.exitSucceed = exports.exitIsSuccess = exports.exitIsInterrupt = exports.exitIsFailure = exports.exitIsFail = exports.exitIsDie = exports.exitInterrupt = exports.exitFailCause = exports.exitFail = exports.exitDie = exports.exit = exports.ensuring = exports.either = exports.die = exports.delay = exports.context = exports.causeWithTrace = exports.causeSquash = exports.causeIsInterrupt = exports.causeIsFail = exports.causeIsDie = exports.causeInterrupt = exports.causeFail = exports.causeDie = exports.catchTag = exports.catchIf = exports.catchCauseIf = exports.catchAllDefect = exports.catchAllCause = exports.catchAll = exports.bindTo = exports.bind = exports.async = exports.asVoid = exports.asSome = exports.as = exports.andThen = exports.all = exports.addFinalizer = exports.acquireUseRelease = exports.acquireRelease = exports.TypeId = exports.TimeoutException = exports.TaggedError = exports.NoSuchElementException = exports.MicroScopeTypeId = exports.MicroScope = exports.MicroSchedulerDefault = exports.MicroFiberTypeId = exports.MicroExitTypeId = exports.MicroCauseTypeId = exports.MaxOpsBeforeYield = exports.Error = exports.Do = exports.CurrentScheduler = exports.CurrentConcurrency = void 0;
exports.zipWith = exports.zip = exports.yieldNowWith = exports.yieldNow = exports.yieldFlush = exports.withTrace = exports.withMicroFiber = exports.withConcurrency = exports.whileLoop = exports.when = exports.void = exports.updateService = exports.updateContext = exports.uninterruptibleMask = exports.uninterruptible = exports.tryPromise = exports.try = exports.timeoutOrElse = exports.timeoutOption = exports.timeout = exports.tapErrorCauseIf = exports.tapErrorCause = exports.tapError = exports.tapDefect = exports.tap = exports.sync = exports.suspend = exports.succeedSome = exports.succeedNone = exports.succeed = exports.sleep = exports.serviceOption = exports.service = exports.scoped = exports.scopeUnsafeMake = exports.scopeMake = exports.scope = exports.scheduleWithMaxElapsed = exports.scheduleWithMaxDelay = exports.scheduleUnion = exports.scheduleSpaced = exports.scheduleRecurs = exports.scheduleIntersect = exports.scheduleExponential = exports.scheduleAddDelay = exports.sandbox = exports.runSyncExit = exports.runSync = exports.runPromiseExit = exports.runPromise = exports.runFork = exports.retry = exports.replicateEffect = exports.replicate = exports.repeatExit = exports.repeat = exports.raceFirst = exports.raceAllFirst = exports.raceAll = exports.race = exports.provideServiceEffect = exports.provideService = exports.provideScope = exports.provideContext = exports.promise = exports.orElseSucceed = exports.orDie = exports.option = exports.onInterrupt = exports.onExitIf = void 0;
var Arr = _interopRequireWildcard(require("./Array.js"));
var Context = _interopRequireWildcard(require("./Context.js"));
var Effectable = _interopRequireWildcard(require("./Effectable.js"));
var Either = _interopRequireWildcard(require("./Either.js"));
var Equal = _interopRequireWildcard(require("./Equal.js"));
var _Function = require("./Function.js");
var _GlobalValue = require("./GlobalValue.js");
var Hash = _interopRequireWildcard(require("./Hash.js"));
var _Inspectable = require("./Inspectable.js");
var InternalContext = _interopRequireWildcard(require("./internal/context.js"));
var doNotation = _interopRequireWildcard(require("./internal/doNotation.js"));
var _effectable = require("./internal/effectable.js");
var Option = _interopRequireWildcard(require("./Option.js"));
var _Pipeable = require("./Pipeable.js");
var _Predicate = require("./Predicate.js");
var _Utils = require("./Utils.js");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* A lightweight alternative to the `Effect` data type, with a subset of the functionality.
*
* @since 3.4.0
* @experimental
*/
/**
* @since 3.4.0
* @experimental
* @category type ids
*/
const TypeId = exports.TypeId = /*#__PURE__*/Symbol.for("effect/Micro");
/**
* @since 3.4.0
* @experimental
* @category MicroExit
*/
const MicroExitTypeId = exports.MicroExitTypeId = /*#__PURE__*/Symbol.for("effect/Micro/MicroExit");
/**
* @since 3.4.0
* @experimental
* @category guards
*/
const isMicro = u => typeof u === "object" && u !== null && TypeId in u;
// ----------------------------------------------------------------------------
// MicroCause
// ----------------------------------------------------------------------------
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.isMicro = isMicro;
const MicroCauseTypeId = exports.MicroCauseTypeId = /*#__PURE__*/Symbol.for("effect/Micro/MicroCause");
/**
* @since 3.6.6
* @experimental
* @category guards
*/
const isMicroCause = self => (0, _Predicate.hasProperty)(self, MicroCauseTypeId);
exports.isMicroCause = isMicroCause;
const microCauseVariance = {
_E: _Function.identity
};
class MicroCauseImpl extends globalThis.Error {
_tag;
traces;
[MicroCauseTypeId];
constructor(_tag, originalError, traces) {
const causeName = `MicroCause.${_tag}`;
let name;
let message;
let stack;
if (originalError instanceof globalThis.Error) {
name = `(${causeName}) ${originalError.name}`;
message = originalError.message;
const messageLines = message.split("\n").length;
stack = originalError.stack ? `(${causeName}) ${originalError.stack.split("\n").slice(0, messageLines + 3).join("\n")}` : `${name}: ${message}`;
} else {
name = causeName;
message = (0, _Inspectable.toStringUnknown)(originalError, 0);
stack = `${name}: ${message}`;
}
if (traces.length > 0) {
stack += `\n ${traces.join("\n ")}`;
}
super(message);
this._tag = _tag;
this.traces = traces;
this[MicroCauseTypeId] = microCauseVariance;
this.name = name;
this.stack = stack;
}
pipe() {
return (0, _Pipeable.pipeArguments)(this, arguments);
}
toString() {
return this.stack;
}
[_Inspectable.NodeInspectSymbol]() {
return this.stack;
}
}
class Fail extends MicroCauseImpl {
error;
constructor(error, traces = []) {
super("Fail", error, traces);
this.error = error;
}
}
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
const causeFail = (error, traces = []) => new Fail(error, traces);
exports.causeFail = causeFail;
class Die extends MicroCauseImpl {
defect;
constructor(defect, traces = []) {
super("Die", defect, traces);
this.defect = defect;
}
}
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
const causeDie = (defect, traces = []) => new Die(defect, traces);
exports.causeDie = causeDie;
class Interrupt extends MicroCauseImpl {
constructor(traces = []) {
super("Interrupt", "interrupted", traces);
}
}
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
const causeInterrupt = (traces = []) => new Interrupt(traces);
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.causeInterrupt = causeInterrupt;
const causeIsFail = self => self._tag === "Fail";
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.causeIsFail = causeIsFail;
const causeIsDie = self => self._tag === "Die";
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.causeIsDie = causeIsDie;
const causeIsInterrupt = self => self._tag === "Interrupt";
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.causeIsInterrupt = causeIsInterrupt;
const causeSquash = self => self._tag === "Fail" ? self.error : self._tag === "Die" ? self.defect : self;
/**
* @since 3.4.6
* @experimental
* @category MicroCause
*/
exports.causeSquash = causeSquash;
const causeWithTrace = exports.causeWithTrace = /*#__PURE__*/(0, _Function.dual)(2, (self, trace) => {
const traces = [...self.traces, trace];
switch (self._tag) {
case "Die":
return causeDie(self.defect, traces);
case "Interrupt":
return causeInterrupt(traces);
case "Fail":
return causeFail(self.error, traces);
}
});
// ----------------------------------------------------------------------------
// MicroFiber
// ----------------------------------------------------------------------------
/**
* @since 3.11.0
* @experimental
* @category MicroFiber
*/
const MicroFiberTypeId = exports.MicroFiberTypeId = /*#__PURE__*/Symbol.for("effect/Micro/MicroFiber");
const fiberVariance = {
_A: _Function.identity,
_E: _Function.identity
};
class MicroFiberImpl {
context;
interruptible;
[MicroFiberTypeId];
_stack = [];
_observers = [];
_exit;
_children;
currentOpCount = 0;
constructor(context, interruptible = true) {
this.context = context;
this.interruptible = interruptible;
this[MicroFiberTypeId] = fiberVariance;
}
getRef(ref) {
return InternalContext.unsafeGetReference(this.context, ref);
}
addObserver(cb) {
if (this._exit) {
cb(this._exit);
return _Function.constVoid;
}
this._observers.push(cb);
return () => {
const index = this._observers.indexOf(cb);
if (index >= 0) {
this._observers.splice(index, 1);
}
};
}
_interrupted = false;
unsafeInterrupt() {
if (this._exit) {
return;
}
this._interrupted = true;
if (this.interruptible) {
this.evaluate(exitInterrupt);
}
}
unsafePoll() {
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 middlware is added in Micro.fork, 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;
for (let i = 0; i < this._observers.length; i++) {
this._observers[i](exit);
}
this._observers.length = 0;
}
runLoop(effect) {
let yielding = false;
let current = effect;
this.currentOpCount = 0;
try {
while (true) {
this.currentOpCount++;
if (!yielding && this.getRef(CurrentScheduler).shouldYield(this)) {
yielding = true;
const prev = current;
current = flatMap(yieldNow, () => prev);
}
current = current[evaluate](this);
if (current === Yield) {
const yielded = this._yielded;
if (MicroExitTypeId in yielded) {
this._yielded = undefined;
return yielded;
}
return Yield;
}
}
} catch (error) {
if (!(0, _Predicate.hasProperty)(current, evaluate)) {
return exitDie(`MicroFiber.runLoop: Not a valid effect: ${String(current)}`);
}
return exitDie(error);
}
}
getCont(symbol) {
while (true) {
const op = this._stack.pop();
if (!op) return undefined;
const cont = op[ensureCont] && op[ensureCont](this);
if (cont) return {
[symbol]: cont
};
if (op[symbol]) return op;
}
}
// cancel the yielded operation, or for the yielded exit value
_yielded = undefined;
yieldWith(value) {
this._yielded = value;
return Yield;
}
children() {
return this._children ??= new Set();
}
}
const fiberMiddleware = /*#__PURE__*/(0, _GlobalValue.globalValue)("effect/Micro/fiberMiddleware", () => ({
interruptChildren: undefined
}));
const fiberInterruptChildren = fiber => {
if (fiber._children === undefined || fiber._children.size === 0) {
return undefined;
}
return fiberInterruptAll(fiber._children);
};
/**
* @since 3.11.0
* @experimental
* @category MicroFiber
*/
const fiberAwait = self => async(resume => sync(self.addObserver(exit => resume(succeed(exit)))));
/**
* @since 3.11.2
* @experimental
* @category MicroFiber
*/
exports.fiberAwait = fiberAwait;
const fiberJoin = self => flatten(fiberAwait(self));
/**
* @since 3.11.0
* @experimental
* @category MicroFiber
*/
exports.fiberJoin = fiberJoin;
const fiberInterrupt = self => suspend(() => {
self.unsafeInterrupt();
return asVoid(fiberAwait(self));
});
/**
* @since 3.11.0
* @experimental
* @category MicroFiber
*/
exports.fiberInterrupt = fiberInterrupt;
const fiberInterruptAll = fibers => suspend(() => {
for (const fiber of fibers) fiber.unsafeInterrupt();
const iter = fibers[Symbol.iterator]();
const wait = suspend(() => {
let result = iter.next();
while (!result.done) {
if (result.value.unsafePoll()) {
result = iter.next();
continue;
}
const fiber = result.value;
return async(resume => {
fiber.addObserver(_ => {
resume(wait);
});
});
}
return exitVoid;
});
return wait;
});
exports.fiberInterruptAll = fiberInterruptAll;
const identifier = /*#__PURE__*/Symbol.for("effect/Micro/identifier");
const args = /*#__PURE__*/Symbol.for("effect/Micro/args");
const evaluate = /*#__PURE__*/Symbol.for("effect/Micro/evaluate");
const successCont = /*#__PURE__*/Symbol.for("effect/Micro/successCont");
const failureCont = /*#__PURE__*/Symbol.for("effect/Micro/failureCont");
const ensureCont = /*#__PURE__*/Symbol.for("effect/Micro/ensureCont");
const Yield = /*#__PURE__*/Symbol.for("effect/Micro/Yield");
const microVariance = {
_A: _Function.identity,
_E: _Function.identity,
_R: _Function.identity
};
const MicroProto = {
...Effectable.EffectPrototype,
_op: "Micro",
[TypeId]: microVariance,
pipe() {
return (0, _Pipeable.pipeArguments)(this, arguments);
},
[Symbol.iterator]() {
return new _Utils.SingleShotGen(new _Utils.YieldWrap(this));
},
toJSON() {
return {
_id: "Micro",
op: this[identifier],
...(args in this ? {
args: this[args]
} : undefined)
};
},
toString() {
return (0, _Inspectable.format)(this);
},
[_Inspectable.NodeInspectSymbol]() {
return (0, _Inspectable.format)(this);
}
};
function defaultEvaluate(_fiber) {
return exitDie(`Micro.evaluate: Not implemented`);
}
const makePrimitiveProto = options => ({
...MicroProto,
[identifier]: options.op,
[evaluate]: options.eval ?? defaultEvaluate,
[successCont]: options.contA,
[failureCont]: options.contE,
[ensureCont]: options.ensure
});
const makePrimitive = options => {
const Proto = makePrimitiveProto(options);
return function () {
const self = Object.create(Proto);
self[args] = options.single === false ? arguments : arguments[0];
return self;
};
};
const makeExit = options => {
const Proto = {
...makePrimitiveProto(options),
[MicroExitTypeId]: MicroExitTypeId,
_tag: options.op,
get [options.prop]() {
return this[args];
},
toJSON() {
return {
_id: "MicroExit",
_tag: options.op,
[options.prop]: this[args]
};
},
[Equal.symbol](that) {
return isMicroExit(that) && that._tag === options.op && Equal.equals(this[args], that[args]);
},
[Hash.symbol]() {
return Hash.cached(this, Hash.combine(Hash.string(options.op))(Hash.hash(this[args])));
}
};
return function (value) {
const self = Object.create(Proto);
self[args] = value;
self[successCont] = undefined;
self[failureCont] = undefined;
self[ensureCont] = undefined;
return self;
};
};
/**
* Creates a `Micro` effect that will succeed with the specified constant value.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const succeed = exports.succeed = /*#__PURE__*/makeExit({
op: "Success",
prop: "value",
eval(fiber) {
const cont = fiber.getCont(successCont);
return cont ? cont[successCont](this[args], fiber) : fiber.yieldWith(this);
}
});
/**
* Creates a `Micro` effect that will fail with the specified `MicroCause`.
*
* @since 3.4.6
* @experimental
* @category constructors
*/
const failCause = exports.failCause = /*#__PURE__*/makeExit({
op: "Failure",
prop: "cause",
eval(fiber) {
let cont = fiber.getCont(failureCont);
while (causeIsInterrupt(this[args]) && cont && fiber.interruptible) {
cont = fiber.getCont(failureCont);
}
return cont ? cont[failureCont](this[args], fiber) : fiber.yieldWith(this);
}
});
/**
* Creates a `Micro` effect that fails with the given error.
*
* This results in a `Fail` variant of the `MicroCause` type, where the error is
* tracked at the type level.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const fail = error => failCause(causeFail(error));
/**
* Creates a `Micro` effect that succeeds with a lazily evaluated value.
*
* If the evaluation of the value throws an error, the effect will fail with a
* `Die` variant of the `MicroCause` type.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.fail = fail;
const sync = exports.sync = /*#__PURE__*/makePrimitive({
op: "Sync",
eval(fiber) {
const value = this[args]();
const cont = fiber.getCont(successCont);
return cont ? cont[successCont](value, fiber) : fiber.yieldWith(exitSucceed(value));
}
});
/**
* Lazily creates a `Micro` effect from the given side-effect.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const suspend = exports.suspend = /*#__PURE__*/makePrimitive({
op: "Suspend",
eval(_fiber) {
return this[args]();
}
});
/**
* Pause the execution of the current `Micro` effect, and resume it on the next
* scheduler tick.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const yieldNowWith = exports.yieldNowWith = /*#__PURE__*/makePrimitive({
op: "Yield",
eval(fiber) {
let resumed = false;
fiber.getRef(CurrentScheduler).scheduleTask(() => {
if (resumed) return;
fiber.evaluate(exitVoid);
}, this[args] ?? 0);
return fiber.yieldWith(() => {
resumed = true;
});
}
});
/**
* Pause the execution of the current `Micro` effect, and resume it on the next
* scheduler tick.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const yieldNow = exports.yieldNow = /*#__PURE__*/yieldNowWith(0);
/**
* Creates a `Micro` effect that will succeed with the value wrapped in `Some`.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const succeedSome = a => succeed(Option.some(a));
/**
* Creates a `Micro` effect that succeeds with `None`.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.succeedSome = succeedSome;
const succeedNone = exports.succeedNone = /*#__PURE__*/succeed( /*#__PURE__*/Option.none());
/**
* Creates a `Micro` effect that will fail with the lazily evaluated `MicroCause`.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const failCauseSync = evaluate => suspend(() => failCause(evaluate()));
/**
* Creates a `Micro` effect that will die with the specified error.
*
* This results in a `Die` variant of the `MicroCause` type, where the error is
* not tracked at the type level.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.failCauseSync = failCauseSync;
const die = defect => exitDie(defect);
/**
* Creates a `Micro` effect that will fail with the lazily evaluated error.
*
* This results in a `Fail` variant of the `MicroCause` type, where the error is
* tracked at the type level.
*
* @since 3.4.6
* @experimental
* @category constructors
*/
exports.die = die;
const failSync = error => suspend(() => fail(error()));
/**
* Converts an `Option` into a `Micro` effect, that will fail with
* `NoSuchElementException` if the option is `None`. Otherwise, it will succeed with the
* value of the option.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.failSync = failSync;
const fromOption = option => option._tag === "Some" ? succeed(option.value) : fail(new NoSuchElementException({}));
/**
* Converts an `Either` into a `Micro` effect, that will fail with the left side
* of the either if it is a `Left`. Otherwise, it will succeed with the right
* side of the either.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.fromOption = fromOption;
const fromEither = either => either._tag === "Right" ? succeed(either.right) : fail(either.left);
exports.fromEither = fromEither;
const void_ = exports.void = /*#__PURE__*/succeed(void 0);
const try_ = options => suspend(() => {
try {
return succeed(options.try());
} catch (err) {
return fail(options.catch(err));
}
});
exports.try = try_;
/**
* Wrap a `Promise` into a `Micro` effect.
*
* Any errors will result in a `Die` variant of the `MicroCause` type, where the
* error is not tracked at the type level.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const promise = evaluate => asyncOptions(function (resume, signal) {
evaluate(signal).then(a => resume(succeed(a)), e => resume(die(e)));
}, evaluate.length !== 0);
/**
* Wrap a `Promise` into a `Micro` effect. Any errors will be caught and
* converted into a specific error type.
*
* @example
* ```ts
* import { Micro } from "effect"
*
* Micro.tryPromise({
* try: () => Promise.resolve("success"),
* catch: (cause) => new Error("caught", { cause })
* })
* ```
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.promise = promise;
const tryPromise = options => asyncOptions(function (resume, signal) {
try {
options.try(signal).then(a => resume(succeed(a)), e => resume(fail(options.catch(e))));
} catch (err) {
resume(fail(options.catch(err)));
}
}, options.try.length !== 0);
/**
* Create a `Micro` effect using the current `MicroFiber`.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.tryPromise = tryPromise;
const withMicroFiber = exports.withMicroFiber = /*#__PURE__*/makePrimitive({
op: "WithMicroFiber",
eval(fiber) {
return this[args](fiber);
}
});
/**
* Flush any yielded effects that are waiting to be executed.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const yieldFlush = exports.yieldFlush = /*#__PURE__*/withMicroFiber(fiber => {
fiber.getRef(CurrentScheduler).flush();
return exitVoid;
});
const asyncOptions = /*#__PURE__*/makePrimitive({
op: "Async",
single: false,
eval(fiber) {
const register = this[args][0];
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",
ensure(fiber) {
if (fiber.interruptible) {
fiber.interruptible = false;
fiber._stack.push(setInterruptible(true));
}
},
contE(cause, _fiber) {
return causeIsInterrupt(cause) ? flatMap(this[args](), () => failCause(cause)) : failCause(cause);
}
});
/**
* Create a `Micro` effect from an asynchronous computation.
*
* You can return a cleanup effect that will be run when the effect is aborted.
* It is also passed an `AbortSignal` that is triggered when the effect is
* aborted.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
const async = register => asyncOptions(register, register.length >= 2);
/**
* A `Micro` that will never succeed or fail. It wraps `setInterval` to prevent
* the Javascript runtime from exiting.
*
* @since 3.4.0
* @experimental
* @category constructors
*/
exports.async = async;
const never = exports.never = /*#__PURE__*/async(function () {
const interval = setInterval(_Function.constVoid, 2147483646);
return sync(() => clearInterval(interval));
});
/**
* @since 3.4.0
* @experimental
* @category constructors
*/
const gen = (...args) => suspend(() => fromIterator(args.length === 1 ? args[0]() : args[1].call(args[0])));
exports.gen = gen;
const fromIterator = /*#__PURE__*/makePrimitive({
op: "Iterator",
contA(value, fiber) {
const state = this[args].next(value);
if (state.done) return succeed(state.value);
fiber._stack.push(this);
return (0, _Utils.yieldWrapGet)(state.value);
},
eval(fiber) {
return this[successCont](undefined, fiber);
}
});
// ----------------------------------------------------------------------------
// mapping & sequencing
// ----------------------------------------------------------------------------
/**
* Create a `Micro` effect that will replace the success value of the given
* effect.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const as = exports.as = /*#__PURE__*/(0, _Function.dual)(2, (self, value) => map(self, _ => value));
/**
* Wrap the success value of this `Micro` effect in a `Some`.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const asSome = self => map(self, Option.some);
/**
* Swap the error and success types of the `Micro` effect.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
exports.asSome = asSome;
const flip = self => matchEffect(self, {
onFailure: succeed,
onSuccess: fail
});
/**
* A more flexible version of `flatMap` that combines `map` and `flatMap` into a
* single API.
*
* It also lets you directly pass a `Micro` effect, which will be executed after
* the current effect.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
exports.flip = flip;
const andThen = exports.andThen = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => flatMap(self, a => {
const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f;
return isMicro(value) ? value : succeed(value);
}));
/**
* Execute a side effect from the success value of the `Micro` effect.
*
* It is similar to the `andThen` api, but the success value is ignored.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const tap = exports.tap = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => flatMap(self, a => {
const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f;
return isMicro(value) ? as(value, a) : succeed(a);
}));
/**
* Replace the success value of the `Micro` effect with `void`.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const asVoid = self => flatMap(self, _ => exitVoid);
/**
* Access the `MicroExit` of the given `Micro` effect.
*
* @since 3.4.6
* @experimental
* @category mapping & sequencing
*/
exports.asVoid = asVoid;
const exit = self => matchCause(self, {
onFailure: exitFailCause,
onSuccess: exitSucceed
});
/**
* Replace the error type of the given `Micro` with the full `MicroCause` object.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
exports.exit = exit;
const sandbox = self => catchAllCause(self, fail);
/**
* Returns an effect that races all the specified effects,
* yielding the value of the first effect to succeed with a value. Losers of
* the race will be interrupted immediately
*
* @since 3.4.0
* @experimental
* @category sequencing
*/
exports.sandbox = sandbox;
const raceAll = all => withMicroFiber(parent => async(resume => {
const effects = Arr.fromIterable(all);
const len = effects.length;
let doneCount = 0;
let done = false;
const fibers = new Set();
const causes = [];
const onExit = exit => {
doneCount++;
if (exit._tag === "Failure") {
causes.push(exit.cause);
if (doneCount >= len) {
resume(failCause(causes[0]));
}
return;
}
done = true;
resume(fibers.size === 0 ? exit : flatMap(uninterruptible(fiberInterruptAll(fibers)), () => exit));
};
for (let i = 0; i < len; i++) {
if (done) break;
const fiber = unsafeFork(parent, interruptible(effects[i]), true, true);
fibers.add(fiber);
fiber.addObserver(exit => {
fibers.delete(fiber);
onExit(exit);
});
}
return fiberInterruptAll(fibers);
}));
/**
* Returns an effect that races all the specified effects,
* yielding the value of the first effect to succeed or fail. Losers of
* the race will be interrupted immediately.
*
* @since 3.4.0
* @experimental
* @category sequencing
*/
exports.raceAll = raceAll;
const raceAllFirst = all => withMicroFiber(parent => async(resume => {
let done = false;
const fibers = new Set();
const onExit = exit => {
done = true;
resume(fibers.size === 0 ? exit : flatMap(fiberInterruptAll(fibers), () => exit));
};
for (const effect of all) {
if (done) break;
const fiber = unsafeFork(parent, interruptible(effect), true, true);
fibers.add(fiber);
fiber.addObserver(exit => {
fibers.delete(fiber);
onExit(exit);
});
}
return fiberInterruptAll(fibers);
}));
/**
* Returns an effect that races two effects, yielding the value of the first
* effect to succeed. Losers of the race will be interrupted immediately.
*
* @since 3.4.0
* @experimental
* @category sequencing
*/
exports.raceAllFirst = raceAllFirst;
const race = exports.race = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => raceAll([self, that]));
/**
* Returns an effect that races two effects, yielding the value of the first
* effect to succeed *or* fail. Losers of the race will be interrupted immediately.
*
* @since 3.4.0
* @experimental
* @category sequencing
*/
const raceFirst = exports.raceFirst = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => raceAllFirst([self, that]));
/**
* Map the success value of this `Micro` effect to another `Micro` effect, then
* flatten the result.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const flatMap = exports.flatMap = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => {
const onSuccess = Object.create(OnSuccessProto);
onSuccess[args] = self;
onSuccess[successCont] = f;
return onSuccess;
});
const OnSuccessProto = /*#__PURE__*/makePrimitiveProto({
op: "OnSuccess",
eval(fiber) {
fiber._stack.push(this);
return this[args];
}
});
// ----------------------------------------------------------------------------
// mapping & sequencing
// ----------------------------------------------------------------------------
/**
* Flattens any nested `Micro` effects, merging the error and requirement types.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
const flatten = self => flatMap(self, _Function.identity);
/**
* Transforms the success value of the `Micro` effect with the specified
* function.
*
* @since 3.4.0
* @experimental
* @category mapping & sequencing
*/
exports.flatten = flatten;
const map = exports.map = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => flatMap(self, a => succeed(f(a))));
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
const isMicroExit = u => (0, _Predicate.hasProperty)(u, MicroExitTypeId);
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.isMicroExit = isMicroExit;
const exitSucceed = exports.exitSucceed = succeed;
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
const exitFailCause = exports.exitFailCause = failCause;
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
const exitInterrupt = exports.exitInterrupt = /*#__PURE__*/exitFailCause( /*#__PURE__*/causeInterrupt());
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
const exitFail = e => exitFailCause(causeFail(e));
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitFail = exitFail;
const exitDie = defect => exitFailCause(causeDie(defect));
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitDie = exitDie;
const exitIsSuccess = self => self._tag === "Success";
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitIsSuccess = exitIsSuccess;
const exitIsFailure = self => self._tag === "Failure";
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitIsFailure = exitIsFailure;
const exitIsInterrupt = self => exitIsFailure(self) && self.cause._tag === "Interrupt";
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitIsInterrupt = exitIsInterrupt;
const exitIsFail = self => exitIsFailure(self) && self.cause._tag === "Fail";
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitIsFail = exitIsFail;
const exitIsDie = self => exitIsFailure(self) && self.cause._tag === "Die";
/**
* @since 3.4.6
* @experimental
* @category MicroExit
*/
exports.exitIsDie = exitIsDie;
const exitVoid = exports.exitVoid = /*#__PURE__*/exitSucceed(void 0);
/**
* @since 3.11.0
* @experimental
* @category MicroExit
*/
const exitVoidAll = exits => {
for (const exit of exits) {
if (exit._tag === "Failure") {
return exit;
}
}
return exitVoid;
};
exports.exitVoidAll = exitVoidAll;
const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : f => setTimeout(f, 0);
/**
* @since 3.5.9
* @experimental
* @category scheduler
*/
class MicroSchedulerDefault {
tasks = [];
running = false;
/**
* @since 3.5.9
*/
scheduleTask(task, _priority) {
this.tasks.push(task);
if (!this.running) {
this.running = true;
setImmediate(this.afterScheduled);
}
}
/**
* @since 3.5.9
*/
afterScheduled = () => {
this.running = false;
this.runTasks();
};
/**
* @since 3.5.9
*/
runTasks() {
const tasks = this.tasks;
this.tasks = [];
for (let i = 0, len = tasks.length; i < len; i++) {
tasks[i]();
}
}
/**
* @since 3.5.9
*/
shouldYield(fiber) {
return fiber.currentOpCount >= fiber.getRef(MaxOpsBeforeYield);
}
/**
* @since 3.5.9
*/
flush() {
while (this.tasks.length > 0) {
this.runTasks();
}
}
}
/**
* Access the given `Context.Tag` from the environment.
*
* @since 3.4.0
* @experimental
* @category environment
*/
exports.MicroSchedulerDefault = MicroSchedulerDefault;
const service = tag => withMicroFiber(fiber => succeed(Context.unsafeGet(fiber.context, tag)));
/**
* Access the given `Context.Tag` from the environment, without tracking the
* dependency at the type level.
*
* It will return an `Option` of the service, depending on whether it is
* available in the environment or not.
*
* @since 3.4.0
* @experimental
* @category environment
*/
exports.service = service;
const serviceOption = tag => withMicroFiber(fiber => succeed(Context.getOption(fiber.context, tag)));
/**
* Update the Context with the given mapping function.
*
* @since 3.11.0
* @experimental
* @category environment
*/
exports.serviceOption = serviceOption;
const updateContext = exports.updateContext = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => withMicroFiber(fiber => {
const prev = fiber.context;
fiber.context = f(prev);
return onExit(self, () => {
fiber.context = prev;
return void_;
});
}));
/**
* Update the service for the given `Context.Tag` in the environment.
*
* @since 3.11.0
* @experimental
* @category environment
*/
const updateService = exports.updateService = /*#__PURE__*/(0, _Function.dual)(3, (self, tag, f) => withMicroFiber(fiber => {
const prev = Context.unsafeGet(fiber.context, tag);
fiber.context = Context.add(fiber.context, tag, f(prev));
return onExit(self, () => {
fiber.context = Context.add(fiber.context, tag, prev);
return void_;
});
}));
/**
* Access the current `Context` from the environment.
*
* @since 3.4.0
* @experimental
* @category environment
*/
const context = () => getContext;
exports.context = context;
const getContext = /*#__PURE__*/withMicroFiber(fiber => succeed(fiber.context));
/**
* Merge the given `Context` with the current context.
*
* @since 3.4.0
* @experimental
* @category environment
*/
const provideContext = exports.provideContext = /*#__PURE__*/(0, _Function.dual)(2, (self, provided) => updateContext(self, Context.merge(provided)));
/**
* Add the provided service to the current context.
*
* @since 3.4.0
* @experimental
* @category environment
*/
const provideService = exports.provideService = /*#__PURE__*/(0, _Function.dual)(3, (self, tag, service) => updateContext(self, Context.add(tag, service)));
/**
* Create a service using the provided `Micro` effect, and add it to the
* current context.
*
* @since 3.4.6
* @experimental
* @category environment
*/
const provideServiceEffect = exports.provideServiceEffect = /*#__PURE__*/(0, _Function.dual)(3, (self, tag, acquire) => flatMap(acquire, service => provideService(self, tag, service)));
// ========================================================================
// References
// ========================================================================
/**
* @since 3.11.0
* @experimental
* @category references
*/
class MaxOpsBeforeYield extends /*#__PURE__*/Context.Reference()("effect/Micro/currentMaxOpsBeforeYield", {
defaultValue: () => 2048
}) {}
/**
* @since 3.11.0
* @experimental
* @category environment refs
*/
exports.MaxOpsBeforeYield = MaxOpsBeforeYield;
class CurrentConcurrency extends /*#__PURE__*/Context.Reference()("effect/Micro/currentConcurrency", {
defaultValue: () => "unbounded"
}) {}
/**
* @since 3.11.0
* @experimental
* @category environment refs
*/
exports.CurrentConcurrency = CurrentConcurrency;
class CurrentScheduler extends /*#__PURE__*/Context.Reference()("effect/Micro/currentScheduler", {
defaultValue: () => new MicroSchedulerDefault()
}) {}
/**
* If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
* api to control the concurrency of that `Micro` when it is run.
*
* @example
* ```ts
* import * as Micro from "effect/Micro"
*
* Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
* concurrency: "inherit"
* }).pipe(
* Micro.withConcurrency(2) // use a concurrency of 2
* )
* ```
*
* @since 3.4.0
* @experimental
* @category environment refs
*/
exports.CurrentScheduler = CurrentScheduler;
const withConcurrency = exports.withConcurrency = /*#__PURE__*/(0, _Function.dual)(2, (self, concurrency) => provideService(self, CurrentConcurrency, concurrency));
// ----------------------------------------------------------------------------
// zipping
// ----------------------------------------------------------------------------
/**
* Combine two `Micro` effects into a single effect that produces a tuple of
* their results.
*
* @since 3.4.0
* @experimental
* @category zipping
*/
const zip = exports.zip = /*#__PURE__*/(0, _Function.dual)(args => isMicro(args[1]), (self, that, options) => zipWith(self, that, (a, a2) => [a, a2], options));
/**
* The `Micro.zipWith` function combines two `Micro` effects and allows you to
* apply a function to the results of the combined effects, transforming them
* into a single value.
*
* @since 3.4.3
* @experimental
* @category zipping
*/
const zipWith = exports.zipWith = /*#__PURE__*/(0, _Function.dual)(args => isMicro(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]) => f(a, a2)) : flatMap(self, a => map(that, a2 => f(a, a2))));
// ----------------------------------------------------------------------------
// filtering & conditionals
// ----------------------------------------------------------------------------
/**
* Filter the specified effect with the provided function, failing with specified
* `MicroCause` if the predicate fails.
*
* In addition to the filtering capabilities discussed earlier, you have the option to further
* refine and narrow down the type of the success channel by providing a
*
* @since 3.4.0
* @experimental
* @category filtering & conditionals
*/
const filterOrFailCause = exports.filterOrFailCause = /*#__PURE__*/(0, _Function.dual)(args => isMicro(args[0]), (self, refinement, orFailWith) => flatMap(self, a => refinement(a) ? succeed(a) : failCause(orFailWith(a))));
/**
* Filter the specified effect with the provided function, failing with specified
* error if the predicate fails.
*
* In addition to the filtering capabilities discussed earlier, you have the option to further
* refine and narrow down the type of the success channel by providing a
*
* @since 3.4.0
* @experimental
* @category filtering & conditionals
*/
const filterOrFail = exports.filterOrFail = /*#__PURE__*/(0, _Function.dual)(args => isMicro(args[0]), (self, refinement, orFailWith) => flatMap(self, a => refinement(a) ? succeed(a) : fail(orFailWith(a))));
/**
* The moral equivalent of `if (p) exp`.
*
* @since 3.4.0
* @experimental
* @category filtering & conditionals
*/
const when = exports.when = /*#__PURE__*/(0, _Function.dual)(2, (self, condition) => flatMap(isMicro(condition) ? condition : sync(condition), pass => pass ? asSome(self) : succeedNone));
// ----------------------------------------------------------------------------
// repetition
// ----------------------------------------------------------------------------
/**
* Repeat the given `Micro` using the provided options.
*
* The `while` predicate will be checked after each iteration, and can use the
* fall `MicroExit` of the effect to determine if the repetition should continue.
*
* @since 3.4.6
* @experimental
* @category repetition
*/
const repeatExit = exports.repeatExit = /*#__PURE__*/(0, _Function.dual)(2, (self, options) => suspend(() => {
const startedAt = options.schedule ? Date.now() : 0;
let attempt = 0;
const loop = flatMap(exit(self), exit => {
if (options.while !== undefined && !options.while(exit)) {
return exit;
} else if (options.times !== undefined && attempt >= options.times) {
return exit;
}
attempt++;
let delayEffect = yieldNow;
if (options.schedule !== undefined) {
const elapsed = Date.now() - startedAt;
const duration = options.schedule(attempt, elapsed);
if (Option.isNone(duration)) {
return exit;
}
delayEffect = sleep(duration.value);
}
return flatMap(delayEffect, () => loop);
});
return loop;
}));
/**
* Repeat the given `Micro` effect using the provided options. Only successful
* results will be repeated.
*
* @since 3.4.0
* @experimental
* @category repetition
*/
const repeat = exports.repeat = /*#__PURE__*/(0, _Function.dual)(args => isMicro(args[0]), (self, options) => repeatExit(self, {
...options,
while: exit => exit._tag === "Success" && (options?.while === undefined || options.while(exit.value))
}));
/**
* Replicates the given effect `n` times.
*
* @since 3.11.0
* @experimental
* @category repetition
*/
const replicate = exports.replicate = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => Array.from({
length: n
}, () => self));
/**
* Performs this effect the specified number of times and collects the
* results.
*
* @since 3.11.0
* @category repetition
*/
const replicateEffect = exports.replicateEffect = /*#__PURE__*/(0, _Function.dual)(args => isMicro(args[0]), (self, n, options) => all(replicate(self, n), options));
/**
* Repeat the given `Micro` effect forever, only stopping if the effect fails.
*
* @since 3.4.0
* @experimental
* @category repetition
*/
const forever = self => repeat(self);
/**
* Create a `MicroSchedule` that will stop repeating after the specified number
* of attempts.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
exports.forever = forever;
const scheduleRecurs = n => attempt => attempt <= n ? Option.some(0) : Option.none();
/**
* Create a `MicroSchedule` that will generate a constant delay.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
exports.scheduleRecurs = scheduleRecurs;
const scheduleSpaced = millis => () => Option.some(millis);
/**
* Create a `MicroSchedule` that will generate a delay with an exponential backoff.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
exports.scheduleSpaced = scheduleSpaced;
const scheduleExponential = (baseMillis, factor = 2) => attempt => Option.some(Math.pow(factor, attempt) * baseMillis);
/**
* Returns a new `MicroSchedule` with an added calculated delay to each delay
* returned by this schedule.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
exports.scheduleExponential = scheduleExponential;
const scheduleAddDelay = exports.scheduleAddDelay = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => (attempt, elapsed) => Option.map(self(attempt, elapsed), duration => duration + f()));
/**
* Transform a `MicroSchedule` to one that will have a delay that will never exceed
* the specified maximum.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
const scheduleWithMaxDelay = exports.scheduleWithMaxDelay = /*#__PURE__*/(0, _Function.dual)(2, (self, max) => (attempt, elapsed) => Option.map(self(attempt, elapsed), duration => Math.min(duration, max)));
/**
* Transform a `MicroSchedule` to one that will stop repeating after the specified
* amount of time.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
const scheduleWithMaxElapsed = exports.scheduleWithMaxElapsed = /*#__PURE__*/(0, _Function.dual)(2, (self, max) => (attempt, elapsed) => elapsed < max ? self(attempt, elapsed) : Option.none());
/**
* Combines two `MicroSchedule`s, by recurring if either schedule wants to
* recur, using the minimum of the two durations between recurrences.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
const scheduleUnion = exports.scheduleUnion = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => (attempt, elapsed) => Option.zipWith(self(attempt, elapsed), that(attempt, elapsed), (d1, d2) => Math.min(d1, d2)));
/**
* Combines two `MicroSchedule`s, by recurring only if both schedules want to
* recur, using the maximum of the two durations between recurrences.
*
* @since 3.4.6
* @experimental
* @category scheduling
*/
const scheduleIntersect = exports.scheduleIntersect = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => (attempt, elapsed) => Option.zipWith(self(attempt, elapsed), that(attempt, elapsed), (d1, d2) => Math.max(d1, d2)));
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
/**
* Catch the full `MicroCause` object of the given `Micro` effect, allowing you to
* recover from any kind of cause.
*
* @since 3.4.6
* @experimental
* @category error handling
*/
const catchAllCause = exports.catchAllCause = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => {
const onFailure = Object.create(OnFailureProto);
onFailure[args] = self;
onFailure[failureCont] = f;
return onFailure;
});
const OnFailureProto = /*#__PURE__*/makePrimitiveProto({
op: "OnFailure",
eval(fiber) {
fiber._stack.push(this);
return this[args];
}
});
/**
* Selectively catch a `MicroCause` object of the given `Micro` effect,
* using the provided predicate to determine if the failure should be caught.
*
* @since 3.4.6
* @experimental
* @category error handling
*/
const catchCauseIf = exports.catchCauseIf = /*#__PURE__*/(0, _Function.dual)(3, (self, predicate, f) => catchAllCause(self, cause => predicate(cause) ? f(cause) : failCause(cause)));
/**
* Catch the error of the given `Micro` effect, allowing you to recover from it.
*
* It only catches expected errors.
*
* @since 3.4.6
* @experimental
* @category error handling
*/
const catchAll = exports.catchAll = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => catchCauseIf(self, causeIsFail, cause => f(cause.error)));
/**
* Catch any unexpected errors of the given `Micro` effec