effect 3.10.19 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/BigDecimal.js +125 -24
- package/dist/cjs/BigDecimal.js.map +1 -1
- package/dist/cjs/Channel.js +44 -4
- package/dist/cjs/Channel.js.map +1 -1
- package/dist/cjs/Config.js +8 -1
- package/dist/cjs/Config.js.map +1 -1
- package/dist/cjs/Context.js +26 -1
- package/dist/cjs/Context.js.map +1 -1
- package/dist/cjs/Cron.js +75 -67
- package/dist/cjs/Cron.js.map +1 -1
- package/dist/cjs/DateTime.js +114 -664
- package/dist/cjs/DateTime.js.map +1 -1
- package/dist/cjs/Effect.js +82 -4
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/Inspectable.js +8 -4
- package/dist/cjs/Inspectable.js.map +1 -1
- package/dist/cjs/JSONSchema.js.map +1 -1
- package/dist/cjs/Micro.js +1099 -1072
- package/dist/cjs/Micro.js.map +1 -1
- package/dist/cjs/STM.js.map +1 -1
- package/dist/cjs/Schema.js +57 -8
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/cjs/Sink.js +9 -1
- package/dist/cjs/Sink.js.map +1 -1
- package/dist/cjs/Stream.js +25 -7
- package/dist/cjs/Stream.js.map +1 -1
- package/dist/cjs/Utils.js +7 -1
- package/dist/cjs/Utils.js.map +1 -1
- package/dist/cjs/internal/channel/channelExecutor.js +5 -9
- package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
- package/dist/cjs/internal/channel.js +156 -130
- package/dist/cjs/internal/channel.js.map +1 -1
- package/dist/cjs/internal/config.js +13 -4
- package/dist/cjs/internal/config.js.map +1 -1
- package/dist/cjs/internal/context.js +46 -3
- package/dist/cjs/internal/context.js.map +1 -1
- package/dist/cjs/internal/dateTime.js +747 -0
- package/dist/cjs/internal/dateTime.js.map +1 -0
- package/dist/cjs/internal/fiberRuntime.js +34 -11
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/groupBy.js +9 -3
- package/dist/cjs/internal/groupBy.js.map +1 -1
- package/dist/cjs/internal/layer.js +1 -1
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/mailbox.js +1 -1
- package/dist/cjs/internal/mailbox.js.map +1 -1
- package/dist/cjs/internal/sink.js +25 -21
- package/dist/cjs/internal/sink.js.map +1 -1
- package/dist/cjs/internal/stream.js +70 -71
- package/dist/cjs/internal/stream.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/cjs/internal/version.js.map +1 -1
- package/dist/dts/BigDecimal.d.ts +56 -1
- package/dist/dts/BigDecimal.d.ts.map +1 -1
- package/dist/dts/Channel.d.ts +66 -5
- package/dist/dts/Channel.d.ts.map +1 -1
- package/dist/dts/Config.d.ts +23 -1
- package/dist/dts/Config.d.ts.map +1 -1
- package/dist/dts/Context.d.ts +111 -0
- package/dist/dts/Context.d.ts.map +1 -1
- package/dist/dts/Cron.d.ts +15 -6
- package/dist/dts/Cron.d.ts.map +1 -1
- package/dist/dts/DateTime.d.ts +40 -49
- package/dist/dts/DateTime.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +88 -1
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/Inspectable.d.ts.map +1 -1
- package/dist/dts/JSONSchema.d.ts +1 -0
- package/dist/dts/JSONSchema.d.ts.map +1 -1
- package/dist/dts/Micro.d.ts +875 -872
- package/dist/dts/Micro.d.ts.map +1 -1
- package/dist/dts/STM.d.ts +2 -0
- package/dist/dts/STM.d.ts.map +1 -1
- package/dist/dts/Schema.d.ts +32 -0
- package/dist/dts/Schema.d.ts.map +1 -1
- package/dist/dts/Sink.d.ts +8 -0
- package/dist/dts/Sink.d.ts.map +1 -1
- package/dist/dts/Stream.d.ts +50 -32
- package/dist/dts/Stream.d.ts.map +1 -1
- package/dist/dts/Utils.d.ts +4 -0
- package/dist/dts/Utils.d.ts.map +1 -1
- package/dist/dts/internal/context.d.ts +1 -1
- package/dist/dts/internal/context.d.ts.map +1 -1
- package/dist/dts/internal/dateTime.d.ts +2 -0
- package/dist/dts/internal/dateTime.d.ts.map +1 -0
- package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
- package/dist/dts/internal/stream.d.ts.map +1 -1
- package/dist/esm/BigDecimal.js +119 -20
- package/dist/esm/BigDecimal.js.map +1 -1
- package/dist/esm/Channel.js +42 -2
- package/dist/esm/Channel.js.map +1 -1
- package/dist/esm/Config.js +7 -0
- package/dist/esm/Config.js.map +1 -1
- package/dist/esm/Context.js +25 -0
- package/dist/esm/Context.js.map +1 -1
- package/dist/esm/Cron.js +75 -67
- package/dist/esm/Cron.js.map +1 -1
- package/dist/esm/DateTime.js +112 -627
- package/dist/esm/DateTime.js.map +1 -1
- package/dist/esm/Effect.js +77 -0
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/Inspectable.js +8 -4
- package/dist/esm/Inspectable.js.map +1 -1
- package/dist/esm/JSONSchema.js.map +1 -1
- package/dist/esm/Micro.js +1077 -1047
- package/dist/esm/Micro.js.map +1 -1
- package/dist/esm/STM.js.map +1 -1
- package/dist/esm/Schema.js +54 -0
- package/dist/esm/Schema.js.map +1 -1
- package/dist/esm/Sink.js +8 -0
- package/dist/esm/Sink.js.map +1 -1
- package/dist/esm/Stream.js +23 -5
- package/dist/esm/Stream.js.map +1 -1
- package/dist/esm/Utils.js +5 -0
- package/dist/esm/Utils.js.map +1 -1
- package/dist/esm/internal/channel/channelExecutor.js +5 -7
- package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
- package/dist/esm/internal/channel.js +152 -129
- package/dist/esm/internal/channel.js.map +1 -1
- package/dist/esm/internal/config.js +11 -3
- package/dist/esm/internal/config.js.map +1 -1
- package/dist/esm/internal/context.js +42 -2
- package/dist/esm/internal/context.js.map +1 -1
- package/dist/esm/internal/dateTime.js +704 -0
- package/dist/esm/internal/dateTime.js.map +1 -0
- package/dist/esm/internal/fiberRuntime.js +31 -9
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/groupBy.js +9 -3
- package/dist/esm/internal/groupBy.js.map +1 -1
- package/dist/esm/internal/layer.js +1 -1
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/mailbox.js +1 -1
- package/dist/esm/internal/mailbox.js.map +1 -1
- package/dist/esm/internal/sink.js +23 -20
- package/dist/esm/internal/sink.js.map +1 -1
- package/dist/esm/internal/stream.js +66 -69
- package/dist/esm/internal/stream.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/dist/esm/internal/version.js.map +1 -1
- package/package.json +1 -1
- package/src/BigDecimal.ts +131 -21
- package/src/Channel.ts +81 -5
- package/src/Config.ts +24 -1
- package/src/Context.ts +119 -0
- package/src/Cron.ts +85 -68
- package/src/DateTime.ts +155 -757
- package/src/Effect.ts +340 -1
- package/src/Inspectable.ts +11 -7
- package/src/JSONSchema.ts +1 -0
- package/src/Micro.ts +2005 -1757
- package/src/STM.ts +2 -0
- package/src/Schema.ts +60 -0
- package/src/Sink.ts +11 -0
- package/src/Stream.ts +55 -44
- package/src/Utils.ts +8 -0
- package/src/internal/channel/channelExecutor.ts +37 -33
- package/src/internal/channel.ts +504 -467
- package/src/internal/config.ts +18 -6
- package/src/internal/context.ts +56 -4
- package/src/internal/dateTime.ts +1126 -0
- package/src/internal/fiberRuntime.ts +35 -16
- package/src/internal/groupBy.ts +13 -22
- package/src/internal/layer.ts +5 -8
- package/src/internal/mailbox.ts +6 -4
- package/src/internal/sink.ts +55 -35
- package/src/internal/stream.ts +299 -299
- package/src/internal/version.ts +1 -1
package/dist/esm/Micro.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A lightweight alternative to the `Effect` data type, with a subset of the functionality.
|
|
3
|
+
*
|
|
4
|
+
* @since 3.4.0
|
|
5
|
+
* @experimental
|
|
6
|
+
*/
|
|
7
|
+
import * as Arr from "effect/Array";
|
|
1
8
|
import * as Context from "./Context.js";
|
|
2
9
|
import * as Effectable from "./Effectable.js";
|
|
3
10
|
import * as Either from "./Either.js";
|
|
11
|
+
import * as Equal from "./Equal.js";
|
|
4
12
|
import { constTrue, constVoid, dual, identity } from "./Function.js";
|
|
5
13
|
import { globalValue } from "./GlobalValue.js";
|
|
6
|
-
import
|
|
14
|
+
import * as Hash from "./Hash.js";
|
|
15
|
+
import { format, NodeInspectSymbol, toStringUnknown } from "./Inspectable.js";
|
|
16
|
+
import * as InternalContext from "./internal/context.js";
|
|
7
17
|
import * as doNotation from "./internal/doNotation.js";
|
|
8
18
|
import { StructuralPrototype } from "./internal/effectable.js";
|
|
9
|
-
import { SingleShotGen } from "./internal/singleShotGen.js";
|
|
10
19
|
import * as Option from "./Option.js";
|
|
11
20
|
import { pipeArguments } from "./Pipeable.js";
|
|
12
21
|
import { hasProperty, isIterable, isTagged } from "./Predicate.js";
|
|
13
|
-
import { YieldWrap, yieldWrapGet } from "./Utils.js";
|
|
22
|
+
import { SingleShotGen, YieldWrap, yieldWrapGet } from "./Utils.js";
|
|
14
23
|
/**
|
|
15
24
|
* @since 3.4.0
|
|
16
25
|
* @experimental
|
|
@@ -20,9 +29,9 @@ export const TypeId = /*#__PURE__*/Symbol.for("effect/Micro");
|
|
|
20
29
|
/**
|
|
21
30
|
* @since 3.4.0
|
|
22
31
|
* @experimental
|
|
23
|
-
* @category
|
|
32
|
+
* @category MicroExit
|
|
24
33
|
*/
|
|
25
|
-
export const
|
|
34
|
+
export const MicroExitTypeId = /*#__PURE__*/Symbol.for("effect/Micro/MicroExit");
|
|
26
35
|
/**
|
|
27
36
|
* @since 3.4.0
|
|
28
37
|
* @experimental
|
|
@@ -30,40 +39,6 @@ export const runSymbol = /*#__PURE__*/Symbol.for("effect/Micro/runSymbol");
|
|
|
30
39
|
*/
|
|
31
40
|
export const isMicro = u => typeof u === "object" && u !== null && TypeId in u;
|
|
32
41
|
// ----------------------------------------------------------------------------
|
|
33
|
-
// Microable
|
|
34
|
-
// ----------------------------------------------------------------------------
|
|
35
|
-
const MicroProto = {
|
|
36
|
-
...Effectable.EffectPrototype,
|
|
37
|
-
_op: "Micro",
|
|
38
|
-
[TypeId]: {
|
|
39
|
-
_A: identity,
|
|
40
|
-
_E: identity,
|
|
41
|
-
_R: identity
|
|
42
|
-
},
|
|
43
|
-
[Symbol.iterator]() {
|
|
44
|
-
return new SingleShotGen(new YieldWrap(this));
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
const MicroBase = /*#__PURE__*/function () {
|
|
48
|
-
function Base() {}
|
|
49
|
-
Base.prototype = MicroProto;
|
|
50
|
-
return Base;
|
|
51
|
-
}();
|
|
52
|
-
/**
|
|
53
|
-
* @since 3.8.4
|
|
54
|
-
* @experimental
|
|
55
|
-
* @category constructors
|
|
56
|
-
*/
|
|
57
|
-
export class Class extends MicroBase {
|
|
58
|
-
/**
|
|
59
|
-
* @since 3.8.4
|
|
60
|
-
* @experimental
|
|
61
|
-
*/
|
|
62
|
-
[runSymbol](env, onExit) {
|
|
63
|
-
this.asMicro()[runSymbol](env, onExit);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// ----------------------------------------------------------------------------
|
|
67
42
|
// MicroCause
|
|
68
43
|
// ----------------------------------------------------------------------------
|
|
69
44
|
/**
|
|
@@ -197,976 +172,1102 @@ export const causeWithTrace = /*#__PURE__*/dual(2, (self, trace) => {
|
|
|
197
172
|
return causeFail(self.error, traces);
|
|
198
173
|
}
|
|
199
174
|
});
|
|
175
|
+
// ----------------------------------------------------------------------------
|
|
176
|
+
// Fiber
|
|
177
|
+
// ----------------------------------------------------------------------------
|
|
200
178
|
/**
|
|
201
|
-
* @since 3.
|
|
202
|
-
* @experimental
|
|
203
|
-
* @category MicroExit
|
|
204
|
-
*/
|
|
205
|
-
export const exitInterrupt = /*#__PURE__*/Either.left( /*#__PURE__*/causeInterrupt());
|
|
206
|
-
/**
|
|
207
|
-
* @since 3.4.6
|
|
208
|
-
* @experimental
|
|
209
|
-
* @category MicroExit
|
|
210
|
-
*/
|
|
211
|
-
export const exitSucceed = Either.right;
|
|
212
|
-
/**
|
|
213
|
-
* @since 3.4.6
|
|
214
|
-
* @experimental
|
|
215
|
-
* @category MicroExit
|
|
216
|
-
*/
|
|
217
|
-
export const exitFail = e => Either.left(causeFail(e));
|
|
218
|
-
/**
|
|
219
|
-
* @since 3.4.6
|
|
220
|
-
* @experimental
|
|
221
|
-
* @category MicroExit
|
|
222
|
-
*/
|
|
223
|
-
export const exitDie = defect => Either.left(causeDie(defect));
|
|
224
|
-
/**
|
|
225
|
-
* @since 3.4.6
|
|
179
|
+
* @since 3.11.0
|
|
226
180
|
* @experimental
|
|
227
|
-
* @category
|
|
181
|
+
* @category Fiber
|
|
228
182
|
*/
|
|
229
|
-
export const
|
|
183
|
+
export const FiberTypeId = /*#__PURE__*/Symbol.for("effect/Micro/Fiber");
|
|
184
|
+
const fiberVariance = {
|
|
185
|
+
_A: identity,
|
|
186
|
+
_E: identity
|
|
187
|
+
};
|
|
188
|
+
class FiberImpl {
|
|
189
|
+
context;
|
|
190
|
+
interruptible;
|
|
191
|
+
[FiberTypeId];
|
|
192
|
+
_stack = [];
|
|
193
|
+
_observers = [];
|
|
194
|
+
_exit;
|
|
195
|
+
_children;
|
|
196
|
+
currentOpCount = 0;
|
|
197
|
+
constructor(context, interruptible = true) {
|
|
198
|
+
this.context = context;
|
|
199
|
+
this.interruptible = interruptible;
|
|
200
|
+
this[FiberTypeId] = fiberVariance;
|
|
201
|
+
}
|
|
202
|
+
getRef(ref) {
|
|
203
|
+
return InternalContext.unsafeGetReference(this.context, ref);
|
|
204
|
+
}
|
|
205
|
+
addObserver(cb) {
|
|
206
|
+
if (this._exit) {
|
|
207
|
+
cb(this._exit);
|
|
208
|
+
return constVoid;
|
|
209
|
+
}
|
|
210
|
+
this._observers.push(cb);
|
|
211
|
+
return () => {
|
|
212
|
+
const index = this._observers.indexOf(cb);
|
|
213
|
+
if (index >= 0) {
|
|
214
|
+
this._observers.splice(index, 1);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
_interrupted = false;
|
|
219
|
+
unsafeInterrupt() {
|
|
220
|
+
if (this._exit) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
this._interrupted = true;
|
|
224
|
+
if (this.interruptible) {
|
|
225
|
+
this.evaluate(exitInterrupt);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
unsafePoll() {
|
|
229
|
+
return this._exit;
|
|
230
|
+
}
|
|
231
|
+
evaluate(effect) {
|
|
232
|
+
if (this._exit) {
|
|
233
|
+
return;
|
|
234
|
+
} else if (this._yielded !== undefined) {
|
|
235
|
+
const yielded = this._yielded;
|
|
236
|
+
this._yielded = undefined;
|
|
237
|
+
yielded();
|
|
238
|
+
}
|
|
239
|
+
const exit = this.runLoop(effect);
|
|
240
|
+
if (exit === Yield) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// the interruptChildren middlware is added in Micro.fork, so it can be
|
|
244
|
+
// tree-shaken if not used
|
|
245
|
+
const interruptChildren = fiberMiddleware.interruptChildren && fiberMiddleware.interruptChildren(this);
|
|
246
|
+
if (interruptChildren !== undefined) {
|
|
247
|
+
return this.evaluate(flatMap(interruptChildren, () => exit));
|
|
248
|
+
}
|
|
249
|
+
this._exit = exit;
|
|
250
|
+
for (let i = 0; i < this._observers.length; i++) {
|
|
251
|
+
this._observers[i](exit);
|
|
252
|
+
}
|
|
253
|
+
this._observers.length = 0;
|
|
254
|
+
}
|
|
255
|
+
runLoop(effect) {
|
|
256
|
+
let yielding = false;
|
|
257
|
+
let current = effect;
|
|
258
|
+
this.currentOpCount = 0;
|
|
259
|
+
try {
|
|
260
|
+
while (true) {
|
|
261
|
+
this.currentOpCount++;
|
|
262
|
+
if (!yielding && this.getRef(CurrentScheduler).shouldYield(this)) {
|
|
263
|
+
yielding = true;
|
|
264
|
+
const prev = current;
|
|
265
|
+
current = flatMap(yieldNow, () => prev);
|
|
266
|
+
}
|
|
267
|
+
current = current[evaluate](this);
|
|
268
|
+
if (current === Yield) {
|
|
269
|
+
const yielded = this._yielded;
|
|
270
|
+
if (MicroExitTypeId in yielded) {
|
|
271
|
+
this._yielded = undefined;
|
|
272
|
+
return yielded;
|
|
273
|
+
}
|
|
274
|
+
return Yield;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
if (!hasProperty(current, evaluate)) {
|
|
279
|
+
return exitDie(`Micro/Fiber.runLoop: Not a valid effect: ${String(current)}`);
|
|
280
|
+
}
|
|
281
|
+
return exitDie(error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
getCont(symbol) {
|
|
285
|
+
while (true) {
|
|
286
|
+
const op = this._stack.pop();
|
|
287
|
+
if (!op) return undefined;
|
|
288
|
+
const cont = op[ensureCont] && op[ensureCont](this);
|
|
289
|
+
if (cont) return {
|
|
290
|
+
[symbol]: cont
|
|
291
|
+
};
|
|
292
|
+
if (op[symbol]) return op;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// cancel the yielded operation, or for the yielded exit value
|
|
296
|
+
_yielded = undefined;
|
|
297
|
+
yieldWith(value) {
|
|
298
|
+
this._yielded = value;
|
|
299
|
+
return Yield;
|
|
300
|
+
}
|
|
301
|
+
children() {
|
|
302
|
+
return this._children ??= new Set();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const fiberMiddleware = /*#__PURE__*/globalValue("effect/Micro/fiberMiddleware", () => ({
|
|
306
|
+
interruptChildren: undefined
|
|
307
|
+
}));
|
|
308
|
+
const fiberInterruptChildren = fiber => {
|
|
309
|
+
if (fiber._children === undefined || fiber._children.size === 0) {
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
return fiberInterruptAll(fiber._children);
|
|
313
|
+
};
|
|
230
314
|
/**
|
|
231
|
-
* @since 3.
|
|
315
|
+
* @since 3.11.0
|
|
232
316
|
* @experimental
|
|
233
|
-
* @category
|
|
317
|
+
* @category Fiber
|
|
234
318
|
*/
|
|
235
|
-
export const
|
|
319
|
+
export const fiberAwait = self => async(resume => sync(self.addObserver(exit => resume(succeed(exit)))));
|
|
236
320
|
/**
|
|
237
|
-
* @since 3.
|
|
321
|
+
* @since 3.11.0
|
|
238
322
|
* @experimental
|
|
239
|
-
* @category
|
|
323
|
+
* @category Fiber
|
|
240
324
|
*/
|
|
241
|
-
export const
|
|
325
|
+
export const fiberInterrupt = self => suspend(() => {
|
|
326
|
+
self.unsafeInterrupt();
|
|
327
|
+
return asVoid(fiberAwait(self));
|
|
328
|
+
});
|
|
242
329
|
/**
|
|
243
|
-
* @since 3.
|
|
330
|
+
* @since 3.11.0
|
|
244
331
|
* @experimental
|
|
245
|
-
* @category
|
|
332
|
+
* @category Fiber
|
|
246
333
|
*/
|
|
247
|
-
export const
|
|
334
|
+
export const fiberInterruptAll = fibers => suspend(() => {
|
|
335
|
+
for (const fiber of fibers) fiber.unsafeInterrupt();
|
|
336
|
+
const iter = fibers[Symbol.iterator]();
|
|
337
|
+
const wait = suspend(() => {
|
|
338
|
+
let result = iter.next();
|
|
339
|
+
while (!result.done) {
|
|
340
|
+
if (result.value.unsafePoll()) {
|
|
341
|
+
result = iter.next();
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const fiber = result.value;
|
|
345
|
+
return async(resume => {
|
|
346
|
+
fiber.addObserver(_ => {
|
|
347
|
+
resume(wait);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return exitVoid;
|
|
352
|
+
});
|
|
353
|
+
return wait;
|
|
354
|
+
});
|
|
355
|
+
const identifier = /*#__PURE__*/Symbol.for("effect/Micro/identifier");
|
|
356
|
+
const args = /*#__PURE__*/Symbol.for("effect/Micro/args");
|
|
357
|
+
const evaluate = /*#__PURE__*/Symbol.for("effect/Micro/evaluate");
|
|
358
|
+
const successCont = /*#__PURE__*/Symbol.for("effect/Micro/successCont");
|
|
359
|
+
const failureCont = /*#__PURE__*/Symbol.for("effect/Micro/failureCont");
|
|
360
|
+
const ensureCont = /*#__PURE__*/Symbol.for("effect/Micro/ensureCont");
|
|
361
|
+
const Yield = /*#__PURE__*/Symbol.for("effect/Micro/Yield");
|
|
362
|
+
const microVariance = {
|
|
363
|
+
_A: identity,
|
|
364
|
+
_E: identity,
|
|
365
|
+
_R: identity
|
|
366
|
+
};
|
|
367
|
+
const MicroProto = {
|
|
368
|
+
...Effectable.EffectPrototype,
|
|
369
|
+
_op: "Micro",
|
|
370
|
+
[TypeId]: microVariance,
|
|
371
|
+
pipe() {
|
|
372
|
+
return pipeArguments(this, arguments);
|
|
373
|
+
},
|
|
374
|
+
[Symbol.iterator]() {
|
|
375
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
376
|
+
},
|
|
377
|
+
toJSON() {
|
|
378
|
+
return {
|
|
379
|
+
_id: "effect/Micro",
|
|
380
|
+
op: this[identifier],
|
|
381
|
+
...(args in this ? {
|
|
382
|
+
args: this[args]
|
|
383
|
+
} : undefined)
|
|
384
|
+
};
|
|
385
|
+
},
|
|
386
|
+
toString() {
|
|
387
|
+
return format(this);
|
|
388
|
+
},
|
|
389
|
+
[NodeInspectSymbol]() {
|
|
390
|
+
return format(this);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
function defaultEvaluate(_fiber) {
|
|
394
|
+
return exitDie(`Micro.evaluate: Not implemented`);
|
|
395
|
+
}
|
|
396
|
+
const makePrimitiveProto = options => ({
|
|
397
|
+
...MicroProto,
|
|
398
|
+
[identifier]: options.op,
|
|
399
|
+
[evaluate]: options.eval ?? defaultEvaluate,
|
|
400
|
+
[successCont]: options.contA,
|
|
401
|
+
[failureCont]: options.contE,
|
|
402
|
+
[ensureCont]: options.ensure
|
|
403
|
+
});
|
|
404
|
+
const makePrimitive = options => {
|
|
405
|
+
const Proto = makePrimitiveProto(options);
|
|
406
|
+
return function () {
|
|
407
|
+
const self = Object.create(Proto);
|
|
408
|
+
self[args] = options.single === false ? arguments : arguments[0];
|
|
409
|
+
return self;
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
const makeExit = options => {
|
|
413
|
+
const Proto = {
|
|
414
|
+
...makePrimitiveProto(options),
|
|
415
|
+
[MicroExitTypeId]: MicroExitTypeId,
|
|
416
|
+
_tag: options.op,
|
|
417
|
+
get [options.prop]() {
|
|
418
|
+
return this[args];
|
|
419
|
+
},
|
|
420
|
+
toJSON() {
|
|
421
|
+
return {
|
|
422
|
+
_id: "effect/Micro/Exit",
|
|
423
|
+
_tag: options.op,
|
|
424
|
+
[options.prop]: this[args]
|
|
425
|
+
};
|
|
426
|
+
},
|
|
427
|
+
[Equal.symbol](that) {
|
|
428
|
+
return isMicroExit(that) && that._tag === options.op && Equal.equals(this[args], that[args]);
|
|
429
|
+
},
|
|
430
|
+
[Hash.symbol]() {
|
|
431
|
+
return Hash.cached(this, Hash.combine(Hash.string(options.op))(Hash.hash(this[args])));
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
return function (value) {
|
|
435
|
+
const self = Object.create(Proto);
|
|
436
|
+
self[args] = value;
|
|
437
|
+
self[successCont] = undefined;
|
|
438
|
+
self[failureCont] = undefined;
|
|
439
|
+
self[ensureCont] = undefined;
|
|
440
|
+
return self;
|
|
441
|
+
};
|
|
442
|
+
};
|
|
248
443
|
/**
|
|
249
|
-
*
|
|
444
|
+
* Creates a `Micro` effect that will succeed with the specified constant value.
|
|
445
|
+
*
|
|
446
|
+
* @since 3.4.0
|
|
250
447
|
* @experimental
|
|
251
|
-
* @category
|
|
448
|
+
* @category constructors
|
|
252
449
|
*/
|
|
253
|
-
export const
|
|
450
|
+
export const succeed = /*#__PURE__*/makeExit({
|
|
451
|
+
op: "Success",
|
|
452
|
+
prop: "value",
|
|
453
|
+
eval(fiber) {
|
|
454
|
+
const cont = fiber.getCont(successCont);
|
|
455
|
+
return cont ? cont[successCont](this[args], fiber) : fiber.yieldWith(this);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
254
458
|
/**
|
|
459
|
+
* Creates a `Micro` effect that will fail with the specified `MicroCause`.
|
|
460
|
+
*
|
|
255
461
|
* @since 3.4.6
|
|
256
462
|
* @experimental
|
|
257
|
-
* @category
|
|
463
|
+
* @category constructors
|
|
258
464
|
*/
|
|
259
|
-
export const
|
|
465
|
+
export const failCause = /*#__PURE__*/makeExit({
|
|
466
|
+
op: "Failure",
|
|
467
|
+
prop: "cause",
|
|
468
|
+
eval(fiber) {
|
|
469
|
+
let cont = fiber.getCont(failureCont);
|
|
470
|
+
while (causeIsInterrupt(this[args]) && cont && fiber.interruptible) {
|
|
471
|
+
cont = fiber.getCont(failureCont);
|
|
472
|
+
}
|
|
473
|
+
return cont ? cont[failureCont](this[args], fiber) : fiber.yieldWith(this);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
260
476
|
/**
|
|
261
|
-
*
|
|
477
|
+
* Creates a `Micro` effect that will fail with the specified error.
|
|
478
|
+
*
|
|
479
|
+
* This will result in a `CauseFail`, where the error is tracked at the
|
|
480
|
+
* type level.
|
|
481
|
+
*
|
|
482
|
+
* @since 3.4.0
|
|
262
483
|
* @experimental
|
|
263
|
-
* @category
|
|
484
|
+
* @category constructors
|
|
264
485
|
*/
|
|
265
|
-
export const
|
|
266
|
-
// ----------------------------------------------------------------------------
|
|
267
|
-
// env
|
|
268
|
-
// ----------------------------------------------------------------------------
|
|
486
|
+
export const fail = error => failCause(causeFail(error));
|
|
269
487
|
/**
|
|
488
|
+
* Creates a `Micro` effect that will succeed with the lazily evaluated value.
|
|
489
|
+
*
|
|
490
|
+
* If the evaluation of the value throws an error, the effect will fail with
|
|
491
|
+
* `CauseDie`.
|
|
492
|
+
*
|
|
270
493
|
* @since 3.4.0
|
|
271
494
|
* @experimental
|
|
272
|
-
* @category
|
|
495
|
+
* @category constructors
|
|
273
496
|
*/
|
|
274
|
-
export const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return pipeArguments(this, arguments);
|
|
497
|
+
export const sync = /*#__PURE__*/makePrimitive({
|
|
498
|
+
op: "Sync",
|
|
499
|
+
eval(fiber) {
|
|
500
|
+
const value = this[args]();
|
|
501
|
+
const cont = fiber.getCont(successCont);
|
|
502
|
+
return cont ? cont[successCont](value, fiber) : fiber.yieldWith(exitSucceed(value));
|
|
281
503
|
}
|
|
282
|
-
};
|
|
504
|
+
});
|
|
283
505
|
/**
|
|
506
|
+
* Lazily creates a `Micro` effect from the given side-effect.
|
|
507
|
+
*
|
|
284
508
|
* @since 3.4.0
|
|
285
509
|
* @experimental
|
|
286
|
-
* @category
|
|
510
|
+
* @category constructors
|
|
287
511
|
*/
|
|
288
|
-
export const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
512
|
+
export const suspend = /*#__PURE__*/makePrimitive({
|
|
513
|
+
op: "Suspend",
|
|
514
|
+
eval(_fiber) {
|
|
515
|
+
return this[args]();
|
|
516
|
+
}
|
|
517
|
+
});
|
|
293
518
|
/**
|
|
519
|
+
* Pause the execution of the current `Micro` effect, and resume it on the next
|
|
520
|
+
* scheduler tick.
|
|
521
|
+
*
|
|
294
522
|
* @since 3.4.0
|
|
295
523
|
* @experimental
|
|
296
|
-
* @category
|
|
524
|
+
* @category constructors
|
|
297
525
|
*/
|
|
298
|
-
export const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
};
|
|
526
|
+
export const yieldNowWith = /*#__PURE__*/makePrimitive({
|
|
527
|
+
op: "Yield",
|
|
528
|
+
eval(fiber) {
|
|
529
|
+
let resumed = false;
|
|
530
|
+
fiber.getRef(CurrentScheduler).scheduleTask(() => {
|
|
531
|
+
if (resumed) return;
|
|
532
|
+
fiber.evaluate(exitVoid);
|
|
533
|
+
}, this[args] ?? 0);
|
|
534
|
+
return fiber.yieldWith(() => {
|
|
535
|
+
resumed = true;
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
});
|
|
306
539
|
/**
|
|
540
|
+
* Pause the execution of the current `Micro` effect, and resume it on the next
|
|
541
|
+
* scheduler tick.
|
|
542
|
+
*
|
|
307
543
|
* @since 3.4.0
|
|
308
544
|
* @experimental
|
|
309
|
-
* @category
|
|
545
|
+
* @category constructors
|
|
310
546
|
*/
|
|
311
|
-
export const
|
|
547
|
+
export const yieldNow = /*#__PURE__*/yieldNowWith(0);
|
|
312
548
|
/**
|
|
549
|
+
* Creates a `Micro` effect that will succeed with `Option.Some` of the value.
|
|
550
|
+
*
|
|
313
551
|
* @since 3.4.0
|
|
314
552
|
* @experimental
|
|
315
|
-
* @category
|
|
553
|
+
* @category constructors
|
|
316
554
|
*/
|
|
317
|
-
export const
|
|
318
|
-
const refs = Object.assign(Object.create(null), self.refs);
|
|
319
|
-
refs[ref.key] = value;
|
|
320
|
-
return envMake(refs);
|
|
321
|
-
});
|
|
555
|
+
export const succeedSome = a => succeed(Option.some(a));
|
|
322
556
|
/**
|
|
557
|
+
* Creates a `Micro` effect that will succeed with `Option.None`.
|
|
558
|
+
*
|
|
323
559
|
* @since 3.4.0
|
|
324
560
|
* @experimental
|
|
325
|
-
* @category
|
|
561
|
+
* @category constructors
|
|
326
562
|
*/
|
|
327
|
-
export const
|
|
563
|
+
export const succeedNone = /*#__PURE__*/succeed( /*#__PURE__*/Option.none());
|
|
328
564
|
/**
|
|
329
|
-
*
|
|
565
|
+
* Creates a `Micro` effect that will fail with the lazily evaluated `MicroCause`.
|
|
330
566
|
*
|
|
331
567
|
* @since 3.4.0
|
|
332
568
|
* @experimental
|
|
333
|
-
* @category
|
|
569
|
+
* @category constructors
|
|
334
570
|
*/
|
|
335
|
-
export const
|
|
336
|
-
onExit(exitSucceed(Context.get(envGet(env, currentContext), tag)));
|
|
337
|
-
});
|
|
571
|
+
export const failCauseSync = evaluate => suspend(() => failCause(evaluate()));
|
|
338
572
|
/**
|
|
339
|
-
*
|
|
340
|
-
* dependency at the type level.
|
|
573
|
+
* Creates a `Micro` effect that will die with the specified error.
|
|
341
574
|
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
575
|
+
* This will result in a `CauseDie`, where the error is not tracked at
|
|
576
|
+
* the type level.
|
|
344
577
|
*
|
|
345
578
|
* @since 3.4.0
|
|
346
579
|
* @experimental
|
|
347
|
-
* @category
|
|
580
|
+
* @category constructors
|
|
348
581
|
*/
|
|
349
|
-
export const
|
|
350
|
-
onExit(exitSucceed(Context.getOption(envGet(env, currentContext), tag)));
|
|
351
|
-
});
|
|
582
|
+
export const die = defect => exitDie(defect);
|
|
352
583
|
/**
|
|
353
|
-
*
|
|
584
|
+
* Creates a `Micro` effect that will fail with the lazily evaluated error.
|
|
354
585
|
*
|
|
355
|
-
*
|
|
586
|
+
* This will result in a `CauseFail`, where the error is tracked at the
|
|
587
|
+
* type level.
|
|
588
|
+
*
|
|
589
|
+
* @since 3.4.6
|
|
356
590
|
* @experimental
|
|
357
|
-
* @category
|
|
591
|
+
* @category constructors
|
|
358
592
|
*/
|
|
359
|
-
export const
|
|
593
|
+
export const failSync = error => suspend(() => fail(error()));
|
|
360
594
|
/**
|
|
361
|
-
*
|
|
595
|
+
* Converts an `Option` into a `Micro` effect, that will fail with
|
|
596
|
+
* `NoSuchElementException` if the option is `None`. Otherwise, it will succeed with the
|
|
597
|
+
* value of the option.
|
|
362
598
|
*
|
|
363
599
|
* @since 3.4.0
|
|
364
600
|
* @experimental
|
|
365
|
-
* @category
|
|
601
|
+
* @category constructors
|
|
366
602
|
*/
|
|
367
|
-
export const
|
|
603
|
+
export const fromOption = option => option._tag === "Some" ? succeed(option.value) : fail(new NoSuchElementException({}));
|
|
368
604
|
/**
|
|
369
|
-
*
|
|
605
|
+
* Converts an `Either` into a `Micro` effect, that will fail with the left side
|
|
606
|
+
* of the either if it is a `Left`. Otherwise, it will succeed with the right
|
|
607
|
+
* side of the either.
|
|
370
608
|
*
|
|
371
609
|
* @since 3.4.0
|
|
372
610
|
* @experimental
|
|
373
|
-
* @category
|
|
611
|
+
* @category constructors
|
|
374
612
|
*/
|
|
375
|
-
export const
|
|
613
|
+
export const fromEither = either => either._tag === "Right" ? succeed(either.right) : fail(either.left);
|
|
614
|
+
const void_ = /*#__PURE__*/succeed(void 0);
|
|
615
|
+
export {
|
|
376
616
|
/**
|
|
377
|
-
*
|
|
617
|
+
* A `Micro` effect that will succeed with `void` (`undefined`).
|
|
378
618
|
*
|
|
379
619
|
* @since 3.4.0
|
|
380
620
|
* @experimental
|
|
381
|
-
* @category
|
|
621
|
+
* @category constructors
|
|
382
622
|
*/
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
})
|
|
623
|
+
void_ as void };
|
|
624
|
+
const try_ = options => suspend(() => {
|
|
625
|
+
try {
|
|
626
|
+
return succeed(options.try());
|
|
627
|
+
} catch (err) {
|
|
628
|
+
return fail(options.catch(err));
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
export {
|
|
388
632
|
/**
|
|
389
|
-
*
|
|
633
|
+
* The `Micro` equivalent of a try / catch block, which allows you to map
|
|
634
|
+
* thrown errors to a specific error type.
|
|
390
635
|
*
|
|
391
636
|
* @since 3.4.0
|
|
392
637
|
* @experimental
|
|
393
|
-
* @category
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
638
|
+
* @category constructors
|
|
639
|
+
* @example
|
|
640
|
+
* ```ts
|
|
641
|
+
* import { Micro } from "effect"
|
|
642
|
+
*
|
|
643
|
+
* Micro.try({
|
|
644
|
+
* try: () => throw new Error("boom"),
|
|
645
|
+
* catch: (cause) => new Error("caught", { cause })
|
|
646
|
+
* })
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
try_ as try };
|
|
400
650
|
/**
|
|
401
|
-
*
|
|
402
|
-
*
|
|
651
|
+
* Wrap a `Promise` into a `Micro` effect. Any errors will result in a
|
|
652
|
+
* `CauseDie`.
|
|
403
653
|
*
|
|
404
|
-
* @since 3.4.
|
|
654
|
+
* @since 3.4.0
|
|
405
655
|
* @experimental
|
|
406
|
-
* @category
|
|
656
|
+
* @category constructors
|
|
407
657
|
*/
|
|
408
|
-
export const
|
|
409
|
-
|
|
658
|
+
export const promise = evaluate => asyncOptions(function (resume, signal) {
|
|
659
|
+
evaluate(signal).then(a => resume(succeed(a)), e => resume(die(e)));
|
|
660
|
+
}, evaluate.length !== 0);
|
|
410
661
|
/**
|
|
411
|
-
*
|
|
662
|
+
* Wrap a `Promise` into a `Micro` effect. Any errors will be caught and
|
|
663
|
+
* converted into a specific error type.
|
|
664
|
+
*
|
|
665
|
+
* @since 3.4.0
|
|
412
666
|
* @experimental
|
|
413
|
-
* @category
|
|
667
|
+
* @category constructors
|
|
668
|
+
* @example
|
|
669
|
+
* ```ts
|
|
670
|
+
* import { Micro } from "effect"
|
|
671
|
+
*
|
|
672
|
+
* Micro.tryPromise({
|
|
673
|
+
* try: () => Promise.resolve("success"),
|
|
674
|
+
* catch: (cause) => new Error("caught", { cause })
|
|
675
|
+
* })
|
|
676
|
+
* ```
|
|
414
677
|
*/
|
|
415
|
-
export
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
*/
|
|
421
|
-
scheduleTask(task, _priority) {
|
|
422
|
-
this.tasks.push(task);
|
|
423
|
-
if (!this.running) {
|
|
424
|
-
this.running = true;
|
|
425
|
-
setImmediate(this.afterScheduled);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* @since 3.5.9
|
|
430
|
-
*/
|
|
431
|
-
afterScheduled = () => {
|
|
432
|
-
this.running = false;
|
|
433
|
-
this.runTasks();
|
|
434
|
-
};
|
|
435
|
-
/**
|
|
436
|
-
* @since 3.5.9
|
|
437
|
-
*/
|
|
438
|
-
runTasks() {
|
|
439
|
-
const tasks = this.tasks;
|
|
440
|
-
this.tasks = [];
|
|
441
|
-
for (let i = 0, len = tasks.length; i < len; i++) {
|
|
442
|
-
tasks[i]();
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* @since 3.5.9
|
|
447
|
-
*/
|
|
448
|
-
shouldYield(_env) {
|
|
449
|
-
return false;
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* @since 3.5.9
|
|
453
|
-
*/
|
|
454
|
-
flush() {
|
|
455
|
-
while (this.tasks.length > 0) {
|
|
456
|
-
this.runTasks();
|
|
457
|
-
}
|
|
678
|
+
export const tryPromise = options => asyncOptions(function (resume, signal) {
|
|
679
|
+
try {
|
|
680
|
+
options.try(signal).then(a => resume(succeed(a)), e => resume(fail(options.catch(e))));
|
|
681
|
+
} catch (err) {
|
|
682
|
+
resume(fail(options.catch(err)));
|
|
458
683
|
}
|
|
459
|
-
}
|
|
460
|
-
// ========================================================================
|
|
461
|
-
// Env refs
|
|
462
|
-
// ========================================================================
|
|
684
|
+
}, options.try.length !== 0);
|
|
463
685
|
/**
|
|
686
|
+
* Create a `Micro` effect using the current `Fiber`.
|
|
687
|
+
*
|
|
464
688
|
* @since 3.4.0
|
|
465
689
|
* @experimental
|
|
466
|
-
* @category
|
|
690
|
+
* @category constructors
|
|
467
691
|
*/
|
|
468
|
-
export const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
[runSymbol](env, onExit) {
|
|
473
|
-
getEnvRef(this)[runSymbol](env, onExit);
|
|
692
|
+
export const withFiber = /*#__PURE__*/makePrimitive({
|
|
693
|
+
op: "WithFiber",
|
|
694
|
+
eval(fiber) {
|
|
695
|
+
return this[args](fiber);
|
|
474
696
|
}
|
|
475
|
-
};
|
|
697
|
+
});
|
|
476
698
|
/**
|
|
699
|
+
* Flush any yielded effects that are waiting to be executed.
|
|
700
|
+
*
|
|
477
701
|
* @since 3.4.0
|
|
478
702
|
* @experimental
|
|
479
|
-
* @category
|
|
703
|
+
* @category constructors
|
|
480
704
|
*/
|
|
481
|
-
export const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
705
|
+
export const yieldFlush = /*#__PURE__*/withFiber(fiber => {
|
|
706
|
+
fiber.getRef(CurrentScheduler).flush();
|
|
707
|
+
return exitVoid;
|
|
708
|
+
});
|
|
709
|
+
const asyncOptions = /*#__PURE__*/makePrimitive({
|
|
710
|
+
op: "Async",
|
|
711
|
+
single: false,
|
|
712
|
+
eval(fiber) {
|
|
713
|
+
const register = this[args][0];
|
|
714
|
+
let resumed = false;
|
|
715
|
+
let yielded = false;
|
|
716
|
+
const controller = this[args][1] ? new AbortController() : undefined;
|
|
717
|
+
const onCancel = register(effect => {
|
|
718
|
+
if (resumed) return;
|
|
719
|
+
resumed = true;
|
|
720
|
+
if (yielded) {
|
|
721
|
+
fiber.evaluate(effect);
|
|
722
|
+
} else {
|
|
723
|
+
yielded = effect;
|
|
724
|
+
}
|
|
725
|
+
}, controller?.signal);
|
|
726
|
+
if (yielded !== false) return yielded;
|
|
727
|
+
yielded = true;
|
|
728
|
+
fiber._yielded = () => {
|
|
729
|
+
resumed = true;
|
|
730
|
+
};
|
|
731
|
+
if (controller === undefined && onCancel === undefined) {
|
|
732
|
+
return Yield;
|
|
733
|
+
}
|
|
734
|
+
fiber._stack.push(asyncFinalizer(() => {
|
|
735
|
+
resumed = true;
|
|
736
|
+
controller?.abort();
|
|
737
|
+
return onCancel ?? exitVoid;
|
|
738
|
+
}));
|
|
739
|
+
return Yield;
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
const asyncFinalizer = /*#__PURE__*/makePrimitive({
|
|
743
|
+
op: "AsyncFinalizer",
|
|
744
|
+
ensure(fiber) {
|
|
745
|
+
if (fiber.interruptible) {
|
|
746
|
+
fiber.interruptible = false;
|
|
747
|
+
fiber._stack.push(setInterruptible(true));
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
contE(cause, _fiber) {
|
|
751
|
+
return causeIsInterrupt(cause) ? flatMap(this[args](), () => failCause(cause)) : failCause(cause);
|
|
752
|
+
}
|
|
486
753
|
});
|
|
487
754
|
/**
|
|
755
|
+
* Create a `Micro` effect from an asynchronous computation.
|
|
756
|
+
*
|
|
757
|
+
* You can return a cleanup effect that will be run when the effect is aborted.
|
|
758
|
+
* It is also passed an `AbortSignal` that is triggered when the effect is
|
|
759
|
+
* aborted.
|
|
760
|
+
*
|
|
488
761
|
* @since 3.4.0
|
|
489
762
|
* @experimental
|
|
490
|
-
* @category
|
|
763
|
+
* @category constructors
|
|
491
764
|
*/
|
|
492
|
-
export const
|
|
765
|
+
export const async = register => asyncOptions(register, register.length >= 2);
|
|
493
766
|
/**
|
|
767
|
+
* A `Micro` that will never succeed or fail. It wraps `setInterval` to prevent
|
|
768
|
+
* the Javascript runtime from exiting.
|
|
769
|
+
*
|
|
494
770
|
* @since 3.4.0
|
|
495
771
|
* @experimental
|
|
496
|
-
* @category
|
|
772
|
+
* @category constructors
|
|
497
773
|
*/
|
|
498
|
-
export const
|
|
774
|
+
export const never = /*#__PURE__*/async(function () {
|
|
775
|
+
const interval = setInterval(constVoid, 2147483646);
|
|
776
|
+
return sync(() => clearInterval(interval));
|
|
777
|
+
});
|
|
499
778
|
/**
|
|
500
779
|
* @since 3.4.0
|
|
501
780
|
* @experimental
|
|
502
|
-
* @category
|
|
781
|
+
* @category constructors
|
|
503
782
|
*/
|
|
504
|
-
export const
|
|
783
|
+
export const gen = (...args) => suspend(() => fromIterator(args.length === 1 ? args[0]() : args[1].call(args[0])));
|
|
784
|
+
const fromIterator = /*#__PURE__*/makePrimitive({
|
|
785
|
+
op: "Iterator",
|
|
786
|
+
contA(value, fiber) {
|
|
787
|
+
const state = this[args].next(value);
|
|
788
|
+
if (state.done) return succeed(state.value);
|
|
789
|
+
fiber._stack.push(this);
|
|
790
|
+
return yieldWrapGet(state.value);
|
|
791
|
+
},
|
|
792
|
+
eval(fiber) {
|
|
793
|
+
return this[successCont](undefined, fiber);
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
// ----------------------------------------------------------------------------
|
|
797
|
+
// mapping & sequencing
|
|
798
|
+
// ----------------------------------------------------------------------------
|
|
505
799
|
/**
|
|
800
|
+
* Create a `Micro` effect that will replace the success value of the given
|
|
801
|
+
* effect.
|
|
802
|
+
*
|
|
506
803
|
* @since 3.4.0
|
|
507
804
|
* @experimental
|
|
508
|
-
* @category
|
|
805
|
+
* @category mapping & sequencing
|
|
509
806
|
*/
|
|
510
|
-
export const
|
|
807
|
+
export const as = /*#__PURE__*/dual(2, (self, value) => map(self, _ => value));
|
|
511
808
|
/**
|
|
809
|
+
* Wrap the success value of this `Micro` effect in an `Option.Some`.
|
|
810
|
+
*
|
|
512
811
|
* @since 3.4.0
|
|
513
812
|
* @experimental
|
|
514
|
-
* @category
|
|
813
|
+
* @category mapping & sequencing
|
|
515
814
|
*/
|
|
516
|
-
export const
|
|
517
|
-
const currentInterruptible = /*#__PURE__*/envRefMake("effect/Micro/currentInterruptible", () => true);
|
|
815
|
+
export const asSome = self => map(self, Option.some);
|
|
518
816
|
/**
|
|
817
|
+
* Swap the error and success types of the `Micro` effect.
|
|
818
|
+
*
|
|
519
819
|
* @since 3.4.0
|
|
520
820
|
* @experimental
|
|
521
|
-
* @category
|
|
821
|
+
* @category mapping & sequencing
|
|
522
822
|
*/
|
|
523
|
-
export const
|
|
823
|
+
export const flip = self => matchEffect(self, {
|
|
824
|
+
onFailure: succeed,
|
|
825
|
+
onSuccess: fail
|
|
826
|
+
});
|
|
524
827
|
/**
|
|
525
|
-
*
|
|
526
|
-
*
|
|
828
|
+
* A more flexible version of `flatMap`, that combines `map` and `flatMap` into
|
|
829
|
+
* a single api.
|
|
830
|
+
*
|
|
831
|
+
* It also allows you to pass in a `Micro` effect directly, which will be
|
|
832
|
+
* executed after the current effect.
|
|
527
833
|
*
|
|
528
834
|
* @since 3.4.0
|
|
529
835
|
* @experimental
|
|
530
|
-
* @category
|
|
531
|
-
* @example
|
|
532
|
-
* ```ts
|
|
533
|
-
* import * as Micro from "effect/Micro"
|
|
534
|
-
*
|
|
535
|
-
* Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
|
|
536
|
-
* concurrency: "inherit"
|
|
537
|
-
* }).pipe(
|
|
538
|
-
* Micro.withConcurrency(2) // use a concurrency of 2
|
|
539
|
-
* )
|
|
540
|
-
* ```
|
|
836
|
+
* @category mapping & sequencing
|
|
541
837
|
*/
|
|
542
|
-
export const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
// ----------------------------------------------------------------------------
|
|
546
|
-
const microDepthState = /*#__PURE__*/globalValue("effect/Micro/microDepthState", () => ({
|
|
547
|
-
depth: 0,
|
|
548
|
-
maxDepthBeforeYield: currentMaxDepthBeforeYield.initial
|
|
838
|
+
export const andThen = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => {
|
|
839
|
+
const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f;
|
|
840
|
+
return isMicro(value) ? value : succeed(value);
|
|
549
841
|
}));
|
|
550
|
-
const unsafeMake = run => {
|
|
551
|
-
const self = Object.create(MicroProto);
|
|
552
|
-
self[runSymbol] = run;
|
|
553
|
-
return self;
|
|
554
|
-
};
|
|
555
|
-
const unsafeMakeOptions = (run, checkAbort) => unsafeMake(function execute(env, onExit) {
|
|
556
|
-
if (checkAbort && env.refs[currentInterruptible.key] !== false && env.refs[currentAbortSignal.key].aborted) {
|
|
557
|
-
return onExit(exitInterrupt);
|
|
558
|
-
}
|
|
559
|
-
microDepthState.depth++;
|
|
560
|
-
if (microDepthState.depth === 1) {
|
|
561
|
-
microDepthState.maxDepthBeforeYield = envGet(env, currentMaxDepthBeforeYield);
|
|
562
|
-
}
|
|
563
|
-
const scheduler = env.refs[currentScheduler.key];
|
|
564
|
-
if (microDepthState.depth >= microDepthState.maxDepthBeforeYield || scheduler.shouldYield(env)) {
|
|
565
|
-
scheduler.scheduleTask(() => execute(env, onExit), 0);
|
|
566
|
-
} else {
|
|
567
|
-
try {
|
|
568
|
-
run(env, onExit);
|
|
569
|
-
} catch (err) {
|
|
570
|
-
onExit(exitDie(err));
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
microDepthState.depth--;
|
|
574
|
-
});
|
|
575
842
|
/**
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
843
|
+
* Execute a side effect from the success value of the `Micro` effect.
|
|
844
|
+
*
|
|
845
|
+
* It is similar to the `andThen` api, but the success value is ignored.
|
|
579
846
|
*
|
|
580
847
|
* @since 3.4.0
|
|
581
848
|
* @experimental
|
|
582
|
-
* @category
|
|
849
|
+
* @category mapping & sequencing
|
|
583
850
|
*/
|
|
584
|
-
export const
|
|
851
|
+
export const tap = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => {
|
|
852
|
+
const value = isMicro(f) ? f : typeof f === "function" ? f(a) : f;
|
|
853
|
+
return isMicro(value) ? as(value, a) : succeed(a);
|
|
854
|
+
}));
|
|
585
855
|
/**
|
|
586
|
-
*
|
|
856
|
+
* Replace the success value of the `Micro` effect with `void`.
|
|
587
857
|
*
|
|
588
|
-
* @since 3.4.
|
|
858
|
+
* @since 3.4.0
|
|
589
859
|
* @experimental
|
|
590
|
-
* @category
|
|
860
|
+
* @category mapping & sequencing
|
|
591
861
|
*/
|
|
592
|
-
export const
|
|
593
|
-
onExit(self);
|
|
594
|
-
});
|
|
862
|
+
export const asVoid = self => flatMap(self, _ => exitVoid);
|
|
595
863
|
/**
|
|
596
|
-
*
|
|
864
|
+
* Access the `MicroExit` of the given `Micro` effect.
|
|
597
865
|
*
|
|
598
866
|
* @since 3.4.6
|
|
599
867
|
* @experimental
|
|
600
|
-
* @category
|
|
868
|
+
* @category mapping & sequencing
|
|
601
869
|
*/
|
|
602
|
-
export const
|
|
603
|
-
|
|
870
|
+
export const exit = self => matchCause(self, {
|
|
871
|
+
onFailure: exitFailCause,
|
|
872
|
+
onSuccess: exitSucceed
|
|
604
873
|
});
|
|
605
874
|
/**
|
|
606
|
-
*
|
|
875
|
+
* Replace the error type of the given `Micro` with the full `MicroCause` object.
|
|
607
876
|
*
|
|
608
877
|
* @since 3.4.0
|
|
609
878
|
* @experimental
|
|
610
|
-
* @category
|
|
879
|
+
* @category mapping & sequencing
|
|
611
880
|
*/
|
|
612
|
-
export const
|
|
881
|
+
export const sandbox = self => catchAllCause(self, fail);
|
|
613
882
|
/**
|
|
614
|
-
*
|
|
883
|
+
* Returns an effect that races all the specified effects,
|
|
884
|
+
* yielding the value of the first effect to succeed with a value. Losers of
|
|
885
|
+
* the race will be interrupted immediately
|
|
615
886
|
*
|
|
616
887
|
* @since 3.4.0
|
|
617
888
|
* @experimental
|
|
618
|
-
* @category
|
|
889
|
+
* @category sequencing
|
|
619
890
|
*/
|
|
620
|
-
export const
|
|
891
|
+
export const raceAll = all => withFiber(parent => async(resume => {
|
|
892
|
+
const effects = Arr.fromIterable(all);
|
|
893
|
+
const len = effects.length;
|
|
894
|
+
let doneCount = 0;
|
|
895
|
+
let done = false;
|
|
896
|
+
const fibers = new Set();
|
|
897
|
+
const causes = [];
|
|
898
|
+
const onExit = exit => {
|
|
899
|
+
doneCount++;
|
|
900
|
+
if (exit._tag === "Failure") {
|
|
901
|
+
causes.push(exit.cause);
|
|
902
|
+
if (doneCount >= len) {
|
|
903
|
+
resume(failCause(causes[0]));
|
|
904
|
+
}
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
done = true;
|
|
908
|
+
resume(fibers.size === 0 ? exit : flatMap(uninterruptible(fiberInterruptAll(fibers)), () => exit));
|
|
909
|
+
};
|
|
910
|
+
for (let i = 0; i < len; i++) {
|
|
911
|
+
if (done) break;
|
|
912
|
+
const fiber = unsafeFork(parent, interruptible(effects[i]), true, true);
|
|
913
|
+
fibers.add(fiber);
|
|
914
|
+
fiber.addObserver(exit => {
|
|
915
|
+
fibers.delete(fiber);
|
|
916
|
+
onExit(exit);
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
return fiberInterruptAll(fibers);
|
|
920
|
+
}));
|
|
621
921
|
/**
|
|
622
|
-
*
|
|
922
|
+
* Returns an effect that races all the specified effects,
|
|
923
|
+
* yielding the value of the first effect to succeed or fail. Losers of
|
|
924
|
+
* the race will be interrupted immediately
|
|
623
925
|
*
|
|
624
926
|
* @since 3.4.0
|
|
625
927
|
* @experimental
|
|
626
|
-
* @category
|
|
928
|
+
* @category sequencing
|
|
627
929
|
*/
|
|
628
|
-
export const
|
|
930
|
+
export const raceAllFirst = all => withFiber(parent => async(resume => {
|
|
931
|
+
let done = false;
|
|
932
|
+
const fibers = new Set();
|
|
933
|
+
const onExit = exit => {
|
|
934
|
+
done = true;
|
|
935
|
+
resume(fibers.size === 0 ? exit : flatMap(fiberInterruptAll(fibers), () => exit));
|
|
936
|
+
};
|
|
937
|
+
for (const effect of all) {
|
|
938
|
+
if (done) break;
|
|
939
|
+
const fiber = unsafeFork(parent, interruptible(effect), true, true);
|
|
940
|
+
fibers.add(fiber);
|
|
941
|
+
fiber.addObserver(exit => {
|
|
942
|
+
fibers.delete(fiber);
|
|
943
|
+
onExit(exit);
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
return fiberInterruptAll(fibers);
|
|
947
|
+
}));
|
|
629
948
|
/**
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
* This will result in a `CauseFail`, where the error is tracked at the
|
|
633
|
-
* type level.
|
|
949
|
+
* Returns an effect that races two effects, yielding the value of the first
|
|
950
|
+
* effect to succeed. Losers of the race will be interrupted immediately
|
|
634
951
|
*
|
|
635
952
|
* @since 3.4.0
|
|
636
953
|
* @experimental
|
|
637
|
-
* @category
|
|
954
|
+
* @category sequencing
|
|
638
955
|
*/
|
|
639
|
-
export const
|
|
956
|
+
export const race = /*#__PURE__*/dual(2, (self, that) => raceAll([self, that]));
|
|
640
957
|
/**
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
* This will result in a `CauseFail`, where the error is tracked at the
|
|
644
|
-
* type level.
|
|
958
|
+
* Returns an effect that races two effects, yielding the value of the first
|
|
959
|
+
* effect to succeed *or* fail. Losers of the race will be interrupted immediately
|
|
645
960
|
*
|
|
646
961
|
* @since 3.4.0
|
|
647
962
|
* @experimental
|
|
648
|
-
* @category
|
|
963
|
+
* @category sequencing
|
|
649
964
|
*/
|
|
650
|
-
export const
|
|
651
|
-
onExit(exitFail(e()));
|
|
652
|
-
});
|
|
965
|
+
export const raceFirst = /*#__PURE__*/dual(2, (self, that) => raceAllFirst([self, that]));
|
|
653
966
|
/**
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
* This will result in a `CauseDie`, where the error is not tracked at
|
|
657
|
-
* the type level.
|
|
967
|
+
* Map the success value of this `Micro` effect to another `Micro` effect, then
|
|
968
|
+
* flatten the result.
|
|
658
969
|
*
|
|
659
970
|
* @since 3.4.0
|
|
660
971
|
* @experimental
|
|
661
|
-
* @category
|
|
972
|
+
* @category mapping & sequencing
|
|
662
973
|
*/
|
|
663
|
-
export const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
* @experimental
|
|
669
|
-
* @category constructors
|
|
670
|
-
*/
|
|
671
|
-
export const failCause = cause => fromExit(exitFailCause(cause));
|
|
672
|
-
/**
|
|
673
|
-
* Creates a `Micro` effect that will fail with the lazily evaluated `MicroCause`.
|
|
674
|
-
*
|
|
675
|
-
* @since 3.4.6
|
|
676
|
-
* @experimental
|
|
677
|
-
* @category constructors
|
|
678
|
-
*/
|
|
679
|
-
export const failCauseSync = cause => fromExitSync(() => exitFailCause(cause()));
|
|
680
|
-
/**
|
|
681
|
-
* Creates a `Micro` effect that will succeed with the lazily evaluated value.
|
|
682
|
-
*
|
|
683
|
-
* If the evaluation of the value throws an error, the effect will fail with
|
|
684
|
-
* `CauseDie`.
|
|
685
|
-
*
|
|
686
|
-
* @since 3.4.0
|
|
687
|
-
* @experimental
|
|
688
|
-
* @category constructors
|
|
689
|
-
*/
|
|
690
|
-
export const sync = evaluate => make(function (_env, onExit) {
|
|
691
|
-
onExit(exitSucceed(evaluate()));
|
|
974
|
+
export const flatMap = /*#__PURE__*/dual(2, (self, f) => {
|
|
975
|
+
const onSuccess = Object.create(OnSuccessProto);
|
|
976
|
+
onSuccess[args] = self;
|
|
977
|
+
onSuccess[successCont] = f;
|
|
978
|
+
return onSuccess;
|
|
692
979
|
});
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
* @experimental
|
|
700
|
-
* @category constructors
|
|
701
|
-
*/
|
|
702
|
-
export const fromOption = option => make(function (_env, onExit) {
|
|
703
|
-
onExit(option._tag === "Some" ? exitSucceed(option.value) : exitFail(new NoSuchElementException({})));
|
|
980
|
+
const OnSuccessProto = /*#__PURE__*/makePrimitiveProto({
|
|
981
|
+
op: "OnSuccess",
|
|
982
|
+
eval(fiber) {
|
|
983
|
+
fiber._stack.push(this);
|
|
984
|
+
return this[args];
|
|
985
|
+
}
|
|
704
986
|
});
|
|
987
|
+
// ----------------------------------------------------------------------------
|
|
988
|
+
// mapping & sequencing
|
|
989
|
+
// ----------------------------------------------------------------------------
|
|
705
990
|
/**
|
|
706
|
-
*
|
|
707
|
-
* of the either if it is a `Left`. Otherwise, it will succeed with the right
|
|
708
|
-
* side of the either.
|
|
991
|
+
* Flattens any nested `Micro` effects, merging the error and requirement types.
|
|
709
992
|
*
|
|
710
993
|
* @since 3.4.0
|
|
711
994
|
* @experimental
|
|
712
|
-
* @category
|
|
995
|
+
* @category mapping & sequencing
|
|
713
996
|
*/
|
|
714
|
-
export const
|
|
715
|
-
onExit(either._tag === "Right" ? either : exitFail(either.left));
|
|
716
|
-
});
|
|
997
|
+
export const flatten = self => flatMap(self, identity);
|
|
717
998
|
/**
|
|
718
|
-
*
|
|
999
|
+
* Transforms the success value of the `Micro` effect with the specified
|
|
1000
|
+
* function.
|
|
719
1001
|
*
|
|
720
1002
|
* @since 3.4.0
|
|
721
1003
|
* @experimental
|
|
722
|
-
* @category
|
|
1004
|
+
* @category mapping & sequencing
|
|
723
1005
|
*/
|
|
724
|
-
export const
|
|
725
|
-
evaluate()[runSymbol](env, onExit);
|
|
726
|
-
});
|
|
727
|
-
const void_ = /*#__PURE__*/succeed(void 0);
|
|
728
|
-
export {
|
|
1006
|
+
export const map = /*#__PURE__*/dual(2, (self, f) => flatMap(self, a => succeed(f(a))));
|
|
729
1007
|
/**
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
* @since 3.4.0
|
|
1008
|
+
* @since 3.4.6
|
|
733
1009
|
* @experimental
|
|
734
|
-
* @category
|
|
1010
|
+
* @category MicroExit
|
|
735
1011
|
*/
|
|
736
|
-
|
|
1012
|
+
export const isMicroExit = u => hasProperty(u, MicroExitTypeId);
|
|
737
1013
|
/**
|
|
738
|
-
*
|
|
739
|
-
*
|
|
740
|
-
* You can return a cleanup effect that will be run when the effect is aborted.
|
|
741
|
-
* It is also passed an `AbortSignal` that is triggered when the effect is
|
|
742
|
-
* aborted.
|
|
743
|
-
*
|
|
744
|
-
* @since 3.4.0
|
|
1014
|
+
* @since 3.4.6
|
|
745
1015
|
* @experimental
|
|
746
|
-
* @category
|
|
1016
|
+
* @category MicroExit
|
|
747
1017
|
*/
|
|
748
|
-
export const
|
|
749
|
-
let resumed = false;
|
|
750
|
-
const controller = register.length > 1 ? new AbortController() : undefined;
|
|
751
|
-
const signal = envGet(env, currentAbortSignal);
|
|
752
|
-
let cleanup = undefined;
|
|
753
|
-
function onAbort() {
|
|
754
|
-
if (cleanup) {
|
|
755
|
-
resume(uninterruptible(andThen(cleanup, fromExit(exitInterrupt))));
|
|
756
|
-
} else {
|
|
757
|
-
resume(fromExit(exitInterrupt));
|
|
758
|
-
}
|
|
759
|
-
if (controller !== undefined) {
|
|
760
|
-
controller.abort();
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
function resume(effect) {
|
|
764
|
-
if (resumed) {
|
|
765
|
-
return;
|
|
766
|
-
}
|
|
767
|
-
resumed = true;
|
|
768
|
-
signal.removeEventListener("abort", onAbort);
|
|
769
|
-
effect[runSymbol](env, onExit);
|
|
770
|
-
}
|
|
771
|
-
cleanup = controller === undefined ? register(resume) : register(resume, controller.signal);
|
|
772
|
-
if (resumed) return;
|
|
773
|
-
signal.addEventListener("abort", onAbort);
|
|
774
|
-
});
|
|
775
|
-
const try_ = options => make(function (_env, onExit) {
|
|
776
|
-
try {
|
|
777
|
-
onExit(exitSucceed(options.try()));
|
|
778
|
-
} catch (err) {
|
|
779
|
-
onExit(exitFail(options.catch(err)));
|
|
780
|
-
}
|
|
781
|
-
});
|
|
782
|
-
export {
|
|
1018
|
+
export const exitSucceed = succeed;
|
|
783
1019
|
/**
|
|
784
|
-
*
|
|
785
|
-
* thrown errors to a specific error type.
|
|
786
|
-
*
|
|
787
|
-
* @since 3.4.0
|
|
1020
|
+
* @since 3.4.6
|
|
788
1021
|
* @experimental
|
|
789
|
-
* @category
|
|
790
|
-
* @example
|
|
791
|
-
* ```ts
|
|
792
|
-
* import { Micro } from "effect"
|
|
793
|
-
*
|
|
794
|
-
* Micro.try({
|
|
795
|
-
* try: () => throw new Error("boom"),
|
|
796
|
-
* catch: (cause) => new Error("caught", { cause })
|
|
797
|
-
* })
|
|
798
|
-
* ```
|
|
1022
|
+
* @category MicroExit
|
|
799
1023
|
*/
|
|
800
|
-
|
|
1024
|
+
export const exitFailCause = failCause;
|
|
801
1025
|
/**
|
|
802
|
-
*
|
|
803
|
-
* `CauseDie`.
|
|
804
|
-
*
|
|
805
|
-
* @since 3.4.0
|
|
1026
|
+
* @since 3.4.6
|
|
806
1027
|
* @experimental
|
|
807
|
-
* @category
|
|
1028
|
+
* @category MicroExit
|
|
808
1029
|
*/
|
|
809
|
-
export const
|
|
810
|
-
evaluate(signal).then(a => resume(succeed(a)), e => resume(die(e)));
|
|
811
|
-
});
|
|
1030
|
+
export const exitInterrupt = /*#__PURE__*/exitFailCause( /*#__PURE__*/causeInterrupt());
|
|
812
1031
|
/**
|
|
813
|
-
*
|
|
814
|
-
* converted into a specific error type.
|
|
815
|
-
*
|
|
816
|
-
* @since 3.4.0
|
|
1032
|
+
* @since 3.4.6
|
|
817
1033
|
* @experimental
|
|
818
|
-
* @category
|
|
819
|
-
* @example
|
|
820
|
-
* ```ts
|
|
821
|
-
* import { Micro } from "effect"
|
|
822
|
-
*
|
|
823
|
-
* Micro.tryPromise({
|
|
824
|
-
* try: () => Promise.resolve("success"),
|
|
825
|
-
* catch: (cause) => new Error("caught", { cause })
|
|
826
|
-
* })
|
|
827
|
-
* ```
|
|
1034
|
+
* @category MicroExit
|
|
828
1035
|
*/
|
|
829
|
-
export const
|
|
830
|
-
try {
|
|
831
|
-
options.try(signal).then(a => resume(succeed(a)), e => resume(fail(options.catch(e))));
|
|
832
|
-
} catch (err) {
|
|
833
|
-
resume(fail(options.catch(err)));
|
|
834
|
-
}
|
|
835
|
-
});
|
|
1036
|
+
export const exitFail = e => exitFailCause(causeFail(e));
|
|
836
1037
|
/**
|
|
837
|
-
*
|
|
838
|
-
* iteration of the event loop.
|
|
839
|
-
*
|
|
840
|
-
* You can specify a priority for the task, which will determine when it is
|
|
841
|
-
* executed relative to other tasks.
|
|
842
|
-
*
|
|
843
|
-
* @since 3.4.0
|
|
1038
|
+
* @since 3.4.6
|
|
844
1039
|
* @experimental
|
|
845
|
-
* @category
|
|
1040
|
+
* @category MicroExit
|
|
846
1041
|
*/
|
|
847
|
-
export const
|
|
848
|
-
envGet(env, currentScheduler).scheduleTask(() => onExit(exitVoid), priority);
|
|
849
|
-
});
|
|
1042
|
+
export const exitDie = defect => exitFailCause(causeDie(defect));
|
|
850
1043
|
/**
|
|
851
|
-
*
|
|
852
|
-
* iteration of the event loop.
|
|
853
|
-
*
|
|
854
|
-
* @since 3.4.0
|
|
1044
|
+
* @since 3.4.6
|
|
855
1045
|
* @experimental
|
|
856
|
-
* @category
|
|
1046
|
+
* @category MicroExit
|
|
857
1047
|
*/
|
|
858
|
-
export const
|
|
1048
|
+
export const exitIsSuccess = self => self._tag === "Success";
|
|
859
1049
|
/**
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
* @since 3.4.0
|
|
1050
|
+
* @since 3.4.6
|
|
863
1051
|
* @experimental
|
|
864
|
-
* @category
|
|
1052
|
+
* @category MicroExit
|
|
865
1053
|
*/
|
|
866
|
-
export const
|
|
867
|
-
envGet(env, currentScheduler).flush();
|
|
868
|
-
onExit(exitVoid);
|
|
869
|
-
});
|
|
1054
|
+
export const exitIsFailure = self => self._tag === "Failure";
|
|
870
1055
|
/**
|
|
871
|
-
*
|
|
872
|
-
* the Javascript runtime from exiting.
|
|
873
|
-
*
|
|
874
|
-
* @since 3.4.0
|
|
1056
|
+
* @since 3.4.6
|
|
875
1057
|
* @experimental
|
|
876
|
-
* @category
|
|
1058
|
+
* @category MicroExit
|
|
877
1059
|
*/
|
|
878
|
-
export const
|
|
879
|
-
const interval = setInterval(constVoid, 2147483646);
|
|
880
|
-
return sync(() => clearInterval(interval));
|
|
881
|
-
});
|
|
1060
|
+
export const exitIsInterrupt = self => exitIsFailure(self) && self.cause._tag === "Interrupt";
|
|
882
1061
|
/**
|
|
883
|
-
* @since 3.4.
|
|
1062
|
+
* @since 3.4.6
|
|
884
1063
|
* @experimental
|
|
885
|
-
* @category
|
|
1064
|
+
* @category MicroExit
|
|
886
1065
|
*/
|
|
887
|
-
export const
|
|
888
|
-
const iterator = args.length === 1 ? args[0]() : args[1].call(args[0]);
|
|
889
|
-
let running = false;
|
|
890
|
-
let value = undefined;
|
|
891
|
-
function run() {
|
|
892
|
-
running = true;
|
|
893
|
-
try {
|
|
894
|
-
let shouldContinue = true;
|
|
895
|
-
while (shouldContinue) {
|
|
896
|
-
const result = iterator.next(value);
|
|
897
|
-
if (result.done) {
|
|
898
|
-
return onExit(exitSucceed(result.value));
|
|
899
|
-
}
|
|
900
|
-
shouldContinue = false;
|
|
901
|
-
yieldWrapGet(result.value)[runSymbol](env, function (exit) {
|
|
902
|
-
if (exit._tag === "Left") {
|
|
903
|
-
onExit(exit);
|
|
904
|
-
} else {
|
|
905
|
-
shouldContinue = true;
|
|
906
|
-
value = exit.right;
|
|
907
|
-
if (!running) run();
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
} catch (err) {
|
|
912
|
-
onExit(exitDie(err));
|
|
913
|
-
}
|
|
914
|
-
running = false;
|
|
915
|
-
}
|
|
916
|
-
run();
|
|
917
|
-
});
|
|
918
|
-
// ----------------------------------------------------------------------------
|
|
919
|
-
// mapping & sequencing
|
|
920
|
-
// ----------------------------------------------------------------------------
|
|
1066
|
+
export const exitIsFail = self => exitIsFailure(self) && self.cause._tag === "Fail";
|
|
921
1067
|
/**
|
|
922
|
-
*
|
|
923
|
-
*
|
|
924
|
-
* @since 3.4.0
|
|
1068
|
+
* @since 3.4.6
|
|
925
1069
|
* @experimental
|
|
926
|
-
* @category
|
|
1070
|
+
* @category MicroExit
|
|
927
1071
|
*/
|
|
928
|
-
export const
|
|
929
|
-
self[runSymbol](env, exit => exit._tag === "Left" ? onExit(exit) : exit.right[runSymbol](env, onExit));
|
|
930
|
-
});
|
|
1072
|
+
export const exitIsDie = self => exitIsFailure(self) && self.cause._tag === "Die";
|
|
931
1073
|
/**
|
|
932
|
-
*
|
|
933
|
-
* function.
|
|
934
|
-
*
|
|
935
|
-
* @since 3.4.0
|
|
1074
|
+
* @since 3.4.6
|
|
936
1075
|
* @experimental
|
|
937
|
-
* @category
|
|
1076
|
+
* @category MicroExit
|
|
938
1077
|
*/
|
|
939
|
-
export const
|
|
940
|
-
self[runSymbol](env, function (exit) {
|
|
941
|
-
onExit(exit._tag === "Left" ? exit : exitSucceed(f(exit.right)));
|
|
942
|
-
});
|
|
943
|
-
}));
|
|
1078
|
+
export const exitVoid = /*#__PURE__*/exitSucceed(void 0);
|
|
944
1079
|
/**
|
|
945
|
-
*
|
|
946
|
-
* effect.
|
|
947
|
-
*
|
|
948
|
-
* @since 3.4.0
|
|
1080
|
+
* @since 3.11.0
|
|
949
1081
|
* @experimental
|
|
950
|
-
* @category
|
|
1082
|
+
* @category MicroExit
|
|
951
1083
|
*/
|
|
952
|
-
export const
|
|
1084
|
+
export const exitVoidAll = exits => {
|
|
1085
|
+
for (const exit of exits) {
|
|
1086
|
+
if (exit._tag === "Failure") {
|
|
1087
|
+
return exit;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
return exitVoid;
|
|
1091
|
+
};
|
|
1092
|
+
const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : f => setTimeout(f, 0);
|
|
953
1093
|
/**
|
|
954
|
-
*
|
|
955
|
-
*
|
|
956
|
-
* @since 3.4.0
|
|
1094
|
+
* @since 3.5.9
|
|
957
1095
|
* @experimental
|
|
958
|
-
* @category
|
|
1096
|
+
* @category scheduler
|
|
959
1097
|
*/
|
|
960
|
-
export
|
|
1098
|
+
export class MicroSchedulerDefault {
|
|
1099
|
+
tasks = [];
|
|
1100
|
+
running = false;
|
|
1101
|
+
/**
|
|
1102
|
+
* @since 3.5.9
|
|
1103
|
+
*/
|
|
1104
|
+
scheduleTask(task, _priority) {
|
|
1105
|
+
this.tasks.push(task);
|
|
1106
|
+
if (!this.running) {
|
|
1107
|
+
this.running = true;
|
|
1108
|
+
setImmediate(this.afterScheduled);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* @since 3.5.9
|
|
1113
|
+
*/
|
|
1114
|
+
afterScheduled = () => {
|
|
1115
|
+
this.running = false;
|
|
1116
|
+
this.runTasks();
|
|
1117
|
+
};
|
|
1118
|
+
/**
|
|
1119
|
+
* @since 3.5.9
|
|
1120
|
+
*/
|
|
1121
|
+
runTasks() {
|
|
1122
|
+
const tasks = this.tasks;
|
|
1123
|
+
this.tasks = [];
|
|
1124
|
+
for (let i = 0, len = tasks.length; i < len; i++) {
|
|
1125
|
+
tasks[i]();
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* @since 3.5.9
|
|
1130
|
+
*/
|
|
1131
|
+
shouldYield(fiber) {
|
|
1132
|
+
return fiber.currentOpCount >= fiber.getRef(MaxOpsBeforeYield);
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* @since 3.5.9
|
|
1136
|
+
*/
|
|
1137
|
+
flush() {
|
|
1138
|
+
while (this.tasks.length > 0) {
|
|
1139
|
+
this.runTasks();
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
961
1143
|
/**
|
|
962
|
-
*
|
|
963
|
-
* flatten the result.
|
|
1144
|
+
* Access the given `Context.Tag` from the environment.
|
|
964
1145
|
*
|
|
965
1146
|
* @since 3.4.0
|
|
966
1147
|
* @experimental
|
|
967
|
-
* @category
|
|
1148
|
+
* @category environment
|
|
968
1149
|
*/
|
|
969
|
-
export const
|
|
970
|
-
self[runSymbol](env, function (exit) {
|
|
971
|
-
if (exit._tag === "Left") {
|
|
972
|
-
return onExit(exit);
|
|
973
|
-
}
|
|
974
|
-
f(exit.right)[runSymbol](env, onExit);
|
|
975
|
-
});
|
|
976
|
-
}));
|
|
1150
|
+
export const service = tag => withFiber(fiber => succeed(Context.unsafeGet(fiber.context, tag)));
|
|
977
1151
|
/**
|
|
978
|
-
*
|
|
1152
|
+
* Access the given `Context.Tag` from the environment, without tracking the
|
|
1153
|
+
* dependency at the type level.
|
|
1154
|
+
*
|
|
1155
|
+
* It will return an `Option` of the service, depending on whether it is
|
|
1156
|
+
* available in the environment or not.
|
|
979
1157
|
*
|
|
980
1158
|
* @since 3.4.0
|
|
981
1159
|
* @experimental
|
|
982
|
-
* @category
|
|
1160
|
+
* @category environment
|
|
983
1161
|
*/
|
|
984
|
-
export const
|
|
985
|
-
onFailure: succeed,
|
|
986
|
-
onSuccess: fail
|
|
987
|
-
});
|
|
1162
|
+
export const serviceOption = tag => withFiber(fiber => succeed(Context.getOption(fiber.context, tag)));
|
|
988
1163
|
/**
|
|
989
|
-
*
|
|
990
|
-
* a single api.
|
|
991
|
-
*
|
|
992
|
-
* It also allows you to pass in a `Micro` effect directly, which will be
|
|
993
|
-
* executed after the current effect.
|
|
1164
|
+
* Update the Context with the given mapping function.
|
|
994
1165
|
*
|
|
995
|
-
* @since 3.
|
|
1166
|
+
* @since 3.11.0
|
|
996
1167
|
* @experimental
|
|
997
|
-
* @category
|
|
1168
|
+
* @category environment
|
|
998
1169
|
*/
|
|
999
|
-
export const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
}
|
|
1006
|
-
const value = isMicro(f) ? f : typeof f === "function" ? f(exit.right) : f;
|
|
1007
|
-
if (isMicro(value)) {
|
|
1008
|
-
value[runSymbol](env, onExit);
|
|
1009
|
-
} else {
|
|
1010
|
-
onExit(exitSucceed(value));
|
|
1011
|
-
}
|
|
1170
|
+
export const updateContext = /*#__PURE__*/dual(2, (self, f) => withFiber(fiber => {
|
|
1171
|
+
const prev = fiber.context;
|
|
1172
|
+
fiber.context = f(prev);
|
|
1173
|
+
return onExit(self, () => {
|
|
1174
|
+
fiber.context = prev;
|
|
1175
|
+
return void_;
|
|
1012
1176
|
});
|
|
1013
1177
|
}));
|
|
1014
1178
|
/**
|
|
1015
|
-
*
|
|
1179
|
+
* Update the service for the given `Context.Tag` in the environment.
|
|
1016
1180
|
*
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
* @since 3.4.0
|
|
1181
|
+
* @since 3.11.0
|
|
1020
1182
|
* @experimental
|
|
1021
|
-
* @category
|
|
1183
|
+
* @category environment
|
|
1022
1184
|
*/
|
|
1023
|
-
export const
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
}
|
|
1030
|
-
const value = isMicro(f) ? f : typeof f === "function" ? f(selfExit.right) : f;
|
|
1031
|
-
if (isMicro(value)) {
|
|
1032
|
-
value[runSymbol](env, function (tapExit) {
|
|
1033
|
-
if (tapExit._tag === "Left") {
|
|
1034
|
-
return onExit(tapExit);
|
|
1035
|
-
}
|
|
1036
|
-
onExit(selfExit);
|
|
1037
|
-
});
|
|
1038
|
-
} else {
|
|
1039
|
-
onExit(selfExit);
|
|
1040
|
-
}
|
|
1185
|
+
export const updateService = /*#__PURE__*/dual(3, (self, tag, f) => withFiber(fiber => {
|
|
1186
|
+
const prev = Context.unsafeGet(fiber.context, tag);
|
|
1187
|
+
fiber.context = Context.add(fiber.context, tag, f(prev));
|
|
1188
|
+
return onExit(self, () => {
|
|
1189
|
+
fiber.context = Context.add(fiber.context, tag, prev);
|
|
1190
|
+
return void_;
|
|
1041
1191
|
});
|
|
1042
1192
|
}));
|
|
1043
1193
|
/**
|
|
1044
|
-
*
|
|
1194
|
+
* Access the current `Context` from the environment.
|
|
1045
1195
|
*
|
|
1046
1196
|
* @since 3.4.0
|
|
1047
1197
|
* @experimental
|
|
1048
|
-
* @category
|
|
1198
|
+
* @category environment
|
|
1049
1199
|
*/
|
|
1050
|
-
export const
|
|
1200
|
+
export const context = () => getContext;
|
|
1201
|
+
const getContext = /*#__PURE__*/withFiber(fiber => succeed(fiber.context));
|
|
1051
1202
|
/**
|
|
1052
|
-
*
|
|
1203
|
+
* Merge the given `Context` with the current context.
|
|
1053
1204
|
*
|
|
1054
|
-
* @since 3.4.
|
|
1205
|
+
* @since 3.4.0
|
|
1055
1206
|
* @experimental
|
|
1056
|
-
* @category
|
|
1207
|
+
* @category environment
|
|
1057
1208
|
*/
|
|
1058
|
-
export const
|
|
1059
|
-
self[runSymbol](env, function (exit) {
|
|
1060
|
-
onExit(exitSucceed(exit));
|
|
1061
|
-
});
|
|
1062
|
-
});
|
|
1209
|
+
export const provideContext = /*#__PURE__*/dual(2, (self, provided) => updateContext(self, Context.merge(provided)));
|
|
1063
1210
|
/**
|
|
1064
|
-
*
|
|
1211
|
+
* Add the provided service to the current context.
|
|
1065
1212
|
*
|
|
1066
1213
|
* @since 3.4.0
|
|
1067
1214
|
* @experimental
|
|
1068
|
-
* @category
|
|
1215
|
+
* @category environment
|
|
1069
1216
|
*/
|
|
1070
|
-
export const
|
|
1071
|
-
function forkSignal(env) {
|
|
1072
|
-
const controller = new AbortController();
|
|
1073
|
-
const parentSignal = envGet(env, currentAbortSignal);
|
|
1074
|
-
function onAbort() {
|
|
1075
|
-
controller.abort();
|
|
1076
|
-
parentSignal.removeEventListener("abort", onAbort);
|
|
1077
|
-
}
|
|
1078
|
-
parentSignal.addEventListener("abort", onAbort);
|
|
1079
|
-
const envWithSignal = envMutate(env, function (refs) {
|
|
1080
|
-
refs[currentAbortController.key] = controller;
|
|
1081
|
-
refs[currentAbortSignal.key] = controller.signal;
|
|
1082
|
-
return refs;
|
|
1083
|
-
});
|
|
1084
|
-
return [envWithSignal, onAbort];
|
|
1085
|
-
}
|
|
1217
|
+
export const provideService = /*#__PURE__*/dual(3, (self, tag, service) => updateContext(self, Context.add(tag, service)));
|
|
1086
1218
|
/**
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
-
* the race will be interrupted immediately
|
|
1219
|
+
* Create a service using the provided `Micro` effect, and add it to the
|
|
1220
|
+
* current context.
|
|
1090
1221
|
*
|
|
1091
|
-
* @since 3.4.
|
|
1222
|
+
* @since 3.4.6
|
|
1092
1223
|
* @experimental
|
|
1093
|
-
* @category
|
|
1224
|
+
* @category environment
|
|
1094
1225
|
*/
|
|
1095
|
-
export const
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
let index = 0;
|
|
1100
|
-
let done = 0;
|
|
1101
|
-
let exit = undefined;
|
|
1102
|
-
const causes = [];
|
|
1103
|
-
function onDone(exit_) {
|
|
1104
|
-
done++;
|
|
1105
|
-
if (exit_._tag === "Right" && exit === undefined) {
|
|
1106
|
-
len = index;
|
|
1107
|
-
exit = exit_;
|
|
1108
|
-
onAbort();
|
|
1109
|
-
} else if (exit_._tag === "Left") {
|
|
1110
|
-
causes.push(exit_.left);
|
|
1111
|
-
}
|
|
1112
|
-
if (done >= len) {
|
|
1113
|
-
onExit(exit ?? Either.left(causes[0]));
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
for (; index < len; index++) {
|
|
1117
|
-
effects[index][runSymbol](envWithSignal, onDone);
|
|
1118
|
-
}
|
|
1119
|
-
});
|
|
1226
|
+
export const provideServiceEffect = /*#__PURE__*/dual(3, (self, tag, acquire) => flatMap(acquire, service => provideService(self, tag, service)));
|
|
1227
|
+
// ========================================================================
|
|
1228
|
+
// References
|
|
1229
|
+
// ========================================================================
|
|
1120
1230
|
/**
|
|
1121
|
-
*
|
|
1122
|
-
* yielding the value of the first effect to succeed or fail. Losers of
|
|
1123
|
-
* the race will be interrupted immediately
|
|
1124
|
-
*
|
|
1125
|
-
* @since 3.4.0
|
|
1231
|
+
* @since 3.11.0
|
|
1126
1232
|
* @experimental
|
|
1127
|
-
* @category
|
|
1233
|
+
* @category references
|
|
1128
1234
|
*/
|
|
1129
|
-
export
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
let len = effects.length;
|
|
1133
|
-
let index = 0;
|
|
1134
|
-
let done = 0;
|
|
1135
|
-
let exit = undefined;
|
|
1136
|
-
const causes = [];
|
|
1137
|
-
function onDone(exit_) {
|
|
1138
|
-
done++;
|
|
1139
|
-
if (exit === undefined) {
|
|
1140
|
-
len = index;
|
|
1141
|
-
exit = exit_;
|
|
1142
|
-
onAbort();
|
|
1143
|
-
}
|
|
1144
|
-
if (done >= len) {
|
|
1145
|
-
onExit(exit ?? Either.left(causes[0]));
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
for (; index < len; index++) {
|
|
1149
|
-
effects[index][runSymbol](envWithSignal, onDone);
|
|
1150
|
-
}
|
|
1151
|
-
});
|
|
1235
|
+
export class MaxOpsBeforeYield extends /*#__PURE__*/Context.Reference()("effect/Micro/currentMaxOpsBeforeYield", {
|
|
1236
|
+
defaultValue: () => 2048
|
|
1237
|
+
}) {}
|
|
1152
1238
|
/**
|
|
1153
|
-
*
|
|
1154
|
-
* effect to succeed. Losers of the race will be interrupted immediately
|
|
1155
|
-
*
|
|
1156
|
-
* @since 3.4.0
|
|
1239
|
+
* @since 3.11.0
|
|
1157
1240
|
* @experimental
|
|
1158
|
-
* @category
|
|
1241
|
+
* @category environment refs
|
|
1159
1242
|
*/
|
|
1160
|
-
export
|
|
1243
|
+
export class CurrentConcurrency extends /*#__PURE__*/Context.Reference()("effect/Micro/currentConcurrency", {
|
|
1244
|
+
defaultValue: () => "unbounded"
|
|
1245
|
+
}) {}
|
|
1161
1246
|
/**
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1247
|
+
* @since 3.11.0
|
|
1248
|
+
* @experimental
|
|
1249
|
+
* @category environment refs
|
|
1250
|
+
*/
|
|
1251
|
+
export class CurrentScheduler extends /*#__PURE__*/Context.Reference()("effect/Micro/currentScheduler", {
|
|
1252
|
+
defaultValue: () => new MicroSchedulerDefault()
|
|
1253
|
+
}) {}
|
|
1254
|
+
/**
|
|
1255
|
+
* If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
|
|
1256
|
+
* api to control the concurrency of that `Micro` when it is run.
|
|
1164
1257
|
*
|
|
1165
1258
|
* @since 3.4.0
|
|
1166
1259
|
* @experimental
|
|
1167
|
-
* @category
|
|
1260
|
+
* @category environment refs
|
|
1261
|
+
* @example
|
|
1262
|
+
* import * as Micro from "effect/Micro"
|
|
1263
|
+
*
|
|
1264
|
+
* Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
|
|
1265
|
+
* concurrency: "inherit"
|
|
1266
|
+
* }).pipe(
|
|
1267
|
+
* Micro.withConcurrency(2) // use a concurrency of 2
|
|
1268
|
+
* )
|
|
1168
1269
|
*/
|
|
1169
|
-
export const
|
|
1270
|
+
export const withConcurrency = /*#__PURE__*/dual(2, (self, concurrency) => provideService(self, CurrentConcurrency, concurrency));
|
|
1170
1271
|
// ----------------------------------------------------------------------------
|
|
1171
1272
|
// zipping
|
|
1172
1273
|
// ----------------------------------------------------------------------------
|
|
@@ -1188,15 +1289,11 @@ export const zip = /*#__PURE__*/dual(args => isMicro(args[1]), (self, that, opti
|
|
|
1188
1289
|
* @experimental
|
|
1189
1290
|
* @category zipping
|
|
1190
1291
|
*/
|
|
1191
|
-
export const zipWith = /*#__PURE__*/dual(args => isMicro(args[1]), (self, that, f, options) =>
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}), ([a, a2]) => f(a, a2));
|
|
1197
|
-
}
|
|
1198
|
-
return flatMap(self, a => map(that, a2 => f(a, a2)));
|
|
1199
|
-
});
|
|
1292
|
+
export const zipWith = /*#__PURE__*/dual(args => isMicro(args[1]), (self, that, f, options) => options?.concurrent
|
|
1293
|
+
// Use `all` exclusively for concurrent cases, as it introduces additional overhead due to the management of concurrency
|
|
1294
|
+
? map(all([self, that], {
|
|
1295
|
+
concurrency: 2
|
|
1296
|
+
}), ([a, a2]) => f(a, a2)) : flatMap(self, a => map(that, a2 => f(a, a2))));
|
|
1200
1297
|
// ----------------------------------------------------------------------------
|
|
1201
1298
|
// filtering & conditionals
|
|
1202
1299
|
// ----------------------------------------------------------------------------
|
|
@@ -1231,7 +1328,7 @@ export const filterOrFail = /*#__PURE__*/dual(args => isMicro(args[0]), (self, r
|
|
|
1231
1328
|
* @experimental
|
|
1232
1329
|
* @category filtering & conditionals
|
|
1233
1330
|
*/
|
|
1234
|
-
export const when = /*#__PURE__*/dual(2, (self, condition) => flatMap(isMicro(condition) ? condition : sync(condition), pass => pass ? asSome(self) :
|
|
1331
|
+
export const when = /*#__PURE__*/dual(2, (self, condition) => flatMap(isMicro(condition) ? condition : sync(condition), pass => pass ? asSome(self) : succeedNone));
|
|
1235
1332
|
// ----------------------------------------------------------------------------
|
|
1236
1333
|
// repetition
|
|
1237
1334
|
// ----------------------------------------------------------------------------
|
|
@@ -1245,14 +1342,14 @@ export const when = /*#__PURE__*/dual(2, (self, condition) => flatMap(isMicro(co
|
|
|
1245
1342
|
* @experimental
|
|
1246
1343
|
* @category repetition
|
|
1247
1344
|
*/
|
|
1248
|
-
export const repeatExit = /*#__PURE__*/dual(2, (self, options) =>
|
|
1345
|
+
export const repeatExit = /*#__PURE__*/dual(2, (self, options) => suspend(() => {
|
|
1249
1346
|
const startedAt = options.schedule ? Date.now() : 0;
|
|
1250
1347
|
let attempt = 0;
|
|
1251
|
-
|
|
1348
|
+
const loop = flatMap(exit(self), exit => {
|
|
1252
1349
|
if (options.while !== undefined && !options.while(exit)) {
|
|
1253
|
-
return
|
|
1350
|
+
return exit;
|
|
1254
1351
|
} else if (options.times !== undefined && attempt >= options.times) {
|
|
1255
|
-
return
|
|
1352
|
+
return exit;
|
|
1256
1353
|
}
|
|
1257
1354
|
attempt++;
|
|
1258
1355
|
let delayEffect = yieldNow;
|
|
@@ -1260,17 +1357,13 @@ export const repeatExit = /*#__PURE__*/dual(2, (self, options) => make(function
|
|
|
1260
1357
|
const elapsed = Date.now() - startedAt;
|
|
1261
1358
|
const duration = options.schedule(attempt, elapsed);
|
|
1262
1359
|
if (Option.isNone(duration)) {
|
|
1263
|
-
return
|
|
1360
|
+
return exit;
|
|
1264
1361
|
}
|
|
1265
1362
|
delayEffect = sleep(duration.value);
|
|
1266
1363
|
}
|
|
1267
|
-
delayEffect
|
|
1268
|
-
if (exit._tag === "Left") {
|
|
1269
|
-
return onExit(exit);
|
|
1270
|
-
}
|
|
1271
|
-
self[runSymbol](env, loop);
|
|
1272
|
-
});
|
|
1364
|
+
return flatMap(delayEffect, () => loop);
|
|
1273
1365
|
});
|
|
1366
|
+
return loop;
|
|
1274
1367
|
}));
|
|
1275
1368
|
/**
|
|
1276
1369
|
* Repeat the given `Micro` effect using the provided options. Only successful
|
|
@@ -1282,8 +1375,26 @@ export const repeatExit = /*#__PURE__*/dual(2, (self, options) => make(function
|
|
|
1282
1375
|
*/
|
|
1283
1376
|
export const repeat = /*#__PURE__*/dual(args => isMicro(args[0]), (self, options) => repeatExit(self, {
|
|
1284
1377
|
...options,
|
|
1285
|
-
while: exit => exit._tag === "
|
|
1378
|
+
while: exit => exit._tag === "Success" && (options?.while === undefined || options.while(exit.value))
|
|
1286
1379
|
}));
|
|
1380
|
+
/**
|
|
1381
|
+
* Replicates the given effect `n` times.
|
|
1382
|
+
*
|
|
1383
|
+
* @since 3.11.0
|
|
1384
|
+
* @experimental
|
|
1385
|
+
* @category repetition
|
|
1386
|
+
*/
|
|
1387
|
+
export const replicate = /*#__PURE__*/dual(2, (self, n) => Array.from({
|
|
1388
|
+
length: n
|
|
1389
|
+
}, () => self));
|
|
1390
|
+
/**
|
|
1391
|
+
* Performs this effect the specified number of times and collects the
|
|
1392
|
+
* results.
|
|
1393
|
+
*
|
|
1394
|
+
* @since 3.11.0
|
|
1395
|
+
* @category repetition
|
|
1396
|
+
*/
|
|
1397
|
+
export const replicateEffect = /*#__PURE__*/dual(args => isMicro(args[0]), (self, n, options) => all(replicate(self, n), options));
|
|
1287
1398
|
/**
|
|
1288
1399
|
* Repeat the given `Micro` effect forever, only stopping if the effect fails.
|
|
1289
1400
|
*
|
|
@@ -1373,7 +1484,19 @@ export const scheduleIntersect = /*#__PURE__*/dual(2, (self, that) => (attempt,
|
|
|
1373
1484
|
* @experimental
|
|
1374
1485
|
* @category error handling
|
|
1375
1486
|
*/
|
|
1376
|
-
export const catchAllCause = /*#__PURE__*/dual(2, (self, f) =>
|
|
1487
|
+
export const catchAllCause = /*#__PURE__*/dual(2, (self, f) => {
|
|
1488
|
+
const onFailure = Object.create(OnFailureProto);
|
|
1489
|
+
onFailure[args] = self;
|
|
1490
|
+
onFailure[failureCont] = f;
|
|
1491
|
+
return onFailure;
|
|
1492
|
+
});
|
|
1493
|
+
const OnFailureProto = /*#__PURE__*/makePrimitiveProto({
|
|
1494
|
+
op: "OnFailure",
|
|
1495
|
+
eval(fiber) {
|
|
1496
|
+
fiber._stack.push(this);
|
|
1497
|
+
return this[args];
|
|
1498
|
+
}
|
|
1499
|
+
});
|
|
1377
1500
|
/**
|
|
1378
1501
|
* Selectively catch a `MicroCause` object of the given `Micro` effect,
|
|
1379
1502
|
* using the provided predicate to determine if the failure should be caught.
|
|
@@ -1382,15 +1505,7 @@ export const catchAllCause = /*#__PURE__*/dual(2, (self, f) => catchCauseIf(self
|
|
|
1382
1505
|
* @experimental
|
|
1383
1506
|
* @category error handling
|
|
1384
1507
|
*/
|
|
1385
|
-
export const catchCauseIf = /*#__PURE__*/dual(3, (self, predicate, f) =>
|
|
1386
|
-
self[runSymbol](env, function (exit) {
|
|
1387
|
-
if (exit._tag === "Right" || !predicate(exit.left)) {
|
|
1388
|
-
onExit(exit);
|
|
1389
|
-
} else {
|
|
1390
|
-
f(exit.left)[runSymbol](env, onExit);
|
|
1391
|
-
}
|
|
1392
|
-
});
|
|
1393
|
-
}));
|
|
1508
|
+
export const catchCauseIf = /*#__PURE__*/dual(3, (self, predicate, f) => catchAllCause(self, cause => predicate(cause) ? f(cause) : failCause(cause)));
|
|
1394
1509
|
/**
|
|
1395
1510
|
* Catch the error of the given `Micro` effect, allowing you to recover from it.
|
|
1396
1511
|
*
|
|
@@ -1400,7 +1515,7 @@ export const catchCauseIf = /*#__PURE__*/dual(3, (self, predicate, f) => make(fu
|
|
|
1400
1515
|
* @experimental
|
|
1401
1516
|
* @category error handling
|
|
1402
1517
|
*/
|
|
1403
|
-
export const catchAll = /*#__PURE__*/dual(2, (self, f) =>
|
|
1518
|
+
export const catchAll = /*#__PURE__*/dual(2, (self, f) => catchCauseIf(self, causeIsFail, cause => f(cause.error)));
|
|
1404
1519
|
/**
|
|
1405
1520
|
* Catch any unexpected errors of the given `Micro` effect, allowing you to recover from them.
|
|
1406
1521
|
*
|
|
@@ -1524,7 +1639,7 @@ export const ignoreLogged = self => matchEffect(self, {
|
|
|
1524
1639
|
* @category error handling
|
|
1525
1640
|
*/
|
|
1526
1641
|
export const option = self => match(self, {
|
|
1527
|
-
onFailure:
|
|
1642
|
+
onFailure: Option.none,
|
|
1528
1643
|
onSuccess: Option.some
|
|
1529
1644
|
});
|
|
1530
1645
|
/**
|
|
@@ -1549,7 +1664,7 @@ export const either = self => match(self, {
|
|
|
1549
1664
|
*/
|
|
1550
1665
|
export const retry = /*#__PURE__*/dual(args => isMicro(args[0]), (self, options) => repeatExit(self, {
|
|
1551
1666
|
...options,
|
|
1552
|
-
while: exit => exit._tag === "
|
|
1667
|
+
while: exit => exit._tag === "Failure" && exit.cause._tag === "Fail" && (options?.while === undefined || options.while(exit.cause.error))
|
|
1553
1668
|
}));
|
|
1554
1669
|
/**
|
|
1555
1670
|
* Add a stack trace to any failures that occur in the effect. The trace will be
|
|
@@ -1576,11 +1691,7 @@ export const withTrace = function () {
|
|
|
1576
1691
|
const lineMatch = line.match(/\((.*)\)$/);
|
|
1577
1692
|
return causeWithTrace(cause, `at ${name} (${lineMatch ? lineMatch[1] : line})`);
|
|
1578
1693
|
}
|
|
1579
|
-
const f = name => self =>
|
|
1580
|
-
self[runSymbol](env, function (exit) {
|
|
1581
|
-
onExit(exit._tag === "Left" ? Either.left(generate(name, exit.left)) : exit);
|
|
1582
|
-
});
|
|
1583
|
-
}, false);
|
|
1694
|
+
const f = name => self => onError(self, cause => failCause(generate(name, cause)));
|
|
1584
1695
|
if (arguments.length === 2) {
|
|
1585
1696
|
return f(arguments[1])(arguments[0]);
|
|
1586
1697
|
}
|
|
@@ -1594,16 +1705,20 @@ export const withTrace = function () {
|
|
|
1594
1705
|
* @experimental
|
|
1595
1706
|
* @category pattern matching
|
|
1596
1707
|
*/
|
|
1597
|
-
export const matchCauseEffect = /*#__PURE__*/dual(2, (self, options) =>
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1708
|
+
export const matchCauseEffect = /*#__PURE__*/dual(2, (self, options) => {
|
|
1709
|
+
const primitive = Object.create(OnSuccessAndFailureProto);
|
|
1710
|
+
primitive[args] = self;
|
|
1711
|
+
primitive[successCont] = options.onSuccess;
|
|
1712
|
+
primitive[failureCont] = options.onFailure;
|
|
1713
|
+
return primitive;
|
|
1714
|
+
});
|
|
1715
|
+
const OnSuccessAndFailureProto = /*#__PURE__*/makePrimitiveProto({
|
|
1716
|
+
op: "OnSuccessAndFailure",
|
|
1717
|
+
eval(fiber) {
|
|
1718
|
+
fiber._stack.push(this);
|
|
1719
|
+
return this[args];
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1607
1722
|
/**
|
|
1608
1723
|
* @since 3.4.6
|
|
1609
1724
|
* @experimental
|
|
@@ -1641,12 +1756,12 @@ export const match = /*#__PURE__*/dual(2, (self, options) => matchEffect(self, {
|
|
|
1641
1756
|
* @experimental
|
|
1642
1757
|
* @category delays & timeouts
|
|
1643
1758
|
*/
|
|
1644
|
-
export const sleep = millis => async(
|
|
1645
|
-
const timeout = setTimeout(
|
|
1759
|
+
export const sleep = millis => async(resume => {
|
|
1760
|
+
const timeout = setTimeout(() => {
|
|
1646
1761
|
resume(void_);
|
|
1647
1762
|
}, millis);
|
|
1648
1763
|
return sync(() => {
|
|
1649
|
-
|
|
1764
|
+
clearTimeout(timeout);
|
|
1650
1765
|
});
|
|
1651
1766
|
});
|
|
1652
1767
|
/**
|
|
@@ -1747,7 +1862,7 @@ class MicroScopeImpl {
|
|
|
1747
1862
|
_tag: "Closed",
|
|
1748
1863
|
exit: microExit
|
|
1749
1864
|
};
|
|
1750
|
-
return flatMap(forEach(finalizers, finalizer => exit(finalizer(microExit))),
|
|
1865
|
+
return flatMap(forEach(finalizers, finalizer => exit(finalizer(microExit))), exitVoidAll);
|
|
1751
1866
|
}
|
|
1752
1867
|
return void_;
|
|
1753
1868
|
});
|
|
@@ -1804,7 +1919,7 @@ export const provideScope = /*#__PURE__*/dual(2, (self, scope) => provideService
|
|
|
1804
1919
|
* @experimental
|
|
1805
1920
|
* @category resources & finalization
|
|
1806
1921
|
*/
|
|
1807
|
-
export const scoped = self => suspend(
|
|
1922
|
+
export const scoped = self => suspend(() => {
|
|
1808
1923
|
const scope = new MicroScopeImpl();
|
|
1809
1924
|
return onExit(provideService(self, MicroScope, scope), exit => scope.close(exit));
|
|
1810
1925
|
});
|
|
@@ -1833,36 +1948,27 @@ export const addFinalizer = finalizer => flatMap(scope, scope => scope.addFinali
|
|
|
1833
1948
|
* @experimental
|
|
1834
1949
|
* @category resources & finalization
|
|
1835
1950
|
*/
|
|
1836
|
-
export const onExit = /*#__PURE__*/dual(2, (self, f) =>
|
|
1951
|
+
export const onExit = /*#__PURE__*/dual(2, (self, f) => uninterruptibleMask(restore => matchCauseEffect(restore(self), {
|
|
1952
|
+
onFailure: cause => flatMap(f(exitFailCause(cause)), () => failCause(cause)),
|
|
1953
|
+
onSuccess: a => flatMap(f(exitSucceed(a)), () => succeed(a))
|
|
1954
|
+
})));
|
|
1837
1955
|
/**
|
|
1838
|
-
*
|
|
1839
|
-
* matches the specified predicate.
|
|
1956
|
+
* Regardless of the result of the this `Micro` effect, run the finalizer effect.
|
|
1840
1957
|
*
|
|
1841
|
-
* @since 3.4.
|
|
1958
|
+
* @since 3.4.0
|
|
1842
1959
|
* @experimental
|
|
1843
1960
|
* @category resources & finalization
|
|
1844
1961
|
*/
|
|
1845
|
-
export const
|
|
1846
|
-
restore(self)[runSymbol](env, function (exit) {
|
|
1847
|
-
if (!refinement(exit)) {
|
|
1848
|
-
return onExit(exit);
|
|
1849
|
-
}
|
|
1850
|
-
f(exit)[runSymbol](env, function (finalizerExit) {
|
|
1851
|
-
if (finalizerExit._tag === "Left") {
|
|
1852
|
-
return onExit(finalizerExit);
|
|
1853
|
-
}
|
|
1854
|
-
onExit(exit);
|
|
1855
|
-
});
|
|
1856
|
-
});
|
|
1857
|
-
})));
|
|
1962
|
+
export const ensuring = /*#__PURE__*/dual(2, (self, finalizer) => onExit(self, _ => finalizer));
|
|
1858
1963
|
/**
|
|
1859
|
-
*
|
|
1964
|
+
* When the `Micro` effect is completed, run the given finalizer effect if it
|
|
1965
|
+
* matches the specified predicate.
|
|
1860
1966
|
*
|
|
1861
|
-
* @since 3.4.
|
|
1967
|
+
* @since 3.4.6
|
|
1862
1968
|
* @experimental
|
|
1863
1969
|
* @category resources & finalization
|
|
1864
1970
|
*/
|
|
1865
|
-
export const
|
|
1971
|
+
export const onExitIf = /*#__PURE__*/dual(3, (self, refinement, f) => onExit(self, exit => refinement(exit) ? f(exit) : exitVoid));
|
|
1866
1972
|
/**
|
|
1867
1973
|
* When the `Micro` effect fails, run the given finalizer effect with the
|
|
1868
1974
|
* `MicroCause` of the executed effect.
|
|
@@ -1871,7 +1977,7 @@ export const ensuring = /*#__PURE__*/dual(2, (self, finalizer) => onExit(self, _
|
|
|
1871
1977
|
* @experimental
|
|
1872
1978
|
* @category resources & finalization
|
|
1873
1979
|
*/
|
|
1874
|
-
export const onError = /*#__PURE__*/dual(2, (self, f) => onExitIf(self, exitIsFailure, exit => f(exit.
|
|
1980
|
+
export const onError = /*#__PURE__*/dual(2, (self, f) => onExitIf(self, exitIsFailure, exit => f(exit.cause)));
|
|
1875
1981
|
/**
|
|
1876
1982
|
* If this `Micro` effect is aborted, run the finalizer effect.
|
|
1877
1983
|
*
|
|
@@ -1888,7 +1994,7 @@ export const onInterrupt = /*#__PURE__*/dual(2, (self, finalizer) => onExitIf(se
|
|
|
1888
1994
|
* @experimental
|
|
1889
1995
|
* @category resources & finalization
|
|
1890
1996
|
*/
|
|
1891
|
-
export const acquireUseRelease = (acquire, use, release) => uninterruptibleMask(restore => flatMap(acquire, a => flatMap(exit(restore(use(a))), exit => andThen(release(a, exit),
|
|
1997
|
+
export const acquireUseRelease = (acquire, use, release) => uninterruptibleMask(restore => flatMap(acquire, a => flatMap(exit(restore(use(a))), exit => andThen(release(a, exit), exit))));
|
|
1892
1998
|
// ----------------------------------------------------------------------------
|
|
1893
1999
|
// interruption
|
|
1894
2000
|
// ----------------------------------------------------------------------------
|
|
@@ -1899,27 +2005,45 @@ export const acquireUseRelease = (acquire, use, release) => uninterruptibleMask(
|
|
|
1899
2005
|
* @experimental
|
|
1900
2006
|
* @category interruption
|
|
1901
2007
|
*/
|
|
1902
|
-
export const interrupt = /*#__PURE__*/
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2008
|
+
export const interrupt = /*#__PURE__*/failCause( /*#__PURE__*/causeInterrupt());
|
|
2009
|
+
/**
|
|
2010
|
+
* Flag the effect as uninterruptible, which means that when the effect is
|
|
2011
|
+
* interrupted, it will be allowed to continue running until completion.
|
|
2012
|
+
*
|
|
2013
|
+
* @since 3.4.0
|
|
2014
|
+
* @experimental
|
|
2015
|
+
* @category flags
|
|
2016
|
+
*/
|
|
2017
|
+
export const uninterruptible = self => withFiber(fiber => {
|
|
2018
|
+
if (!fiber.interruptible) return self;
|
|
2019
|
+
fiber.interruptible = false;
|
|
2020
|
+
fiber._stack.push(setInterruptible(true));
|
|
2021
|
+
return self;
|
|
2022
|
+
});
|
|
2023
|
+
const setInterruptible = /*#__PURE__*/makePrimitive({
|
|
2024
|
+
op: "SetInterruptible",
|
|
2025
|
+
ensure(fiber) {
|
|
2026
|
+
fiber.interruptible = this[args];
|
|
2027
|
+
if (fiber._interrupted && fiber.interruptible) {
|
|
2028
|
+
return () => exitInterrupt;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
1906
2031
|
});
|
|
1907
2032
|
/**
|
|
1908
|
-
*
|
|
1909
|
-
*
|
|
2033
|
+
* Flag the effect as interruptible, which means that when the effect is
|
|
2034
|
+
* interrupted, it will be interrupted immediately.
|
|
1910
2035
|
*
|
|
1911
2036
|
* @since 3.4.0
|
|
1912
2037
|
* @experimental
|
|
1913
|
-
* @category
|
|
2038
|
+
* @category flags
|
|
1914
2039
|
*/
|
|
1915
|
-
export const
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
}, false);
|
|
2040
|
+
export const interruptible = self => withFiber(fiber => {
|
|
2041
|
+
if (fiber.interruptible) return self;
|
|
2042
|
+
fiber.interruptible = true;
|
|
2043
|
+
fiber._stack.push(setInterruptible(false));
|
|
2044
|
+
if (fiber._interrupted) return exitInterrupt;
|
|
2045
|
+
return self;
|
|
2046
|
+
});
|
|
1923
2047
|
/**
|
|
1924
2048
|
* Wrap the given `Micro` effect in an uninterruptible region, preventing the
|
|
1925
2049
|
* effect from being aborted.
|
|
@@ -1941,36 +2065,11 @@ export const uninterruptible = self => unsafeMakeOptions(function (env, onExit)
|
|
|
1941
2065
|
* )
|
|
1942
2066
|
* ```
|
|
1943
2067
|
*/
|
|
1944
|
-
export const uninterruptibleMask = f =>
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
env[currentAbortSignal.key] = new AbortController().signal;
|
|
1950
|
-
return env;
|
|
1951
|
-
}) : env;
|
|
1952
|
-
effect[runSymbol](nextEnv, onExit);
|
|
1953
|
-
}, false);
|
|
1954
|
-
/**
|
|
1955
|
-
* Wrap the given `Micro` effect in an interruptible region, allowing the effect
|
|
1956
|
-
* to be aborted.
|
|
1957
|
-
*
|
|
1958
|
-
* @since 3.4.0
|
|
1959
|
-
* @experimental
|
|
1960
|
-
* @category interruption
|
|
1961
|
-
*/
|
|
1962
|
-
export const interruptible = self => make((env, onExit) => {
|
|
1963
|
-
const isInterruptible = envGet(env, currentInterruptible);
|
|
1964
|
-
let newEnv = env;
|
|
1965
|
-
if (!isInterruptible) {
|
|
1966
|
-
const controller = envGet(env, currentAbortController);
|
|
1967
|
-
newEnv = envMutate(env, function (env) {
|
|
1968
|
-
env[currentInterruptible.key] = true;
|
|
1969
|
-
env[currentAbortSignal.key] = controller.signal;
|
|
1970
|
-
return env;
|
|
1971
|
-
});
|
|
1972
|
-
}
|
|
1973
|
-
self[runSymbol](newEnv, onExit);
|
|
2068
|
+
export const uninterruptibleMask = f => withFiber(fiber => {
|
|
2069
|
+
if (!fiber.interruptible) return f(identity);
|
|
2070
|
+
fiber.interruptible = false;
|
|
2071
|
+
fiber._stack.push(setInterruptible(true));
|
|
2072
|
+
return f(interruptible);
|
|
1974
2073
|
});
|
|
1975
2074
|
/**
|
|
1976
2075
|
* Runs all the provided effects in sequence respecting the structure provided in input.
|
|
@@ -1997,6 +2096,29 @@ export const all = (arg, options) => {
|
|
|
1997
2096
|
}), out);
|
|
1998
2097
|
});
|
|
1999
2098
|
};
|
|
2099
|
+
/**
|
|
2100
|
+
* @since 3.11.0
|
|
2101
|
+
* @experimental
|
|
2102
|
+
* @category collecting & elements
|
|
2103
|
+
*/
|
|
2104
|
+
export const whileLoop = /*#__PURE__*/makePrimitive({
|
|
2105
|
+
op: "While",
|
|
2106
|
+
contA(value, fiber) {
|
|
2107
|
+
this[args].step(value);
|
|
2108
|
+
if (this[args].while()) {
|
|
2109
|
+
fiber._stack.push(this);
|
|
2110
|
+
return this[args].body();
|
|
2111
|
+
}
|
|
2112
|
+
return exitVoid;
|
|
2113
|
+
},
|
|
2114
|
+
eval(fiber) {
|
|
2115
|
+
if (this[args].while()) {
|
|
2116
|
+
fiber._stack.push(this);
|
|
2117
|
+
return this[args].body();
|
|
2118
|
+
}
|
|
2119
|
+
return exitVoid;
|
|
2120
|
+
}
|
|
2121
|
+
});
|
|
2000
2122
|
/**
|
|
2001
2123
|
* For each element of the provided iterable, run the effect and collect the results.
|
|
2002
2124
|
*
|
|
@@ -2010,58 +2132,76 @@ export const all = (arg, options) => {
|
|
|
2010
2132
|
* @experimental
|
|
2011
2133
|
* @category collecting & elements
|
|
2012
2134
|
*/
|
|
2013
|
-
export const forEach = (iterable, f, options) =>
|
|
2014
|
-
const concurrencyOption = options?.concurrency === "inherit" ?
|
|
2135
|
+
export const forEach = (iterable, f, options) => withFiber(parent => {
|
|
2136
|
+
const concurrencyOption = options?.concurrency === "inherit" ? parent.getRef(CurrentConcurrency) : options?.concurrency ?? 1;
|
|
2015
2137
|
const concurrency = concurrencyOption === "unbounded" ? Number.POSITIVE_INFINITY : Math.max(1, concurrencyOption);
|
|
2016
|
-
|
|
2017
|
-
const [envWithSignal, onAbort] = forkSignal(env);
|
|
2018
|
-
// iterate
|
|
2019
|
-
let result = undefined;
|
|
2020
|
-
const items = Array.from(iterable);
|
|
2138
|
+
const items = Arr.fromIterable(iterable);
|
|
2021
2139
|
let length = items.length;
|
|
2022
2140
|
if (length === 0) {
|
|
2023
|
-
return
|
|
2141
|
+
return options?.discard ? void_ : succeed([]);
|
|
2024
2142
|
}
|
|
2025
2143
|
const out = options?.discard ? undefined : new Array(length);
|
|
2026
2144
|
let index = 0;
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2145
|
+
if (concurrency === 1) {
|
|
2146
|
+
return as(whileLoop({
|
|
2147
|
+
while: () => index < items.length,
|
|
2148
|
+
body: () => f(items[index], index),
|
|
2149
|
+
step: out ? b => out[index++] = b : _ => index++
|
|
2150
|
+
}), out);
|
|
2151
|
+
}
|
|
2152
|
+
return async(resume => {
|
|
2153
|
+
const fibers = new Set();
|
|
2154
|
+
let result = undefined;
|
|
2155
|
+
let inProgress = 0;
|
|
2156
|
+
let doneCount = 0;
|
|
2157
|
+
let pumping = false;
|
|
2158
|
+
let interrupted = false;
|
|
2159
|
+
function pump() {
|
|
2160
|
+
pumping = true;
|
|
2161
|
+
while (inProgress < concurrency && index < length) {
|
|
2162
|
+
const currentIndex = index;
|
|
2163
|
+
const item = items[currentIndex];
|
|
2164
|
+
index++;
|
|
2165
|
+
inProgress++;
|
|
2166
|
+
try {
|
|
2167
|
+
const child = unsafeFork(parent, f(item, currentIndex), true, true);
|
|
2168
|
+
fibers.add(child);
|
|
2169
|
+
child.addObserver(exit => {
|
|
2170
|
+
fibers.delete(child);
|
|
2171
|
+
if (interrupted) {
|
|
2172
|
+
return;
|
|
2173
|
+
} else if (exit._tag === "Failure") {
|
|
2174
|
+
if (result === undefined) {
|
|
2175
|
+
result = exit;
|
|
2176
|
+
length = index;
|
|
2177
|
+
fibers.forEach(fiber => fiber.unsafeInterrupt());
|
|
2178
|
+
}
|
|
2179
|
+
} else if (out !== undefined) {
|
|
2180
|
+
out[currentIndex] = exit.value;
|
|
2044
2181
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
length = index;
|
|
2059
|
-
onAbort();
|
|
2182
|
+
doneCount++;
|
|
2183
|
+
inProgress--;
|
|
2184
|
+
if (doneCount === length) {
|
|
2185
|
+
resume(result ?? succeed(out));
|
|
2186
|
+
} else if (!pumping && inProgress < concurrency) {
|
|
2187
|
+
pump();
|
|
2188
|
+
}
|
|
2189
|
+
});
|
|
2190
|
+
} catch (err) {
|
|
2191
|
+
result = exitDie(err);
|
|
2192
|
+
length = index;
|
|
2193
|
+
fibers.forEach(fiber => fiber.unsafeInterrupt());
|
|
2194
|
+
}
|
|
2060
2195
|
}
|
|
2196
|
+
pumping = false;
|
|
2061
2197
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2198
|
+
pump();
|
|
2199
|
+
return suspend(() => {
|
|
2200
|
+
interrupted = true;
|
|
2201
|
+
index = length;
|
|
2202
|
+
return fiberInterruptAll(fibers);
|
|
2203
|
+
});
|
|
2204
|
+
});
|
|
2065
2205
|
});
|
|
2066
2206
|
/**
|
|
2067
2207
|
* Effectfully filter the elements of the provided iterable.
|
|
@@ -2134,92 +2274,8 @@ export {
|
|
|
2134
2274
|
*/
|
|
2135
2275
|
let_ as let };
|
|
2136
2276
|
// ----------------------------------------------------------------------------
|
|
2137
|
-
//
|
|
2277
|
+
// fibers & forking
|
|
2138
2278
|
// ----------------------------------------------------------------------------
|
|
2139
|
-
/**
|
|
2140
|
-
* @since 3.4.0
|
|
2141
|
-
* @experimental
|
|
2142
|
-
* @category handle & forking
|
|
2143
|
-
*/
|
|
2144
|
-
export const HandleTypeId = /*#__PURE__*/Symbol.for("effect/Micro/Handle");
|
|
2145
|
-
/**
|
|
2146
|
-
* @since 3.4.0
|
|
2147
|
-
* @experimental
|
|
2148
|
-
* @category handle & forking
|
|
2149
|
-
*/
|
|
2150
|
-
export const isHandle = u => typeof u === "object" && u !== null && HandleTypeId in u;
|
|
2151
|
-
class HandleImpl extends Class {
|
|
2152
|
-
parentSignal;
|
|
2153
|
-
[HandleTypeId];
|
|
2154
|
-
observers = /*#__PURE__*/new Set();
|
|
2155
|
-
_exit = undefined;
|
|
2156
|
-
_controller;
|
|
2157
|
-
isRoot;
|
|
2158
|
-
constructor(parentSignal, controller) {
|
|
2159
|
-
super();
|
|
2160
|
-
this.parentSignal = parentSignal;
|
|
2161
|
-
this[HandleTypeId] = HandleTypeId;
|
|
2162
|
-
this.isRoot = controller !== undefined;
|
|
2163
|
-
this._controller = controller ?? new AbortController();
|
|
2164
|
-
if (!this.isRoot) {
|
|
2165
|
-
parentSignal.addEventListener("abort", this.unsafeInterrupt);
|
|
2166
|
-
}
|
|
2167
|
-
}
|
|
2168
|
-
unsafePoll() {
|
|
2169
|
-
return this._exit ?? null;
|
|
2170
|
-
}
|
|
2171
|
-
unsafeInterrupt = () => {
|
|
2172
|
-
this._controller.abort();
|
|
2173
|
-
};
|
|
2174
|
-
emit(exit) {
|
|
2175
|
-
if (this._exit) {
|
|
2176
|
-
return;
|
|
2177
|
-
}
|
|
2178
|
-
this._exit = exit;
|
|
2179
|
-
if (!this.isRoot) {
|
|
2180
|
-
this.parentSignal.removeEventListener("abort", this.unsafeInterrupt);
|
|
2181
|
-
}
|
|
2182
|
-
this.observers.forEach(observer => observer(exit));
|
|
2183
|
-
this.observers.clear();
|
|
2184
|
-
}
|
|
2185
|
-
addObserver(observer) {
|
|
2186
|
-
if (this._exit) {
|
|
2187
|
-
return observer(this._exit);
|
|
2188
|
-
}
|
|
2189
|
-
this.observers.add(observer);
|
|
2190
|
-
}
|
|
2191
|
-
removeObserver(observer) {
|
|
2192
|
-
this.observers.delete(observer);
|
|
2193
|
-
}
|
|
2194
|
-
get await() {
|
|
2195
|
-
return suspend(() => {
|
|
2196
|
-
if (this._exit) {
|
|
2197
|
-
return succeed(this._exit);
|
|
2198
|
-
}
|
|
2199
|
-
return async(resume => {
|
|
2200
|
-
function observer(exit) {
|
|
2201
|
-
resume(succeed(exit));
|
|
2202
|
-
}
|
|
2203
|
-
this.addObserver(observer);
|
|
2204
|
-
return sync(() => {
|
|
2205
|
-
this.removeObserver(observer);
|
|
2206
|
-
});
|
|
2207
|
-
});
|
|
2208
|
-
});
|
|
2209
|
-
}
|
|
2210
|
-
get join() {
|
|
2211
|
-
return flatMap(this.await, fromExit);
|
|
2212
|
-
}
|
|
2213
|
-
get interrupt() {
|
|
2214
|
-
return suspend(() => {
|
|
2215
|
-
this.unsafeInterrupt();
|
|
2216
|
-
return this.await;
|
|
2217
|
-
});
|
|
2218
|
-
}
|
|
2219
|
-
asMicro() {
|
|
2220
|
-
return this.join;
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
2279
|
/**
|
|
2224
2280
|
* Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
|
|
2225
2281
|
* aborted.
|
|
@@ -2230,21 +2286,23 @@ class HandleImpl extends Class {
|
|
|
2230
2286
|
* @experimental
|
|
2231
2287
|
* @category handle & forking
|
|
2232
2288
|
*/
|
|
2233
|
-
export const fork = self =>
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
const nextEnv = envMutate(env, map => {
|
|
2237
|
-
map[currentAbortController.key] = handle._controller;
|
|
2238
|
-
map[currentAbortSignal.key] = handle._controller.signal;
|
|
2239
|
-
return map;
|
|
2240
|
-
});
|
|
2241
|
-
envGet(env, currentScheduler).scheduleTask(() => {
|
|
2242
|
-
self[runSymbol](nextEnv, exit => {
|
|
2243
|
-
handle.emit(exit);
|
|
2244
|
-
});
|
|
2245
|
-
}, 0);
|
|
2246
|
-
onExit(Either.right(handle));
|
|
2289
|
+
export const fork = self => withFiber(fiber => {
|
|
2290
|
+
fiberMiddleware.interruptChildren ??= fiberInterruptChildren;
|
|
2291
|
+
return succeed(unsafeFork(fiber, self));
|
|
2247
2292
|
});
|
|
2293
|
+
const unsafeFork = (parent, effect, immediate = false, daemon = false) => {
|
|
2294
|
+
const child = new FiberImpl(parent.context, parent.interruptible);
|
|
2295
|
+
if (!daemon) {
|
|
2296
|
+
parent.children().add(child);
|
|
2297
|
+
child.addObserver(() => parent.children().delete(child));
|
|
2298
|
+
}
|
|
2299
|
+
if (immediate) {
|
|
2300
|
+
child.evaluate(effect);
|
|
2301
|
+
} else {
|
|
2302
|
+
parent.getRef(CurrentScheduler).scheduleTask(() => child.evaluate(effect), 0);
|
|
2303
|
+
}
|
|
2304
|
+
return child;
|
|
2305
|
+
};
|
|
2248
2306
|
/**
|
|
2249
2307
|
* Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
|
|
2250
2308
|
* aborted.
|
|
@@ -2255,21 +2313,7 @@ export const fork = self => make(function (env, onExit) {
|
|
|
2255
2313
|
* @experimental
|
|
2256
2314
|
* @category handle & forking
|
|
2257
2315
|
*/
|
|
2258
|
-
export const forkDaemon = self =>
|
|
2259
|
-
const controller = new AbortController();
|
|
2260
|
-
const handle = new HandleImpl(controller.signal, controller);
|
|
2261
|
-
const nextEnv = envMutate(env, map => {
|
|
2262
|
-
map[currentAbortController.key] = controller;
|
|
2263
|
-
map[currentAbortSignal.key] = controller.signal;
|
|
2264
|
-
return map;
|
|
2265
|
-
});
|
|
2266
|
-
envGet(env, currentScheduler).scheduleTask(() => {
|
|
2267
|
-
self[runSymbol](nextEnv, exit => {
|
|
2268
|
-
handle.emit(exit);
|
|
2269
|
-
});
|
|
2270
|
-
}, 0);
|
|
2271
|
-
onExit(Either.right(handle));
|
|
2272
|
-
});
|
|
2316
|
+
export const forkDaemon = self => withFiber(fiber => succeed(unsafeFork(fiber, self, false, true)));
|
|
2273
2317
|
/**
|
|
2274
2318
|
* Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
|
|
2275
2319
|
* aborted.
|
|
@@ -2280,7 +2324,7 @@ export const forkDaemon = self => make(function (env, onExit) {
|
|
|
2280
2324
|
* @experimental
|
|
2281
2325
|
* @category handle & forking
|
|
2282
2326
|
*/
|
|
2283
|
-
export const forkIn = /*#__PURE__*/dual(2, (self, scope) => uninterruptibleMask(restore => flatMap(scope.fork, scope => tap(restore(forkDaemon(onExit(self, exit => scope.close(exit)))), fiber => scope.addFinalizer(_ =>
|
|
2327
|
+
export const forkIn = /*#__PURE__*/dual(2, (self, scope) => uninterruptibleMask(restore => flatMap(scope.fork, scope => tap(restore(forkDaemon(onExit(self, exit => scope.close(exit)))), fiber => scope.addFinalizer(_ => fiberInterrupt(fiber))))));
|
|
2284
2328
|
/**
|
|
2285
2329
|
* Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
|
|
2286
2330
|
* aborted.
|
|
@@ -2320,29 +2364,20 @@ export const forkScoped = self => flatMap(scope, scope => forkIn(self, scope));
|
|
|
2320
2364
|
* ```
|
|
2321
2365
|
*/
|
|
2322
2366
|
export const runFork = (effect, options) => {
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2325
|
-
refs[currentAbortController.key] = controller;
|
|
2326
|
-
refs[currentAbortSignal.key] = controller.signal;
|
|
2327
|
-
refs[currentScheduler.key] = options?.scheduler ?? new MicroSchedulerDefault();
|
|
2328
|
-
const env = envMake(refs);
|
|
2329
|
-
const handle = new HandleImpl(controller.signal, controller);
|
|
2330
|
-
effect[runSymbol](envSet(env, currentAbortSignal, handle._controller.signal), exit => {
|
|
2331
|
-
handle.emit(exit);
|
|
2332
|
-
if (options?.signal) {
|
|
2333
|
-
options.signal.removeEventListener("abort", handle.unsafeInterrupt);
|
|
2334
|
-
}
|
|
2335
|
-
});
|
|
2367
|
+
const fiber = new FiberImpl(CurrentScheduler.context(options?.scheduler ?? new MicroSchedulerDefault()));
|
|
2368
|
+
fiber.evaluate(effect);
|
|
2336
2369
|
if (options?.signal) {
|
|
2337
2370
|
if (options.signal.aborted) {
|
|
2338
|
-
|
|
2371
|
+
fiber.unsafeInterrupt();
|
|
2339
2372
|
} else {
|
|
2340
|
-
|
|
2373
|
+
const abort = () => fiber.unsafeInterrupt();
|
|
2374
|
+
options.signal.addEventListener("abort", abort, {
|
|
2341
2375
|
once: true
|
|
2342
2376
|
});
|
|
2377
|
+
fiber.addObserver(() => options.signal.removeEventListener("abort", abort));
|
|
2343
2378
|
}
|
|
2344
2379
|
}
|
|
2345
|
-
return
|
|
2380
|
+
return fiber;
|
|
2346
2381
|
};
|
|
2347
2382
|
/**
|
|
2348
2383
|
* Execute the `Micro` effect and return a `Promise` that resolves with the
|
|
@@ -2365,10 +2400,10 @@ export const runPromiseExit = (effect, options) => new Promise((resolve, _reject
|
|
|
2365
2400
|
* @category execution
|
|
2366
2401
|
*/
|
|
2367
2402
|
export const runPromise = (effect, options) => runPromiseExit(effect, options).then(exit => {
|
|
2368
|
-
if (exit._tag === "
|
|
2369
|
-
throw exit.
|
|
2403
|
+
if (exit._tag === "Failure") {
|
|
2404
|
+
throw exit.cause;
|
|
2370
2405
|
}
|
|
2371
|
-
return exit.
|
|
2406
|
+
return exit.value;
|
|
2372
2407
|
});
|
|
2373
2408
|
/**
|
|
2374
2409
|
* Attempt to execute the `Micro` effect synchronously and return the `MicroExit`.
|
|
@@ -2382,15 +2417,11 @@ export const runPromise = (effect, options) => runPromiseExit(effect, options).t
|
|
|
2382
2417
|
*/
|
|
2383
2418
|
export const runSyncExit = effect => {
|
|
2384
2419
|
const scheduler = new MicroSchedulerDefault();
|
|
2385
|
-
const
|
|
2420
|
+
const fiber = runFork(effect, {
|
|
2386
2421
|
scheduler
|
|
2387
2422
|
});
|
|
2388
2423
|
scheduler.flush();
|
|
2389
|
-
|
|
2390
|
-
if (exit === null) {
|
|
2391
|
-
return exitDie(handle);
|
|
2392
|
-
}
|
|
2393
|
-
return exit;
|
|
2424
|
+
return fiber._exit ?? exitDie(fiber);
|
|
2394
2425
|
};
|
|
2395
2426
|
/**
|
|
2396
2427
|
* Attempt to execute the `Micro` effect synchronously and return the success
|
|
@@ -2402,24 +2433,24 @@ export const runSyncExit = effect => {
|
|
|
2402
2433
|
*/
|
|
2403
2434
|
export const runSync = effect => {
|
|
2404
2435
|
const exit = runSyncExit(effect);
|
|
2405
|
-
if (exit._tag === "
|
|
2406
|
-
|
|
2407
|
-
}
|
|
2408
|
-
return exit.right;
|
|
2436
|
+
if (exit._tag === "Failure") throw exit.cause;
|
|
2437
|
+
return exit.value;
|
|
2409
2438
|
};
|
|
2410
2439
|
const YieldableError = /*#__PURE__*/function () {
|
|
2411
|
-
class YieldableError extends globalThis.Error {
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2440
|
+
class YieldableError extends globalThis.Error {}
|
|
2441
|
+
Object.assign(YieldableError.prototype, MicroProto, StructuralPrototype, {
|
|
2442
|
+
[identifier]: "Failure",
|
|
2443
|
+
[evaluate]() {
|
|
2444
|
+
return fail(this);
|
|
2445
|
+
},
|
|
2415
2446
|
toString() {
|
|
2416
2447
|
return this.message ? `${this.name}: ${this.message}` : this.name;
|
|
2417
|
-
}
|
|
2448
|
+
},
|
|
2418
2449
|
toJSON() {
|
|
2419
2450
|
return {
|
|
2420
2451
|
...this
|
|
2421
2452
|
};
|
|
2422
|
-
}
|
|
2453
|
+
},
|
|
2423
2454
|
[NodeInspectSymbol]() {
|
|
2424
2455
|
const stack = this.stack;
|
|
2425
2456
|
if (stack) {
|
|
@@ -2427,8 +2458,7 @@ const YieldableError = /*#__PURE__*/function () {
|
|
|
2427
2458
|
}
|
|
2428
2459
|
return this.toString();
|
|
2429
2460
|
}
|
|
2430
|
-
}
|
|
2431
|
-
Object.assign(YieldableError.prototype, MicroProto, StructuralPrototype);
|
|
2461
|
+
});
|
|
2432
2462
|
return YieldableError;
|
|
2433
2463
|
}();
|
|
2434
2464
|
/**
|