effect 3.3.5 → 3.4.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.
Files changed (98) hide show
  1. package/Micro/package.json +6 -0
  2. package/dist/cjs/Array.js +18 -3
  3. package/dist/cjs/Array.js.map +1 -1
  4. package/dist/cjs/Chunk.js +13 -2
  5. package/dist/cjs/Chunk.js.map +1 -1
  6. package/dist/cjs/Effect.js +110 -8
  7. package/dist/cjs/Effect.js.map +1 -1
  8. package/dist/cjs/Either.js +31 -1
  9. package/dist/cjs/Either.js.map +1 -1
  10. package/dist/cjs/ManagedRuntime.js.map +1 -1
  11. package/dist/cjs/Micro.js +2383 -0
  12. package/dist/cjs/Micro.js.map +1 -0
  13. package/dist/cjs/Option.js +1 -2
  14. package/dist/cjs/Option.js.map +1 -1
  15. package/dist/cjs/Schedule.js +2 -2
  16. package/dist/cjs/Stream.js.map +1 -1
  17. package/dist/cjs/Tuple.js +16 -9
  18. package/dist/cjs/Tuple.js.map +1 -1
  19. package/dist/cjs/index.js +4 -2
  20. package/dist/cjs/index.js.map +1 -1
  21. package/dist/cjs/internal/core-effect.js +4 -2
  22. package/dist/cjs/internal/core-effect.js.map +1 -1
  23. package/dist/cjs/internal/core.js +12 -2
  24. package/dist/cjs/internal/core.js.map +1 -1
  25. package/dist/cjs/internal/fiberRuntime.js +32 -0
  26. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  27. package/dist/cjs/internal/stream.js.map +1 -1
  28. package/dist/cjs/internal/version.js +1 -1
  29. package/dist/dts/Array.d.ts +14 -0
  30. package/dist/dts/Array.d.ts.map +1 -1
  31. package/dist/dts/Cause.d.ts +1 -1
  32. package/dist/dts/Chunk.d.ts +11 -0
  33. package/dist/dts/Chunk.d.ts.map +1 -1
  34. package/dist/dts/Effect.d.ts +109 -5
  35. package/dist/dts/Effect.d.ts.map +1 -1
  36. package/dist/dts/Either.d.ts +35 -0
  37. package/dist/dts/Either.d.ts.map +1 -1
  38. package/dist/dts/ManagedRuntime.d.ts +15 -0
  39. package/dist/dts/ManagedRuntime.d.ts.map +1 -1
  40. package/dist/dts/Micro.d.ts +2002 -0
  41. package/dist/dts/Micro.d.ts.map +1 -0
  42. package/dist/dts/Option.d.ts +2 -0
  43. package/dist/dts/Option.d.ts.map +1 -1
  44. package/dist/dts/Schedule.d.ts +2 -2
  45. package/dist/dts/Stream.d.ts +45 -6
  46. package/dist/dts/Stream.d.ts.map +1 -1
  47. package/dist/dts/Tuple.d.ts +18 -0
  48. package/dist/dts/Tuple.d.ts.map +1 -1
  49. package/dist/dts/index.d.ts +7 -0
  50. package/dist/dts/index.d.ts.map +1 -1
  51. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  52. package/dist/dts/internal/core.d.ts.map +1 -1
  53. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  54. package/dist/esm/Array.js +14 -0
  55. package/dist/esm/Array.js.map +1 -1
  56. package/dist/esm/Chunk.js +11 -0
  57. package/dist/esm/Chunk.js.map +1 -1
  58. package/dist/esm/Effect.js +107 -5
  59. package/dist/esm/Effect.js.map +1 -1
  60. package/dist/esm/Either.js +30 -0
  61. package/dist/esm/Either.js.map +1 -1
  62. package/dist/esm/ManagedRuntime.js.map +1 -1
  63. package/dist/esm/Micro.js +2307 -0
  64. package/dist/esm/Micro.js.map +1 -0
  65. package/dist/esm/Option.js +1 -1
  66. package/dist/esm/Option.js.map +1 -1
  67. package/dist/esm/Schedule.js +2 -2
  68. package/dist/esm/Stream.js.map +1 -1
  69. package/dist/esm/Tuple.js +15 -8
  70. package/dist/esm/Tuple.js.map +1 -1
  71. package/dist/esm/index.js +7 -0
  72. package/dist/esm/index.js.map +1 -1
  73. package/dist/esm/internal/core-effect.js +2 -0
  74. package/dist/esm/internal/core-effect.js.map +1 -1
  75. package/dist/esm/internal/core.js +10 -1
  76. package/dist/esm/internal/core.js.map +1 -1
  77. package/dist/esm/internal/fiberRuntime.js +32 -0
  78. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  79. package/dist/esm/internal/stream.js.map +1 -1
  80. package/dist/esm/internal/version.js +1 -1
  81. package/package.json +9 -1
  82. package/src/Array.ts +15 -0
  83. package/src/Cause.ts +1 -1
  84. package/src/Chunk.ts +12 -0
  85. package/src/Effect.ts +117 -5
  86. package/src/Either.ts +51 -0
  87. package/src/ManagedRuntime.ts +16 -0
  88. package/src/Micro.ts +3826 -0
  89. package/src/Option.ts +12 -1
  90. package/src/Schedule.ts +2 -2
  91. package/src/Stream.ts +60 -8
  92. package/src/Tuple.ts +18 -8
  93. package/src/index.ts +8 -0
  94. package/src/internal/core-effect.ts +33 -0
  95. package/src/internal/core.ts +18 -1
  96. package/src/internal/fiberRuntime.ts +32 -0
  97. package/src/internal/stream.ts +8 -4
  98. package/src/internal/version.ts +1 -1
@@ -0,0 +1,2307 @@
1
+ import * as Context from "./Context.js";
2
+ import * as Effectable from "./Effectable.js";
3
+ import * as Either from "./Either.js";
4
+ import { constTrue, constVoid, dual, identity } from "./Function.js";
5
+ import { globalValue } from "./GlobalValue.js";
6
+ import { NodeInspectSymbol, toStringUnknown } from "./Inspectable.js";
7
+ import { StructuralPrototype } from "./internal/effectable.js";
8
+ import { SingleShotGen } from "./internal/singleShotGen.js";
9
+ import * as Option from "./Option.js";
10
+ import { pipeArguments } from "./Pipeable.js";
11
+ import { isIterable, isTagged } from "./Predicate.js";
12
+ import { YieldWrap, yieldWrapGet } from "./Utils.js";
13
+ /**
14
+ * @since 3.4.0
15
+ * @experimental
16
+ * @category type ids
17
+ */
18
+ export const TypeId = /*#__PURE__*/Symbol.for("effect/Micro");
19
+ /**
20
+ * @since 3.4.0
21
+ * @experimental
22
+ * @category symbols
23
+ */
24
+ export const runSymbol = /*#__PURE__*/Symbol.for("effect/Micro/runSymbol");
25
+ /**
26
+ * @since 3.4.0
27
+ * @experimental
28
+ * @category guards
29
+ */
30
+ export const isMicro = u => typeof u === "object" && u !== null && TypeId in u;
31
+ // ----------------------------------------------------------------------------
32
+ // Failures
33
+ // ----------------------------------------------------------------------------
34
+ /**
35
+ * @since 3.4.0
36
+ * @experimental
37
+ * @category failure
38
+ */
39
+ export const FailureTypeId = /*#__PURE__*/Symbol.for("effect/Micro/Failure");
40
+ const failureVariance = {
41
+ _E: identity
42
+ };
43
+ class FailureImpl extends globalThis.Error {
44
+ _tag;
45
+ traces;
46
+ [FailureTypeId];
47
+ constructor(_tag, originalError, traces) {
48
+ const failureName = `Failure${_tag}`;
49
+ let name;
50
+ let message;
51
+ let stack;
52
+ if (originalError instanceof globalThis.Error) {
53
+ name = `(${failureName}) ${originalError.name}`;
54
+ message = originalError.message;
55
+ const messageLines = message.split("\n").length;
56
+ stack = originalError.stack ? `(${failureName}) ${originalError.stack.split("\n").slice(0, messageLines + 3).join("\n")}` : `${name}: ${message}`;
57
+ } else {
58
+ name = failureName;
59
+ message = toStringUnknown(originalError, 0);
60
+ stack = `${name}: ${message}`;
61
+ }
62
+ if (traces.length > 0) {
63
+ stack += `\n ${traces.join("\n ")}`;
64
+ }
65
+ super(message);
66
+ this._tag = _tag;
67
+ this.traces = traces;
68
+ this[FailureTypeId] = failureVariance;
69
+ this.name = name;
70
+ this.stack = stack;
71
+ }
72
+ pipe() {
73
+ return pipeArguments(this, arguments);
74
+ }
75
+ toString() {
76
+ return this.stack;
77
+ }
78
+ [NodeInspectSymbol]() {
79
+ return this.stack;
80
+ }
81
+ }
82
+ class FailureExpectedImpl extends FailureImpl {
83
+ error;
84
+ constructor(error, traces = []) {
85
+ super("Expected", error, traces);
86
+ this.error = error;
87
+ }
88
+ }
89
+ /**
90
+ * @since 3.4.0
91
+ * @experimental
92
+ * @category failure
93
+ */
94
+ export const FailureExpected = (error, traces = []) => new FailureExpectedImpl(error, traces);
95
+ class FailureUnexpectedImpl extends FailureImpl {
96
+ defect;
97
+ constructor(defect, traces = []) {
98
+ super("Unexpected", defect, traces);
99
+ this.defect = defect;
100
+ }
101
+ }
102
+ /**
103
+ * @since 3.4.0
104
+ * @experimental
105
+ * @category failure
106
+ */
107
+ export const FailureUnexpected = (defect, traces = []) => new FailureUnexpectedImpl(defect, traces);
108
+ class FailureAbortedImpl extends FailureImpl {
109
+ constructor(traces = []) {
110
+ super("Aborted", "aborted", traces);
111
+ }
112
+ }
113
+ /**
114
+ * @since 3.4.0
115
+ * @experimental
116
+ * @category failure
117
+ */
118
+ export const FailureAborted = (traces = []) => new FailureAbortedImpl(traces);
119
+ /**
120
+ * @since 3.4.0
121
+ * @experimental
122
+ * @category failure
123
+ */
124
+ export const failureIsExpected = self => self._tag === "Expected";
125
+ /**
126
+ * @since 3.4.0
127
+ * @experimental
128
+ * @category failure
129
+ */
130
+ export const failureIsUnexpected = self => self._tag === "Unexpected";
131
+ /**
132
+ * @since 3.4.0
133
+ * @experimental
134
+ * @category failure
135
+ */
136
+ export const failureIsAborted = self => self._tag === "Aborted";
137
+ /**
138
+ * @since 3.4.0
139
+ * @experimental
140
+ * @category failure
141
+ */
142
+ export const failureSquash = self => self._tag === "Expected" ? self.error : self._tag === "Unexpected" ? self.defect : self;
143
+ /**
144
+ * @since 3.4.0
145
+ * @experimental
146
+ * @category failure
147
+ */
148
+ export const failureWithTrace = /*#__PURE__*/dual(2, (self, trace) => {
149
+ if (self._tag === "Expected") {
150
+ return FailureExpected(self.error, [...self.traces, trace]);
151
+ } else if (self._tag === "Unexpected") {
152
+ return FailureUnexpected(self.defect, [...self.traces, trace]);
153
+ }
154
+ return FailureAborted([...self.traces, trace]);
155
+ });
156
+ /**
157
+ * @since 3.4.0
158
+ * @experimental
159
+ * @category result
160
+ */
161
+ export const ResultAborted = /*#__PURE__*/Either.left( /*#__PURE__*/FailureAborted());
162
+ /**
163
+ * @since 3.4.0
164
+ * @experimental
165
+ * @category result
166
+ */
167
+ export const ResultSuccess = Either.right;
168
+ /**
169
+ * @since 3.4.0
170
+ * @experimental
171
+ * @category result
172
+ */
173
+ export const ResultFail = e => Either.left(FailureExpected(e));
174
+ /**
175
+ * @since 3.4.0
176
+ * @experimental
177
+ * @category result
178
+ */
179
+ export const ResultFailUnexpected = defect => Either.left(FailureUnexpected(defect));
180
+ /**
181
+ * @since 3.4.0
182
+ * @experimental
183
+ * @category result
184
+ */
185
+ export const ResultFailWith = Either.left;
186
+ /**
187
+ * @since 3.4.0
188
+ * @experimental
189
+ * @category result
190
+ */
191
+ export const resultIsSuccess = Either.isRight;
192
+ /**
193
+ * @since 3.4.0
194
+ * @experimental
195
+ * @category result
196
+ */
197
+ export const resultIsFailure = Either.isLeft;
198
+ /**
199
+ * @since 3.4.0
200
+ * @experimental
201
+ * @category result
202
+ */
203
+ export const resultIsAborted = self => resultIsFailure(self) && self.left._tag === "Aborted";
204
+ /**
205
+ * @since 3.4.0
206
+ * @experimental
207
+ * @category result
208
+ */
209
+ export const resultIsFailureExpected = self => resultIsFailure(self) && self.left._tag === "Expected";
210
+ /**
211
+ * @since 3.4.0
212
+ * @experimental
213
+ * @category result
214
+ */
215
+ export const resultIsFailureUnexpected = self => resultIsFailure(self) && self.left._tag === "Unexpected";
216
+ /**
217
+ * @since 3.4.0
218
+ * @experimental
219
+ * @category result
220
+ */
221
+ export const resultVoid = /*#__PURE__*/ResultSuccess(void 0);
222
+ // ----------------------------------------------------------------------------
223
+ // env
224
+ // ----------------------------------------------------------------------------
225
+ /**
226
+ * @since 3.4.0
227
+ * @experimental
228
+ * @category environment
229
+ */
230
+ export const EnvTypeId = /*#__PURE__*/Symbol.for("effect/Micro/Env");
231
+ /**
232
+ * @since 3.4.0
233
+ * @experimental
234
+ * @category environment
235
+ */
236
+ export const EnvRefTypeId = /*#__PURE__*/Symbol.for("effect/Micro/EnvRef");
237
+ const EnvProto = {
238
+ [EnvTypeId]: {
239
+ _R: identity
240
+ },
241
+ pipe() {
242
+ return pipeArguments(this, arguments);
243
+ }
244
+ };
245
+ /**
246
+ * @since 3.4.0
247
+ * @experimental
248
+ * @category environment
249
+ */
250
+ export const envMake = refs => {
251
+ const self = Object.create(EnvProto);
252
+ self.refs = refs;
253
+ return self;
254
+ };
255
+ /**
256
+ * @since 3.4.0
257
+ * @experimental
258
+ * @category environment
259
+ */
260
+ export const envUnsafeMakeEmpty = () => {
261
+ const controller = new AbortController();
262
+ const refs = Object.create(null);
263
+ refs[currentAbortController.key] = controller;
264
+ refs[currentAbortSignal.key] = controller.signal;
265
+ return envMake(refs);
266
+ };
267
+ /**
268
+ * @since 3.4.0
269
+ * @experimental
270
+ * @category environment
271
+ */
272
+ export const envGet = /*#__PURE__*/dual(2, (self, ref) => ref.key in self.refs ? self.refs[ref.key] : ref.initial);
273
+ /**
274
+ * @since 3.4.0
275
+ * @experimental
276
+ * @category environment
277
+ */
278
+ export const envSet = /*#__PURE__*/dual(3, (self, ref, value) => {
279
+ const refs = Object.assign(Object.create(null), self.refs);
280
+ refs[ref.key] = value;
281
+ return envMake(refs);
282
+ });
283
+ /**
284
+ * @since 3.4.0
285
+ * @experimental
286
+ * @category environment
287
+ */
288
+ export const envMutate = /*#__PURE__*/dual(2, (self, f) => envMake(f(Object.assign(Object.create(null), self.refs))));
289
+ /**
290
+ * Access the given `Context.Tag` from the environment.
291
+ *
292
+ * @since 3.4.0
293
+ * @experimental
294
+ * @category environment
295
+ */
296
+ export const service = tag => make(function (env, onResult) {
297
+ onResult(ResultSuccess(Context.get(envGet(env, currentContext), tag)));
298
+ });
299
+ /**
300
+ * Access the given `Context.Tag` from the environment, without tracking the
301
+ * dependency at the type level.
302
+ *
303
+ * It will return an `Option` of the service, depending on whether it is
304
+ * available in the environment or not.
305
+ *
306
+ * @since 3.4.0
307
+ * @experimental
308
+ * @category environment
309
+ */
310
+ export const serviceOption = tag => make(function (env, onResult) {
311
+ onResult(ResultSuccess(Context.getOption(envGet(env, currentContext), tag)));
312
+ });
313
+ /**
314
+ * Retrieve the current value of the given `EnvRef`.
315
+ *
316
+ * @since 3.4.0
317
+ * @experimental
318
+ * @category environment
319
+ */
320
+ export const getEnvRef = envRef => make((env, onResult) => onResult(Either.right(envGet(env, envRef))));
321
+ /**
322
+ * Set the value of the given `EnvRef` for the duration of the effect.
323
+ *
324
+ * @since 3.4.0
325
+ * @experimental
326
+ * @category environment
327
+ */
328
+ export const locally = /*#__PURE__*/dual(3, (self, fiberRef, value) => make((env, onResult) => self[runSymbol](envSet(env, fiberRef, value), onResult)));
329
+ /**
330
+ * Access the current `Context` from the environment.
331
+ *
332
+ * @since 3.4.0
333
+ * @experimental
334
+ * @category environment
335
+ */
336
+ export const context = () => getEnvRef(currentContext);
337
+ /**
338
+ * Merge the given `Context` with the current context.
339
+ *
340
+ * @since 3.4.0
341
+ * @experimental
342
+ * @category environment
343
+ */
344
+ export const provideContext = /*#__PURE__*/dual(2, (self, provided) => make(function (env, onResult) {
345
+ const context = envGet(env, currentContext);
346
+ const nextEnv = envSet(env, currentContext, Context.merge(context, provided));
347
+ self[runSymbol](nextEnv, onResult);
348
+ }));
349
+ /**
350
+ * Add the provided service to the current context.
351
+ *
352
+ * @since 3.4.0
353
+ * @experimental
354
+ * @category environment
355
+ */
356
+ export const provideService = /*#__PURE__*/dual(3, (self, tag, service) => make(function (env, onResult) {
357
+ const context = envGet(env, currentContext);
358
+ const nextEnv = envSet(env, currentContext, Context.add(context, tag, service));
359
+ self[runSymbol](nextEnv, onResult);
360
+ }));
361
+ /**
362
+ * Create a service using the provided `Micro` effect, and add it to the
363
+ * current context.
364
+ *
365
+ * @since 3.4.0
366
+ * @experimental
367
+ * @category environment
368
+ */
369
+ export const provideServiceMicro = /*#__PURE__*/dual(3, (self, tag, acquire) => flatMap(acquire, service => provideService(self, tag, service)));
370
+ // ========================================================================
371
+ // Env refs
372
+ // ========================================================================
373
+ const EnvRefProto = {
374
+ [EnvRefTypeId]: EnvRefTypeId
375
+ };
376
+ /**
377
+ * @since 3.4.0
378
+ * @experimental
379
+ * @category environment refs
380
+ */
381
+ export const envRefMake = (key, initial) => globalValue(key, () => {
382
+ const self = Object.create(EnvRefProto);
383
+ self.key = key;
384
+ self.initial = initial();
385
+ return self;
386
+ });
387
+ /**
388
+ * @since 3.4.0
389
+ * @experimental
390
+ * @category environment refs
391
+ */
392
+ export const currentAbortController = /*#__PURE__*/envRefMake("effect/Micro/currentAbortController", () => new AbortController());
393
+ /**
394
+ * @since 3.4.0
395
+ * @experimental
396
+ * @category environment refs
397
+ */
398
+ export const currentAbortSignal = /*#__PURE__*/envRefMake("effect/Micro/currentAbortSignal", () => currentAbortController.initial.signal);
399
+ /**
400
+ * @since 3.4.0
401
+ * @experimental
402
+ * @category environment refs
403
+ */
404
+ export const currentContext = /*#__PURE__*/envRefMake("effect/Micro/currentContext", () => Context.empty());
405
+ /**
406
+ * @since 3.4.0
407
+ * @experimental
408
+ * @category environment refs
409
+ */
410
+ export const currentConcurrency = /*#__PURE__*/envRefMake("effect/Micro/currentConcurrency", () => "unbounded");
411
+ /**
412
+ * @since 3.4.0
413
+ * @experimental
414
+ * @category environment refs
415
+ */
416
+ export const currentMaxDepthBeforeYield = /*#__PURE__*/envRefMake("effect/Micro/currentMaxDepthBeforeYield", () => 2048);
417
+ const currentInterruptible = /*#__PURE__*/envRefMake("effect/Micro/currentInterruptible", () => true);
418
+ /**
419
+ * If you have a `Micro` that uses `concurrency: "inherit"`, you can use this
420
+ * api to control the concurrency of that `Micro` when it is run.
421
+ *
422
+ * @since 3.4.0
423
+ * @experimental
424
+ * @category environment refs
425
+ * @example
426
+ * import * as Micro from "effect/Micro"
427
+ *
428
+ * Micro.forEach([1, 2, 3], (n) => Micro.succeed(n), {
429
+ * concurrency: "inherit"
430
+ * }).pipe(
431
+ * Micro.withConcurrency(2) // use a concurrency of 2
432
+ * )
433
+ */
434
+ export const withConcurrency = /*#__PURE__*/dual(2, (self, concurrency) => locally(self, currentConcurrency, concurrency));
435
+ // ----------------------------------------------------------------------------
436
+ // constructors
437
+ // ----------------------------------------------------------------------------
438
+ const MicroProto = {
439
+ ...Effectable.EffectPrototype,
440
+ _op: "Micro",
441
+ [TypeId]: {
442
+ _A: identity,
443
+ _E: identity,
444
+ _R: identity
445
+ },
446
+ [Symbol.iterator]() {
447
+ return new SingleShotGen(new YieldWrap(this));
448
+ }
449
+ };
450
+ const microDepthState = /*#__PURE__*/globalValue("effect/Micro/microDepthState", () => ({
451
+ depth: 0,
452
+ maxDepthBeforeYield: currentMaxDepthBeforeYield.initial
453
+ }));
454
+ const unsafeMake = run => {
455
+ const self = Object.create(MicroProto);
456
+ self[runSymbol] = run;
457
+ return self;
458
+ };
459
+ const unsafeMakeOptions = (run, checkAbort) => unsafeMake(function execute(env, onResult) {
460
+ if (checkAbort && env.refs[currentInterruptible.key] !== false && env.refs[currentAbortSignal.key].aborted) {
461
+ return onResult(ResultAborted);
462
+ }
463
+ microDepthState.depth++;
464
+ if (microDepthState.depth === 1) {
465
+ microDepthState.maxDepthBeforeYield = envGet(env, currentMaxDepthBeforeYield);
466
+ }
467
+ if (microDepthState.depth >= microDepthState.maxDepthBeforeYield) {
468
+ yieldAdd(() => execute(env, onResult));
469
+ } else {
470
+ try {
471
+ run(env, onResult);
472
+ } catch (err) {
473
+ onResult(ResultFailUnexpected(err));
474
+ }
475
+ }
476
+ microDepthState.depth--;
477
+ });
478
+ /**
479
+ * A low-level constructor for creating a `Micro` effect. It takes a function
480
+ * that receives an environment and a callback which should be called with the
481
+ * result of the effect.
482
+ *
483
+ * @since 3.4.0
484
+ * @experimental
485
+ * @category constructors
486
+ */
487
+ export const make = run => unsafeMakeOptions(run, true);
488
+ /**
489
+ * Converts a `Result` into a `Micro` effect.
490
+ *
491
+ * @since 3.4.0
492
+ * @experimental
493
+ * @category constructors
494
+ */
495
+ export const fromResult = self => make(function (_env, onResult) {
496
+ onResult(self);
497
+ });
498
+ /**
499
+ * Converts a lazy `Result` into a `Micro` effect.
500
+ *
501
+ * @since 3.4.0
502
+ * @experimental
503
+ * @category constructors
504
+ */
505
+ export const fromResultSync = self => make(function (_env, onResult) {
506
+ onResult(self());
507
+ });
508
+ /**
509
+ * Creates a `Micro` effect that will succeed with the specified constant value.
510
+ *
511
+ * @since 3.4.0
512
+ * @experimental
513
+ * @category constructors
514
+ */
515
+ export const succeed = a => fromResult(ResultSuccess(a));
516
+ /**
517
+ * Creates a `Micro` effect that will succeed with `Option.Some` of the value.
518
+ *
519
+ * @since 3.4.0
520
+ * @experimental
521
+ * @category constructors
522
+ */
523
+ export const succeedSome = a => succeed(Option.some(a));
524
+ /**
525
+ * Creates a `Micro` effect that will succeed with `Option.None`.
526
+ *
527
+ * @since 3.4.0
528
+ * @experimental
529
+ * @category constructors
530
+ */
531
+ export const succeedNone = /*#__PURE__*/succeed( /*#__PURE__*/Option.none());
532
+ /**
533
+ * Creates a `Micro` effect that will fail with the specified error.
534
+ *
535
+ * This will result in a `FailureExpected`, where the error is tracked at the
536
+ * type level.
537
+ *
538
+ * @since 3.4.0
539
+ * @experimental
540
+ * @category constructors
541
+ */
542
+ export const fail = e => fromResult(ResultFail(e));
543
+ /**
544
+ * Creates a `Micro` effect that will fail with the lazily evaluated error.
545
+ *
546
+ * This will result in a `FailureExpected`, where the error is tracked at the
547
+ * type level.
548
+ *
549
+ * @since 3.4.0
550
+ * @experimental
551
+ * @category constructors
552
+ */
553
+ export const failSync = e => make(function (_env, onResult) {
554
+ onResult(ResultFail(e()));
555
+ });
556
+ /**
557
+ * Creates a `Micro` effect that will die with the specified error.
558
+ *
559
+ * This will result in a `FailureUnexpected`, where the error is not tracked at
560
+ * the type level.
561
+ *
562
+ * @since 3.4.0
563
+ * @experimental
564
+ * @category constructors
565
+ */
566
+ export const die = defect => fromResult(ResultFailUnexpected(defect));
567
+ /**
568
+ * Creates a `Micro` effect that will fail with the specified `Failure`.
569
+ *
570
+ * @since 3.4.0
571
+ * @experimental
572
+ * @category constructors
573
+ */
574
+ export const failWith = failure => fromResult(ResultFailWith(failure));
575
+ /**
576
+ * Creates a `Micro` effect that will fail with the lazily evaluated `Failure`.
577
+ *
578
+ * @since 3.4.0
579
+ * @experimental
580
+ * @category constructors
581
+ */
582
+ export const failWithSync = failure => fromResultSync(() => ResultFailWith(failure()));
583
+ /**
584
+ * Creates a `Micro` effect that will succeed with the lazily evaluated value.
585
+ *
586
+ * If the evaluation of the value throws an error, the effect will fail with
587
+ * `FailureUnexpected`.
588
+ *
589
+ * @since 3.4.0
590
+ * @experimental
591
+ * @category constructors
592
+ */
593
+ export const sync = evaluate => make(function (_env, onResult) {
594
+ onResult(ResultSuccess(evaluate()));
595
+ });
596
+ /**
597
+ * Converts an `Option` into a `Micro` effect, that will fail with a
598
+ * `Option.None` if the option is `None`. Otherwise, it will succeed with the
599
+ * value of the option.
600
+ *
601
+ * @since 3.4.0
602
+ * @experimental
603
+ * @category constructors
604
+ */
605
+ export const fromOption = option => make(function (_env, onResult) {
606
+ onResult(option._tag === "Some" ? ResultSuccess(option.value) : ResultFail(Option.none()));
607
+ });
608
+ /**
609
+ * Converts an `Either` into a `Micro` effect, that will fail with the left side
610
+ * of the either if it is a `Left`. Otherwise, it will succeed with the right
611
+ * side of the either.
612
+ *
613
+ * @since 3.4.0
614
+ * @experimental
615
+ * @category constructors
616
+ */
617
+ export const fromEither = either => make(function (_env, onResult) {
618
+ onResult(either._tag === "Right" ? either : ResultFail(either.left));
619
+ });
620
+ /**
621
+ * Lazily creates a `Micro` effect from the given side-effect.
622
+ *
623
+ * @since 3.4.0
624
+ * @experimental
625
+ * @category constructors
626
+ */
627
+ export const suspend = evaluate => make(function (env, onResult) {
628
+ evaluate()[runSymbol](env, onResult);
629
+ });
630
+ const void_ = /*#__PURE__*/succeed(void 0);
631
+ export {
632
+ /**
633
+ * A `Micro` effect that will succeed with `void` (`undefined`).
634
+ *
635
+ * @since 3.4.0
636
+ * @experimental
637
+ * @category constructors
638
+ */
639
+ void_ as void };
640
+ /**
641
+ * Create a `Micro` effect from an asynchronous computation.
642
+ *
643
+ * You can return a cleanup effect that will be run when the effect is aborted.
644
+ * It is also passed an `AbortSignal` that is triggered when the effect is
645
+ * aborted.
646
+ *
647
+ * @since 3.4.0
648
+ * @experimental
649
+ * @category constructors
650
+ */
651
+ export const async = register => make(function (env, onResult) {
652
+ let resumed = false;
653
+ const controller = register.length > 1 ? new AbortController() : undefined;
654
+ const signal = envGet(env, currentAbortSignal);
655
+ let cleanup = undefined;
656
+ function onAbort() {
657
+ if (cleanup) {
658
+ resume(uninterruptible(andThen(cleanup, fromResult(ResultAborted))));
659
+ } else {
660
+ resume(fromResult(ResultAborted));
661
+ }
662
+ if (controller !== undefined) {
663
+ controller.abort();
664
+ }
665
+ }
666
+ function resume(effect) {
667
+ if (resumed) {
668
+ return;
669
+ }
670
+ resumed = true;
671
+ signal.removeEventListener("abort", onAbort);
672
+ effect[runSymbol](env, onResult);
673
+ }
674
+ cleanup = controller === undefined ? register(resume) : register(resume, controller.signal);
675
+ if (resumed) return;
676
+ signal.addEventListener("abort", onAbort);
677
+ });
678
+ const try_ = options => make(function (_env, onResult) {
679
+ try {
680
+ onResult(ResultSuccess(options.try()));
681
+ } catch (err) {
682
+ onResult(ResultFail(options.catch(err)));
683
+ }
684
+ });
685
+ export {
686
+ /**
687
+ * The `Micro` equivalent of a try / catch block, which allows you to map
688
+ * thrown errors to a specific error type.
689
+ *
690
+ * @since 3.4.0
691
+ * @experimental
692
+ * @category constructors
693
+ * @example
694
+ * import { Micro } from "effect"
695
+ *
696
+ * Micro.try({
697
+ * try: () => throw new Error("boom"),
698
+ * catch: (cause) => new Error("caught", { cause })
699
+ * })
700
+ */
701
+ try_ as try };
702
+ /**
703
+ * Wrap a `Promise` into a `Micro` effect. Any errors will result in a
704
+ * `FailureUnexpected`.
705
+ *
706
+ * @since 3.4.0
707
+ * @experimental
708
+ * @category constructors
709
+ */
710
+ export const promise = evaluate => async(function (resume, signal) {
711
+ evaluate(signal).then(a => resume(succeed(a)), e => resume(die(e)));
712
+ });
713
+ /**
714
+ * Wrap a `Promise` into a `Micro` effect. Any errors will be caught and
715
+ * converted into a specific error type.
716
+ *
717
+ * @since 3.4.0
718
+ * @experimental
719
+ * @category constructors
720
+ * @example
721
+ * import { Micro } from "effect"
722
+ *
723
+ * Micro.tryPromise({
724
+ * try: () => Promise.resolve("success"),
725
+ * catch: (cause) => new Error("caught", { cause })
726
+ * })
727
+ */
728
+ export const tryPromise = options => async(function (resume, signal) {
729
+ try {
730
+ options.try(signal).then(a => resume(succeed(a)), e => resume(fail(options.catch(e))));
731
+ } catch (err) {
732
+ resume(fail(options.catch(err)));
733
+ }
734
+ });
735
+ const yieldState = /*#__PURE__*/globalValue("effect/Micro/yieldState", () => ({
736
+ tasks: [],
737
+ working: false
738
+ }));
739
+ const yieldRunTasks = () => {
740
+ const tasks = yieldState.tasks;
741
+ yieldState.tasks = [];
742
+ for (let i = 0, len = tasks.length; i < len; i++) {
743
+ tasks[i]();
744
+ }
745
+ };
746
+ const setImmediate = "setImmediate" in globalThis ? globalThis.setImmediate : f => setTimeout(f, 0);
747
+ const yieldAdd = task => {
748
+ yieldState.tasks.push(task);
749
+ if (!yieldState.working) {
750
+ yieldState.working = true;
751
+ setImmediate(() => {
752
+ yieldState.working = false;
753
+ yieldRunTasks();
754
+ });
755
+ }
756
+ };
757
+ /**
758
+ * Pause the execution of the current `Micro` effect, and resume it on the next
759
+ * iteration of the event loop.
760
+ *
761
+ * @since 3.4.0
762
+ * @experimental
763
+ * @category constructors
764
+ */
765
+ export const yieldNow = /*#__PURE__*/make(function (_env, onResult) {
766
+ yieldAdd(() => onResult(resultVoid));
767
+ });
768
+ /**
769
+ * Flush any yielded effects that are waiting to be executed.
770
+ *
771
+ * @since 3.4.0
772
+ * @experimental
773
+ * @category constructors
774
+ */
775
+ export const yieldFlush = /*#__PURE__*/sync(function () {
776
+ while (yieldState.tasks.length > 0) {
777
+ yieldRunTasks();
778
+ }
779
+ });
780
+ /**
781
+ * A `Micro` that will never succeed or fail. It wraps `setInterval` to prevent
782
+ * the Javascript runtime from exiting.
783
+ *
784
+ * @since 3.4.0
785
+ * @experimental
786
+ * @category constructors
787
+ */
788
+ export const never = /*#__PURE__*/async(function () {
789
+ const interval = setInterval(constVoid, 2147483646);
790
+ return sync(() => clearInterval(interval));
791
+ });
792
+ /**
793
+ * @since 3.4.0
794
+ * @experimental
795
+ * @category constructors
796
+ */
797
+ export const gen = f => make(function (env, onResult) {
798
+ const iterator = f();
799
+ let running = false;
800
+ let value = undefined;
801
+ function run() {
802
+ running = true;
803
+ try {
804
+ let shouldContinue = true;
805
+ while (shouldContinue) {
806
+ const result = iterator.next(value);
807
+ if (result.done) {
808
+ return onResult(ResultSuccess(result.value));
809
+ }
810
+ shouldContinue = false;
811
+ yieldWrapGet(result.value)[runSymbol](env, function (result) {
812
+ if (result._tag === "Left") {
813
+ onResult(result);
814
+ } else {
815
+ shouldContinue = true;
816
+ value = result.right;
817
+ if (!running) run();
818
+ }
819
+ });
820
+ }
821
+ } catch (err) {
822
+ onResult(ResultFailUnexpected(err));
823
+ }
824
+ running = false;
825
+ }
826
+ run();
827
+ });
828
+ // ----------------------------------------------------------------------------
829
+ // mapping & sequencing
830
+ // ----------------------------------------------------------------------------
831
+ /**
832
+ * Flattens any nested `Micro` effects, merging the error and requirement types.
833
+ *
834
+ * @since 3.4.0
835
+ * @experimental
836
+ * @category mapping & sequencing
837
+ */
838
+ export const flatten = self => make(function (env, onResult) {
839
+ self[runSymbol](env, result => result._tag === "Left" ? onResult(result) : result.right[runSymbol](env, onResult));
840
+ });
841
+ /**
842
+ * Transforms the success value of the `Micro` effect with the specified
843
+ * function.
844
+ *
845
+ * @since 3.4.0
846
+ * @experimental
847
+ * @category mapping & sequencing
848
+ */
849
+ export const map = /*#__PURE__*/dual(2, (self, f) => make(function (env, onResult) {
850
+ self[runSymbol](env, function (result) {
851
+ onResult(result._tag === "Left" ? result : ResultSuccess(f(result.right)));
852
+ });
853
+ }));
854
+ /**
855
+ * Create a `Micro` effect that will replace the success value of the given
856
+ * effect.
857
+ *
858
+ * @since 3.4.0
859
+ * @experimental
860
+ * @category mapping & sequencing
861
+ */
862
+ export const as = /*#__PURE__*/dual(2, (self, value) => map(self, _ => value));
863
+ /**
864
+ * Wrap the success value of this `Micro` effect in an `Option.Some`.
865
+ *
866
+ * @since 3.4.0
867
+ * @experimental
868
+ * @category mapping & sequencing
869
+ */
870
+ export const asSome = self => map(self, Option.some);
871
+ /**
872
+ * Map the success value of this `Micro` effect to another `Micro` effect, then
873
+ * flatten the result.
874
+ *
875
+ * @since 3.4.0
876
+ * @experimental
877
+ * @category mapping & sequencing
878
+ */
879
+ export const flatMap = /*#__PURE__*/dual(2, (self, f) => make(function (env, onResult) {
880
+ self[runSymbol](env, function (result) {
881
+ if (result._tag === "Left") {
882
+ return onResult(result);
883
+ }
884
+ f(result.right)[runSymbol](env, onResult);
885
+ });
886
+ }));
887
+ /**
888
+ * Swap the error and success types of the `Micro` effect.
889
+ *
890
+ * @since 3.4.0
891
+ * @experimental
892
+ * @category mapping & sequencing
893
+ */
894
+ export const flip = self => matchMicro(self, {
895
+ onFailure: succeed,
896
+ onSuccess: fail
897
+ });
898
+ /**
899
+ * A more flexible version of `flatMap`, that combines `map` and `flatMap` into
900
+ * a single api.
901
+ *
902
+ * It also allows you to pass in a `Micro` effect directly, which will be
903
+ * executed after the current effect.
904
+ *
905
+ * @since 3.4.0
906
+ * @experimental
907
+ * @category mapping & sequencing
908
+ */
909
+ export const andThen = /*#__PURE__*/dual(2, (self, f) => make(function (env, onResult) {
910
+ self[runSymbol](env, function (result) {
911
+ if (result._tag === "Left") {
912
+ return onResult(result);
913
+ } else if (envGet(env, currentAbortSignal).aborted) {
914
+ return onResult(ResultAborted);
915
+ }
916
+ const value = isMicro(f) ? f : typeof f === "function" ? f(result.right) : f;
917
+ if (isMicro(value)) {
918
+ value[runSymbol](env, onResult);
919
+ } else {
920
+ onResult(ResultSuccess(value));
921
+ }
922
+ });
923
+ }));
924
+ /**
925
+ * Execute a side effect from the success value of the `Micro` effect.
926
+ *
927
+ * It is similar to the `andThen` api, but the success value is ignored.
928
+ *
929
+ * @since 3.4.0
930
+ * @experimental
931
+ * @category mapping & sequencing
932
+ */
933
+ export const tap = /*#__PURE__*/dual(2, (self, f) => make(function (env, onResult) {
934
+ self[runSymbol](env, function (selfResult) {
935
+ if (selfResult._tag === "Left") {
936
+ return onResult(selfResult);
937
+ } else if (envGet(env, currentAbortSignal).aborted) {
938
+ return onResult(ResultAborted);
939
+ }
940
+ const value = isMicro(f) ? f : typeof f === "function" ? f(selfResult.right) : f;
941
+ if (isMicro(value)) {
942
+ value[runSymbol](env, function (tapResult) {
943
+ if (tapResult._tag === "Left") {
944
+ return onResult(tapResult);
945
+ }
946
+ onResult(selfResult);
947
+ });
948
+ } else {
949
+ onResult(selfResult);
950
+ }
951
+ });
952
+ }));
953
+ /**
954
+ * Replace the success value of the `Micro` effect with `void`.
955
+ *
956
+ * @since 3.4.0
957
+ * @experimental
958
+ * @category mapping & sequencing
959
+ */
960
+ export const asVoid = self => map(self, _ => void 0);
961
+ /**
962
+ * Access the `Result` of the given `Micro` effect.
963
+ *
964
+ * @since 3.4.0
965
+ * @experimental
966
+ * @category mapping & sequencing
967
+ */
968
+ export const asResult = self => make(function (env, onResult) {
969
+ self[runSymbol](env, function (result) {
970
+ onResult(ResultSuccess(result));
971
+ });
972
+ });
973
+ /**
974
+ * Replace the error type of the given `Micro` with the full `Failure` object.
975
+ *
976
+ * @since 3.4.0
977
+ * @experimental
978
+ * @category mapping & sequencing
979
+ */
980
+ export const sandbox = self => catchFailure(self, failure => fail(failure));
981
+ function forkSignal(env) {
982
+ const controller = new AbortController();
983
+ const parentSignal = envGet(env, currentAbortSignal);
984
+ function onAbort() {
985
+ controller.abort();
986
+ parentSignal.removeEventListener("abort", onAbort);
987
+ }
988
+ parentSignal.addEventListener("abort", onAbort);
989
+ const envWithSignal = envMutate(env, function (refs) {
990
+ refs[currentAbortController.key] = controller;
991
+ refs[currentAbortSignal.key] = controller.signal;
992
+ return refs;
993
+ });
994
+ return [envWithSignal, onAbort];
995
+ }
996
+ /**
997
+ * Returns an effect that races all the specified effects,
998
+ * yielding the value of the first effect to succeed with a value. Losers of
999
+ * the race will be interrupted immediately
1000
+ *
1001
+ * @since 3.4.0
1002
+ * @experimental
1003
+ * @category sequencing
1004
+ */
1005
+ export const raceAll = all => make(function (env, onResult) {
1006
+ const [envWithSignal, onAbort] = forkSignal(env);
1007
+ const effects = Array.from(all);
1008
+ let len = effects.length;
1009
+ let index = 0;
1010
+ let done = 0;
1011
+ let result = undefined;
1012
+ const failures = [];
1013
+ function onDone(result_) {
1014
+ done++;
1015
+ if (result_._tag === "Right" && result === undefined) {
1016
+ len = index;
1017
+ result = result_;
1018
+ onAbort();
1019
+ } else if (result_._tag === "Left") {
1020
+ failures.push(result_.left);
1021
+ }
1022
+ if (done >= len) {
1023
+ onResult(result ?? Either.left(failures[0]));
1024
+ }
1025
+ }
1026
+ for (; index < len; index++) {
1027
+ effects[index][runSymbol](envWithSignal, onDone);
1028
+ }
1029
+ });
1030
+ /**
1031
+ * Returns an effect that races all the specified effects,
1032
+ * yielding the value of the first effect to succeed or fail. Losers of
1033
+ * the race will be interrupted immediately
1034
+ *
1035
+ * @since 3.4.0
1036
+ * @experimental
1037
+ * @category sequencing
1038
+ */
1039
+ export const raceAllFirst = all => make(function (env, onResult) {
1040
+ const [envWithSignal, onAbort] = forkSignal(env);
1041
+ const effects = Array.from(all);
1042
+ let len = effects.length;
1043
+ let index = 0;
1044
+ let done = 0;
1045
+ let result = undefined;
1046
+ const failures = [];
1047
+ function onDone(result_) {
1048
+ done++;
1049
+ if (result === undefined) {
1050
+ len = index;
1051
+ result = result_;
1052
+ onAbort();
1053
+ }
1054
+ if (done >= len) {
1055
+ onResult(result ?? Either.left(failures[0]));
1056
+ }
1057
+ }
1058
+ for (; index < len; index++) {
1059
+ effects[index][runSymbol](envWithSignal, onDone);
1060
+ }
1061
+ });
1062
+ /**
1063
+ * Returns an effect that races two effects, yielding the value of the first
1064
+ * effect to succeed. Losers of the race will be interrupted immediately
1065
+ *
1066
+ * @since 3.4.0
1067
+ * @experimental
1068
+ * @category sequencing
1069
+ */
1070
+ export const race = /*#__PURE__*/dual(2, (self, that) => raceAll([self, that]));
1071
+ /**
1072
+ * Returns an effect that races two effects, yielding the value of the first
1073
+ * effect to succeed *or* fail. Losers of the race will be interrupted immediately
1074
+ *
1075
+ * @since 3.4.0
1076
+ * @experimental
1077
+ * @category sequencing
1078
+ */
1079
+ export const raceFirst = /*#__PURE__*/dual(2, (self, that) => raceAllFirst([self, that]));
1080
+ // ----------------------------------------------------------------------------
1081
+ // zipping
1082
+ // ----------------------------------------------------------------------------
1083
+ /**
1084
+ * Combine two `Micro` effects into a single effect that produces a tuple of
1085
+ * their results.
1086
+ *
1087
+ * @since 3.4.0
1088
+ * @experimental
1089
+ * @category zipping
1090
+ */
1091
+ export const zip = /*#__PURE__*/dual(args => isMicro(args[1]), (self, that, options) => {
1092
+ if (options?.concurrent) {
1093
+ return all([self, that], {
1094
+ concurrency: "unbounded"
1095
+ });
1096
+ }
1097
+ return flatMap(self, a => map(that, a2 => [a, a2]));
1098
+ });
1099
+ // ----------------------------------------------------------------------------
1100
+ // filtering & conditionals
1101
+ // ----------------------------------------------------------------------------
1102
+ /**
1103
+ * Filter the specified effect with the provided function, failing with specified
1104
+ * `Failure` if the predicate fails.
1105
+ *
1106
+ * In addition to the filtering capabilities discussed earlier, you have the option to further
1107
+ * refine and narrow down the type of the success channel by providing a
1108
+ *
1109
+ * @since 3.4.0
1110
+ * @experimental
1111
+ * @category filtering & conditionals
1112
+ */
1113
+ export const filterOrFailWith = /*#__PURE__*/dual(args => isMicro(args[0]), (self, refinement, orFailWith) => flatMap(self, a => refinement(a) ? succeed(a) : failWith(orFailWith(a))));
1114
+ /**
1115
+ * Filter the specified effect with the provided function, failing with specified
1116
+ * error if the predicate fails.
1117
+ *
1118
+ * In addition to the filtering capabilities discussed earlier, you have the option to further
1119
+ * refine and narrow down the type of the success channel by providing a
1120
+ *
1121
+ * @since 3.4.0
1122
+ * @experimental
1123
+ * @category filtering & conditionals
1124
+ */
1125
+ export const filterOrFail = /*#__PURE__*/dual(args => isMicro(args[0]), (self, refinement, orFailWith) => flatMap(self, a => refinement(a) ? succeed(a) : fail(orFailWith(a))));
1126
+ /**
1127
+ * The moral equivalent of `if (p) exp`.
1128
+ *
1129
+ * @since 3.4.0
1130
+ * @experimental
1131
+ * @category filtering & conditionals
1132
+ */
1133
+ export const when = /*#__PURE__*/dual(2, (self, condition) => flatMap(isMicro(condition) ? condition : sync(condition), pass => pass ? asSome(self) : succeed(Option.none())));
1134
+ // ----------------------------------------------------------------------------
1135
+ // repetition
1136
+ // ----------------------------------------------------------------------------
1137
+ /**
1138
+ * Repeat the given `Micro` using the provided options.
1139
+ *
1140
+ * The `while` predicate will be checked after each iteration, and can use the
1141
+ * fall `Result` of the effect to determine if the repetition should continue.
1142
+ *
1143
+ * @since 3.4.0
1144
+ * @experimental
1145
+ * @category repetition
1146
+ */
1147
+ export const repeatResult = /*#__PURE__*/dual(2, (self, options) => make(function (env, onResult) {
1148
+ const startedAt = options.delay ? Date.now() : 0;
1149
+ let attempt = 0;
1150
+ self[runSymbol](env, function loop(result) {
1151
+ if (options.while !== undefined && !options.while(result)) {
1152
+ return onResult(result);
1153
+ } else if (options.times !== undefined && attempt >= options.times) {
1154
+ return onResult(result);
1155
+ }
1156
+ attempt++;
1157
+ let delayEffect = yieldNow;
1158
+ if (options.delay !== undefined) {
1159
+ const elapsed = Date.now() - startedAt;
1160
+ const duration = options.delay(attempt, elapsed);
1161
+ if (Option.isNone(duration)) {
1162
+ return onResult(result);
1163
+ }
1164
+ delayEffect = sleep(duration.value);
1165
+ }
1166
+ delayEffect[runSymbol](env, function (result) {
1167
+ if (result._tag === "Left") {
1168
+ return onResult(result);
1169
+ }
1170
+ self[runSymbol](env, loop);
1171
+ });
1172
+ });
1173
+ }));
1174
+ /**
1175
+ * Repeat the given `Micro` effect using the provided options. Only successful
1176
+ * results will be repeated.
1177
+ *
1178
+ * @since 3.4.0
1179
+ * @experimental
1180
+ * @category repetition
1181
+ */
1182
+ export const repeat = /*#__PURE__*/dual(args => isMicro(args[0]), (self, options) => repeatResult(self, {
1183
+ ...options,
1184
+ while: result => result._tag === "Right" && (options?.while === undefined || options.while(result.right))
1185
+ }));
1186
+ /**
1187
+ * Repeat the given `Micro` effect forever, only stopping if the effect fails.
1188
+ *
1189
+ * @since 3.4.0
1190
+ * @experimental
1191
+ * @category repetition
1192
+ */
1193
+ export const forever = self => repeat(self);
1194
+ /**
1195
+ * Create a `DelayFn` that will generate a duration with an exponential backoff.
1196
+ *
1197
+ * @since 3.4.0
1198
+ * @experimental
1199
+ * @category delay fn
1200
+ */
1201
+ export const delayExponential = (baseMillis, factor = 2) => attempt => Option.some(attempt ** factor * baseMillis);
1202
+ /**
1203
+ * Create a `DelayFn` that will generate a duration with fixed intervals.
1204
+ *
1205
+ * @since 3.4.0
1206
+ * @experimental
1207
+ * @category delay fn
1208
+ */
1209
+ export const delaySpaced = millis => _ => Option.some(millis);
1210
+ /**
1211
+ * Transform a `DelayFn` to one that will have a duration that will never exceed
1212
+ * the specified maximum.
1213
+ *
1214
+ * @since 3.4.0
1215
+ * @experimental
1216
+ * @category delay fn
1217
+ */
1218
+ export const delayWithMax = /*#__PURE__*/dual(2, (self, max) => (attempt, elapsed) => Option.map(self(attempt, elapsed), duration => Math.min(duration, max)));
1219
+ /**
1220
+ * Transform a `DelayFn` to one that will stop repeating after the specified
1221
+ * amount of time.
1222
+ *
1223
+ * @since 3.4.0
1224
+ * @experimental
1225
+ * @category delay fn
1226
+ */
1227
+ export const delayWithMaxElapsed = /*#__PURE__*/dual(2, (self, max) => (attempt, elapsed) => elapsed < max ? self(attempt, elapsed) : Option.none());
1228
+ /**
1229
+ * Transform a `DelayFn` to one that will stop repeating after the specified
1230
+ * number of attempts.
1231
+ *
1232
+ * @since 3.4.0
1233
+ * @experimental
1234
+ * @category delay fn
1235
+ */
1236
+ export const delayWithRecurs = /*#__PURE__*/dual(2, (self, n) => (attempt, elapsed) => Option.filter(self(attempt, elapsed), () => attempt <= n));
1237
+ // ----------------------------------------------------------------------------
1238
+ // error handling
1239
+ // ----------------------------------------------------------------------------
1240
+ /**
1241
+ * Catch the full `Failure` object of the given `Micro` effect, allowing you to
1242
+ * recover from any kind of failure.
1243
+ *
1244
+ * @since 3.4.0
1245
+ * @experimental
1246
+ * @category error handling
1247
+ */
1248
+ export const catchFailure = /*#__PURE__*/dual(2, (self, f) => catchFailureIf(self, constTrue, f));
1249
+ /**
1250
+ * Selectively catch a `Failure` object of the given `Micro` effect,
1251
+ * using the provided predicate to determine if the failure should be caught.
1252
+ *
1253
+ * @since 3.4.0
1254
+ * @experimental
1255
+ * @category error handling
1256
+ */
1257
+ export const catchFailureIf = /*#__PURE__*/dual(3, (self, refinement, f) => make(function (env, onResult) {
1258
+ self[runSymbol](env, function (result) {
1259
+ if (result._tag === "Right" || !refinement(result.left)) {
1260
+ return onResult(result);
1261
+ }
1262
+ f(result.left)[runSymbol](env, onResult);
1263
+ });
1264
+ }));
1265
+ /**
1266
+ * Catch the error of the given `Micro` effect, allowing you to recover from it.
1267
+ *
1268
+ * It only catches expected (`FailureExpected`) errors.
1269
+ *
1270
+ * @since 3.4.0
1271
+ * @experimental
1272
+ * @category error handling
1273
+ */
1274
+ export const catchExpected = /*#__PURE__*/dual(2, (self, f) => catchFailureIf(self, failureIsExpected, failure => f(failure.error)));
1275
+ /**
1276
+ * Catch any unexpected errors of the given `Micro` effect, allowing you to recover from them.
1277
+ *
1278
+ * @since 3.4.0
1279
+ * @experimental
1280
+ * @category error handling
1281
+ */
1282
+ export const catchUnexpected = /*#__PURE__*/dual(2, (self, f) => catchFailureIf(self, failureIsUnexpected, failure => f(failure.defect)));
1283
+ /**
1284
+ * Perform a side effect using the full `Failure` object of the given `Micro`.
1285
+ *
1286
+ * @since 3.4.0
1287
+ * @experimental
1288
+ * @category error handling
1289
+ */
1290
+ export const tapFailure = /*#__PURE__*/dual(2, (self, f) => tapFailureIf(self, constTrue, f));
1291
+ /**
1292
+ * Perform a side effect using if a `Failure` object matches the specified
1293
+ * predicate.
1294
+ *
1295
+ * @since 3.4.0
1296
+ * @experimental
1297
+ * @category error handling
1298
+ */
1299
+ export const tapFailureIf = /*#__PURE__*/dual(3, (self, refinement, f) => catchFailureIf(self, refinement, failure => andThen(f(failure), failWith(failure))));
1300
+ /**
1301
+ * Perform a side effect from expected errors of the given `Micro`.
1302
+ *
1303
+ * @since 3.4.0
1304
+ * @experimental
1305
+ * @category error handling
1306
+ */
1307
+ export const tapExpected = /*#__PURE__*/dual(2, (self, f) => tapFailureIf(self, failureIsExpected, failure => f(failure.error)));
1308
+ /**
1309
+ * Perform a side effect from unexpected errors of the given `Micro`.
1310
+ *
1311
+ * @since 3.4.0
1312
+ * @experimental
1313
+ * @category error handling
1314
+ */
1315
+ export const tapUnexpected = /*#__PURE__*/dual(2, (self, f) => tapFailureIf(self, failureIsUnexpected, failure => f(failure.defect)));
1316
+ /**
1317
+ * Catch any expected errors that match the specified predicate.
1318
+ *
1319
+ * @since 3.4.0
1320
+ * @experimental
1321
+ * @category error handling
1322
+ */
1323
+ export const catchIf = /*#__PURE__*/dual(3, (self, pred, f) => catchFailureIf(self, f => failureIsExpected(f) && pred(f.error), failure => f(failure.error)));
1324
+ /**
1325
+ * Recovers from the specified tagged error.
1326
+ *
1327
+ * @since 3.4.0
1328
+ * @experimental
1329
+ * @category error handling
1330
+ */
1331
+ export const catchTag = /*#__PURE__*/dual(3, (self, k, f) => catchIf(self, error => isTagged(error, k), f));
1332
+ /**
1333
+ * Transform the full `Failure` object of the given `Micro` effect.
1334
+ *
1335
+ * @since 3.4.0
1336
+ * @experimental
1337
+ * @category error handling
1338
+ */
1339
+ export const mapFailure = /*#__PURE__*/dual(2, (self, f) => catchFailure(self, failure => failWith(f(failure))));
1340
+ /**
1341
+ * Transform any expected errors of the given `Micro` effect.
1342
+ *
1343
+ * @since 3.4.0
1344
+ * @experimental
1345
+ * @category error handling
1346
+ */
1347
+ export const mapError = /*#__PURE__*/dual(2, (self, f) => catchExpected(self, error => fail(f(error))));
1348
+ /**
1349
+ * Elevate any expected errors of the given `Micro` effect to unexpected errors,
1350
+ * resulting in an error type of `never`.
1351
+ *
1352
+ * @since 3.4.0
1353
+ * @experimental
1354
+ * @category error handling
1355
+ */
1356
+ export const orDie = self => catchExpected(self, die);
1357
+ /**
1358
+ * Recover from all errors by succeeding with the given value.
1359
+ *
1360
+ * @since 3.4.0
1361
+ * @experimental
1362
+ * @category error handling
1363
+ */
1364
+ export const orElseSucceed = /*#__PURE__*/dual(2, (self, f) => catchExpected(self, _ => sync(f)));
1365
+ /**
1366
+ * Ignore any expected errors of the given `Micro` effect, returning `void`.
1367
+ *
1368
+ * @since 3.4.0
1369
+ * @experimental
1370
+ * @category error handling
1371
+ */
1372
+ export const ignore = self => matchMicro(self, {
1373
+ onFailure: _ => void_,
1374
+ onSuccess: _ => void_
1375
+ });
1376
+ /**
1377
+ * Ignore any expected errors of the given `Micro` effect, returning `void`.
1378
+ *
1379
+ * @since 3.4.0
1380
+ * @experimental
1381
+ * @category error handling
1382
+ */
1383
+ export const ignoreLogged = self => matchMicro(self, {
1384
+ onFailure: failure => sync(() => console.error(failure)),
1385
+ onSuccess: _ => void_
1386
+ });
1387
+ /**
1388
+ * Replace the success value of the given `Micro` effect with an `Option`,
1389
+ * wrapping the success value in `Some` and returning `None` if the effect fails
1390
+ * with an expected error.
1391
+ *
1392
+ * @since 3.4.0
1393
+ * @experimental
1394
+ * @category error handling
1395
+ */
1396
+ export const option = self => match(self, {
1397
+ onFailure: _ => Option.none(),
1398
+ onSuccess: Option.some
1399
+ });
1400
+ /**
1401
+ * Replace the success value of the given `Micro` effect with an `Either`,
1402
+ * wrapping the success value in `Right` and wrapping any expected errors with
1403
+ * a `Left`.
1404
+ *
1405
+ * @since 3.4.0
1406
+ * @experimental
1407
+ * @category error handling
1408
+ */
1409
+ export const either = self => match(self, {
1410
+ onFailure: Either.left,
1411
+ onSuccess: Either.right
1412
+ });
1413
+ /**
1414
+ * Retry the given `Micro` effect using the provided options.
1415
+ *
1416
+ * @since 3.4.0
1417
+ * @experimental
1418
+ * @category error handling
1419
+ */
1420
+ export const retry = /*#__PURE__*/dual(args => isMicro(args[0]), (self, options) => repeatResult(self, {
1421
+ ...options,
1422
+ while: result => result._tag === "Left" && result.left._tag === "Expected" && (options?.while === undefined || options.while(result.left.error))
1423
+ }));
1424
+ /**
1425
+ * Add a stack trace to any failures that occur in the effect. The trace will be
1426
+ * added to the `traces` field of the `Failure` object.
1427
+ *
1428
+ * @since 3.4.0
1429
+ * @experimental
1430
+ * @category error handling
1431
+ */
1432
+ export const withTrace = function () {
1433
+ const prevLimit = globalThis.Error.stackTraceLimit;
1434
+ globalThis.Error.stackTraceLimit = 2;
1435
+ const error = new globalThis.Error();
1436
+ globalThis.Error.stackTraceLimit = prevLimit;
1437
+ function generate(name, failure) {
1438
+ const stack = error.stack;
1439
+ if (!stack) {
1440
+ return failure;
1441
+ }
1442
+ const line = stack.split("\n")[2]?.trim().replace(/^at /, "");
1443
+ if (!line) {
1444
+ return failure;
1445
+ }
1446
+ const lineMatch = line.match(/\((.*)\)$/);
1447
+ return failureWithTrace(failure, `at ${name} (${lineMatch ? lineMatch[1] : line})`);
1448
+ }
1449
+ const f = name => self => unsafeMakeOptions(function (env, onResult) {
1450
+ self[runSymbol](env, function (result) {
1451
+ onResult(result._tag === "Left" ? Either.left(generate(name, result.left)) : result);
1452
+ });
1453
+ }, false);
1454
+ if (arguments.length === 2) {
1455
+ return f(arguments[1])(arguments[0]);
1456
+ }
1457
+ return f(arguments[0]);
1458
+ };
1459
+ // ----------------------------------------------------------------------------
1460
+ // pattern matching
1461
+ // ----------------------------------------------------------------------------
1462
+ /**
1463
+ * @since 3.4.0
1464
+ * @experimental
1465
+ * @category pattern matching
1466
+ */
1467
+ export const matchFailureMicro = /*#__PURE__*/dual(2, (self, options) => make(function (env, onResult) {
1468
+ self[runSymbol](env, function (result) {
1469
+ try {
1470
+ const next = result._tag === "Left" ? options.onFailure(result.left) : options.onSuccess(result.right);
1471
+ next[runSymbol](env, onResult);
1472
+ } catch (err) {
1473
+ onResult(ResultFailUnexpected(err));
1474
+ }
1475
+ });
1476
+ }));
1477
+ /**
1478
+ * @since 3.4.0
1479
+ * @experimental
1480
+ * @category pattern matching
1481
+ */
1482
+ export const matchFailure = /*#__PURE__*/dual(2, (self, options) => matchFailureMicro(self, {
1483
+ onFailure: failure => sync(() => options.onFailure(failure)),
1484
+ onSuccess: value => sync(() => options.onSuccess(value))
1485
+ }));
1486
+ /**
1487
+ * @since 3.4.0
1488
+ * @experimental
1489
+ * @category pattern matching
1490
+ */
1491
+ export const matchMicro = /*#__PURE__*/dual(2, (self, options) => matchFailureMicro(self, {
1492
+ onFailure: failure => failure._tag === "Expected" ? options.onFailure(failure.error) : failWith(failure),
1493
+ onSuccess: options.onSuccess
1494
+ }));
1495
+ /**
1496
+ * @since 3.4.0
1497
+ * @experimental
1498
+ * @category pattern matching
1499
+ */
1500
+ export const match = /*#__PURE__*/dual(2, (self, options) => matchMicro(self, {
1501
+ onFailure: error => sync(() => options.onFailure(error)),
1502
+ onSuccess: value => sync(() => options.onSuccess(value))
1503
+ }));
1504
+ // ----------------------------------------------------------------------------
1505
+ // delays & timeouts
1506
+ // ----------------------------------------------------------------------------
1507
+ /**
1508
+ * Create a `Micro` effect that will sleep for the specified duration.
1509
+ *
1510
+ * @since 3.4.0
1511
+ * @experimental
1512
+ * @category delays & timeouts
1513
+ */
1514
+ export const sleep = millis => async(function (resume) {
1515
+ const timeout = setTimeout(function () {
1516
+ resume(void_);
1517
+ }, millis);
1518
+ return sync(() => {
1519
+ return clearTimeout(timeout);
1520
+ });
1521
+ });
1522
+ /**
1523
+ * Returns an effect that will delay the execution of this effect by the
1524
+ * specified duration.
1525
+ *
1526
+ * @since 3.4.0
1527
+ * @experimental
1528
+ * @category delays & timeouts
1529
+ */
1530
+ export const delay = /*#__PURE__*/dual(2, (self, millis) => andThen(sleep(millis), self));
1531
+ /**
1532
+ * Returns an effect that will timeout this effect, that will execute the
1533
+ * fallback effect if the timeout elapses before the effect has produced a value.
1534
+ *
1535
+ * If the timeout elapses, the running effect will be safely interrupted.
1536
+ *
1537
+ * @since 3.4.0
1538
+ * @experimental
1539
+ * @category delays & timeouts
1540
+ */
1541
+ export const timeoutOrElse = /*#__PURE__*/dual(2, (self, options) => raceFirst(self, andThen(interruptible(sleep(options.duration)), options.onTimeout)));
1542
+ /**
1543
+ * Returns an effect that will timeout this effect, succeeding with a `None`
1544
+ * if the timeout elapses before the effect has produced a value; and `Some` of
1545
+ * the produced value otherwise.
1546
+ *
1547
+ * If the timeout elapses, the running effect will be safely interrupted.
1548
+ *
1549
+ * @since 3.4.0
1550
+ * @experimental
1551
+ * @category delays & timeouts
1552
+ */
1553
+ export const timeout = /*#__PURE__*/dual(2, (self, millis) => raceFirst(asSome(self), as(interruptible(sleep(millis)), Option.none())));
1554
+ // ----------------------------------------------------------------------------
1555
+ // resources & finalization
1556
+ // ----------------------------------------------------------------------------
1557
+ /**
1558
+ * @since 3.4.0
1559
+ * @experimental
1560
+ * @category resources & finalization
1561
+ */
1562
+ export const MicroScopeTypeId = /*#__PURE__*/Symbol.for("effect/Micro/MicroScope");
1563
+ /**
1564
+ * @since 3.4.0
1565
+ * @experimental
1566
+ * @category resources & finalization
1567
+ */
1568
+ export const MicroScope = /*#__PURE__*/Context.GenericTag("effect/Micro/MicroScope");
1569
+ class ScopeImpl {
1570
+ [MicroScopeTypeId];
1571
+ state = {
1572
+ _tag: "Open",
1573
+ finalizers: new Set()
1574
+ };
1575
+ constructor() {
1576
+ this[MicroScopeTypeId] = MicroScopeTypeId;
1577
+ }
1578
+ unsafeAddFinalizer(finalizer) {
1579
+ if (this.state._tag === "Open") {
1580
+ this.state.finalizers.add(finalizer);
1581
+ }
1582
+ }
1583
+ addFinalizer(finalizer) {
1584
+ return suspend(() => {
1585
+ if (this.state._tag === "Open") {
1586
+ this.state.finalizers.add(finalizer);
1587
+ return void_;
1588
+ }
1589
+ return finalizer(this.state.result);
1590
+ });
1591
+ }
1592
+ unsafeRemoveFinalizer(finalizer) {
1593
+ if (this.state._tag === "Open") {
1594
+ this.state.finalizers.delete(finalizer);
1595
+ }
1596
+ }
1597
+ close(result) {
1598
+ return suspend(() => {
1599
+ if (this.state._tag === "Open") {
1600
+ const finalizers = Array.from(this.state.finalizers).reverse();
1601
+ this.state = {
1602
+ _tag: "Closed",
1603
+ result
1604
+ };
1605
+ return flatMap(forEach(finalizers, finalizer => asResult(finalizer(result))), results => asVoid(fromResult(Either.all(results))));
1606
+ }
1607
+ return void_;
1608
+ });
1609
+ }
1610
+ get fork() {
1611
+ return sync(() => {
1612
+ const newScope = new ScopeImpl();
1613
+ if (this.state._tag === "Closed") {
1614
+ newScope.state = this.state;
1615
+ return newScope;
1616
+ }
1617
+ function fin(result) {
1618
+ return newScope.close(result);
1619
+ }
1620
+ this.state.finalizers.add(fin);
1621
+ newScope.unsafeAddFinalizer(_ => sync(() => this.unsafeRemoveFinalizer(fin)));
1622
+ return newScope;
1623
+ });
1624
+ }
1625
+ }
1626
+ /**
1627
+ * @since 3.4.0
1628
+ * @experimental
1629
+ * @category resources & finalization
1630
+ */
1631
+ export const scopeMake = /*#__PURE__*/sync(() => new ScopeImpl());
1632
+ /**
1633
+ * @since 3.4.0
1634
+ * @experimental
1635
+ * @category resources & finalization
1636
+ */
1637
+ export const scopeUnsafeMake = () => new ScopeImpl();
1638
+ /**
1639
+ * Access the current `MicroScope`.
1640
+ *
1641
+ * @since 3.4.0
1642
+ * @experimental
1643
+ * @category resources & finalization
1644
+ */
1645
+ export const scope = /*#__PURE__*/service(MicroScope);
1646
+ /**
1647
+ * Provide a `MicroScope` to an effect.
1648
+ *
1649
+ * @since 3.4.0
1650
+ * @experimental
1651
+ * @category resources & finalization
1652
+ */
1653
+ export const provideScope = /*#__PURE__*/dual(2, (self, scope) => provideService(self, MicroScope, scope));
1654
+ /**
1655
+ * Provide a `MicroScope` to the given effect, closing it after the effect has
1656
+ * finished executing.
1657
+ *
1658
+ * @since 3.4.0
1659
+ * @experimental
1660
+ * @category resources & finalization
1661
+ */
1662
+ export const scoped = self => suspend(function () {
1663
+ const scope = new ScopeImpl();
1664
+ return onResult(provideService(self, MicroScope, scope), result => scope.close(result));
1665
+ });
1666
+ /**
1667
+ * Create a resource with a cleanup `Micro` effect, ensuring the cleanup is
1668
+ * executed when the `MicroScope` is closed.
1669
+ *
1670
+ * @since 3.4.0
1671
+ * @experimental
1672
+ * @category resources & finalization
1673
+ */
1674
+ export const acquireRelease = (acquire, release) => uninterruptible(flatMap(scope, scope => tap(acquire, a => scope.addFinalizer(result => release(a, result)))));
1675
+ /**
1676
+ * Add a finalizer to the current `MicroScope`.
1677
+ *
1678
+ * @since 3.4.0
1679
+ * @experimental
1680
+ * @category resources & finalization
1681
+ */
1682
+ export const addFinalizer = finalizer => flatMap(scope, scope => scope.addFinalizer(finalizer));
1683
+ /**
1684
+ * When the `Micro` effect is completed, run the given finalizer effect with the
1685
+ * `Result` of the executed effect.
1686
+ *
1687
+ * @since 3.4.0
1688
+ * @experimental
1689
+ * @category resources & finalization
1690
+ */
1691
+ export const onResult = /*#__PURE__*/dual(2, (self, f) => onResultIf(self, constTrue, f));
1692
+ /**
1693
+ * When the `Micro` effect is completed, run the given finalizer effect if it
1694
+ * matches the specified predicate.
1695
+ *
1696
+ * @since 3.4.0
1697
+ * @experimental
1698
+ * @category resources & finalization
1699
+ */
1700
+ export const onResultIf = /*#__PURE__*/dual(3, (self, refinement, f) => uninterruptibleMask(restore => make(function (env, onResult) {
1701
+ restore(self)[runSymbol](env, function (result) {
1702
+ if (!refinement(result)) {
1703
+ return onResult(result);
1704
+ }
1705
+ f(result)[runSymbol](env, function (finalizerResult) {
1706
+ if (finalizerResult._tag === "Left") {
1707
+ return onResult(finalizerResult);
1708
+ }
1709
+ onResult(result);
1710
+ });
1711
+ });
1712
+ })));
1713
+ /**
1714
+ * Regardless of the result of the this `Micro` effect, run the finalizer effect.
1715
+ *
1716
+ * @since 3.4.0
1717
+ * @experimental
1718
+ * @category resources & finalization
1719
+ */
1720
+ export const ensuring = /*#__PURE__*/dual(2, (self, finalizer) => onResult(self, _ => finalizer));
1721
+ /**
1722
+ * When the `Micro` effect fails, run the given finalizer effect with the
1723
+ * `Failure` of the executed effect.
1724
+ *
1725
+ * @since 3.4.0
1726
+ * @experimental
1727
+ * @category resources & finalization
1728
+ */
1729
+ export const onFailure = /*#__PURE__*/dual(2, (self, f) => onResultIf(self, resultIsFailure, result => f(result.left)));
1730
+ /**
1731
+ * If this `Micro` effect is aborted, run the finalizer effect.
1732
+ *
1733
+ * @since 3.4.0
1734
+ * @experimental
1735
+ * @category resources & finalization
1736
+ */
1737
+ export const onAbort = /*#__PURE__*/dual(2, (self, finalizer) => onResultIf(self, resultIsAborted, _ => finalizer));
1738
+ /**
1739
+ * Acquire a resource, use it, and then release the resource when the `use`
1740
+ * effect has completed.
1741
+ *
1742
+ * @since 3.4.0
1743
+ * @experimental
1744
+ * @category resources & finalization
1745
+ */
1746
+ export const acquireUseRelease = (acquire, use, release) => uninterruptibleMask(restore => flatMap(acquire, a => flatMap(asResult(restore(use(a))), result => andThen(release(a, result), fromResult(result)))));
1747
+ // ----------------------------------------------------------------------------
1748
+ // interruption
1749
+ // ----------------------------------------------------------------------------
1750
+ /**
1751
+ * Abort the current `Micro` effect.
1752
+ *
1753
+ * @since 3.4.0
1754
+ * @experimental
1755
+ * @category interruption
1756
+ */
1757
+ export const abort = /*#__PURE__*/make(function (env, onResult) {
1758
+ const controller = envGet(env, currentAbortController);
1759
+ controller.abort();
1760
+ onResult(ResultAborted);
1761
+ });
1762
+ /**
1763
+ * Wrap the given `Micro` effect in an uninterruptible region, preventing the
1764
+ * effect from being aborted.
1765
+ *
1766
+ * @since 3.4.0
1767
+ * @experimental
1768
+ * @category interruption
1769
+ */
1770
+ export const uninterruptible = self => unsafeMakeOptions(function (env, onResult) {
1771
+ const nextEnv = envMutate(env, function (env) {
1772
+ env[currentInterruptible.key] = false;
1773
+ env[currentAbortSignal.key] = new AbortController().signal;
1774
+ return env;
1775
+ });
1776
+ self[runSymbol](nextEnv, onResult);
1777
+ }, false);
1778
+ /**
1779
+ * Wrap the given `Micro` effect in an uninterruptible region, preventing the
1780
+ * effect from being aborted.
1781
+ *
1782
+ * You can use the `restore` function to restore a `Micro` effect to the
1783
+ * interruptibility state before the `uninterruptibleMask` was applied.
1784
+ *
1785
+ * @since 3.4.0
1786
+ * @experimental
1787
+ * @category interruption
1788
+ * @example
1789
+ * import * as Micro from "effect/Micro"
1790
+ *
1791
+ * Micro.uninterruptibleMask((restore) =>
1792
+ * Micro.sleep(1000).pipe( // uninterruptible
1793
+ * Micro.andThen(restore(Micro.sleep(1000))) // interruptible
1794
+ * )
1795
+ * )
1796
+ */
1797
+ export const uninterruptibleMask = f => unsafeMakeOptions((env, onResult) => {
1798
+ const isInterruptible = envGet(env, currentInterruptible);
1799
+ const effect = isInterruptible ? f(interruptible) : f(identity);
1800
+ const nextEnv = isInterruptible ? envMutate(env, function (env) {
1801
+ env[currentInterruptible.key] = false;
1802
+ env[currentAbortSignal.key] = new AbortController().signal;
1803
+ return env;
1804
+ }) : env;
1805
+ effect[runSymbol](nextEnv, onResult);
1806
+ }, false);
1807
+ /**
1808
+ * Wrap the given `Micro` effect in an interruptible region, allowing the effect
1809
+ * to be aborted.
1810
+ *
1811
+ * @since 3.4.0
1812
+ * @experimental
1813
+ * @category interruption
1814
+ */
1815
+ export const interruptible = self => make((env, onResult) => {
1816
+ const isInterruptible = envGet(env, currentInterruptible);
1817
+ let newEnv = env;
1818
+ if (!isInterruptible) {
1819
+ const controller = envGet(env, currentAbortController);
1820
+ newEnv = envMutate(env, function (env) {
1821
+ env[currentInterruptible.key] = true;
1822
+ env[currentAbortSignal.key] = controller.signal;
1823
+ return env;
1824
+ });
1825
+ }
1826
+ self[runSymbol](newEnv, onResult);
1827
+ });
1828
+ /**
1829
+ * Runs all the provided effects in sequence respecting the structure provided in input.
1830
+ *
1831
+ * Supports multiple arguments, a single argument tuple / array or record / struct.
1832
+ *
1833
+ * @since 3.4.0
1834
+ * @experimental
1835
+ * @category collecting & elements
1836
+ */
1837
+ export const all = (arg, options) => {
1838
+ if (Array.isArray(arg) || isIterable(arg)) {
1839
+ return forEach(arg, identity, options);
1840
+ } else if (options?.discard) {
1841
+ return forEach(Object.values(arg), identity, options);
1842
+ }
1843
+ return suspend(() => {
1844
+ const out = {};
1845
+ return as(forEach(Object.entries(arg), ([key, effect]) => map(effect, value => {
1846
+ out[key] = value;
1847
+ }), {
1848
+ discard: true,
1849
+ concurrency: options?.concurrency
1850
+ }), out);
1851
+ });
1852
+ };
1853
+ /**
1854
+ * For each element of the provided iterable, run the effect and collect the results.
1855
+ *
1856
+ * If the `discard` option is set to `true`, the results will be discarded and
1857
+ * the effect will return `void`.
1858
+ *
1859
+ * The `concurrency` option can be set to control how many effects are run in
1860
+ * parallel. By default, the effects are run sequentially.
1861
+ *
1862
+ * @since 3.4.0
1863
+ * @experimental
1864
+ * @category collecting & elements
1865
+ */
1866
+ export const forEach = (iterable, f, options) => make(function (env, onResult) {
1867
+ const concurrencyOption = options?.concurrency === "inherit" ? envGet(env, currentConcurrency) : options?.concurrency ?? 1;
1868
+ const concurrency = concurrencyOption === "unbounded" ? Number.POSITIVE_INFINITY : Math.max(1, concurrencyOption);
1869
+ // abort
1870
+ const [envWithSignal, onAbort] = forkSignal(env);
1871
+ // iterate
1872
+ let failure = undefined;
1873
+ const items = Array.from(iterable);
1874
+ let length = items.length;
1875
+ const out = options?.discard ? undefined : new Array(length);
1876
+ let index = 0;
1877
+ let inProgress = 0;
1878
+ let doneCount = 0;
1879
+ let pumping = false;
1880
+ function pump() {
1881
+ pumping = true;
1882
+ while (inProgress < concurrency && index < length) {
1883
+ const currentIndex = index;
1884
+ const item = items[currentIndex];
1885
+ index++;
1886
+ inProgress++;
1887
+ try {
1888
+ f(item, currentIndex)[runSymbol](envWithSignal, function (result) {
1889
+ if (result._tag === "Left") {
1890
+ if (failure === undefined) {
1891
+ failure = result;
1892
+ length = index;
1893
+ onAbort();
1894
+ }
1895
+ } else if (out !== undefined) {
1896
+ out[currentIndex] = result.right;
1897
+ }
1898
+ doneCount++;
1899
+ inProgress--;
1900
+ if (doneCount === length) {
1901
+ onResult(failure ?? Either.right(out));
1902
+ } else if (!pumping && inProgress < concurrency) {
1903
+ pump();
1904
+ }
1905
+ });
1906
+ } catch (err) {
1907
+ failure = ResultFailUnexpected(err);
1908
+ length = index;
1909
+ onAbort();
1910
+ }
1911
+ }
1912
+ pumping = false;
1913
+ }
1914
+ pump();
1915
+ });
1916
+ /**
1917
+ * Effectfully filter the elements of the provided iterable.
1918
+ *
1919
+ * Use the `concurrency` option to control how many elements are processed in parallel.
1920
+ *
1921
+ * @since 3.4.0
1922
+ * @experimental
1923
+ * @category collecting & elements
1924
+ */
1925
+ export const filter = (iterable, f, options) => filterMap(iterable, a => map(f(a), pass => {
1926
+ pass = options?.negate ? !pass : pass;
1927
+ return pass ? Option.some(a) : Option.none();
1928
+ }));
1929
+ /**
1930
+ * Effectfully filter the elements of the provided iterable.
1931
+ *
1932
+ * Use the `concurrency` option to control how many elements are processed in parallel.
1933
+ *
1934
+ * @since 3.4.0
1935
+ * @experimental
1936
+ * @category collecting & elements
1937
+ */
1938
+ export const filterMap = (iterable, f, options) => suspend(() => {
1939
+ const out = [];
1940
+ return as(forEach(iterable, a => map(f(a), o => {
1941
+ if (o._tag === "Some") {
1942
+ out.push(o.value);
1943
+ }
1944
+ }), {
1945
+ discard: true,
1946
+ concurrency: options?.concurrency
1947
+ }), out);
1948
+ });
1949
+ // ----------------------------------------------------------------------------
1950
+ // do notation
1951
+ // ----------------------------------------------------------------------------
1952
+ /**
1953
+ * Start a do notation block.
1954
+ *
1955
+ * @since 3.4.0
1956
+ * @experimental
1957
+ * @category do notation
1958
+ */
1959
+ export const Do = /*#__PURE__*/succeed({});
1960
+ /**
1961
+ * Bind the success value of this `Micro` effect to the provided name.
1962
+ *
1963
+ * @since 3.4.0
1964
+ * @experimental
1965
+ * @category do notation
1966
+ */
1967
+ export const bindTo = /*#__PURE__*/dual(2, (self, name) => map(self, f => ({
1968
+ [name]: f
1969
+ })));
1970
+ /**
1971
+ * Bind the success value of this `Micro` effect to the provided name.
1972
+ *
1973
+ * @since 3.4.0
1974
+ * @experimental
1975
+ * @category do notation
1976
+ */
1977
+ export const bind = /*#__PURE__*/dual(3, (self, name, f) => flatMap(self, a => map(f(a), b => ({
1978
+ ...a,
1979
+ [name]: b
1980
+ }))));
1981
+ const let_ = /*#__PURE__*/dual(3, (self, name, f) => map(self, a => ({
1982
+ ...a,
1983
+ [name]: f(a)
1984
+ })));
1985
+ export {
1986
+ /**
1987
+ * Bind the result of a synchronous computation to the given name.
1988
+ *
1989
+ * @since 3.4.0
1990
+ * @experimental
1991
+ * @category do notation
1992
+ */
1993
+ let_ as let };
1994
+ // ----------------------------------------------------------------------------
1995
+ // handle & forking
1996
+ // ----------------------------------------------------------------------------
1997
+ /**
1998
+ * @since 3.4.0
1999
+ * @experimental
2000
+ * @category handle & forking
2001
+ */
2002
+ export const HandleTypeId = /*#__PURE__*/Symbol.for("effect/Micro/Handle");
2003
+ /**
2004
+ * @since 3.4.0
2005
+ * @experimental
2006
+ * @category handle & forking
2007
+ */
2008
+ export const isHandle = u => typeof u === "object" && u !== null && HandleTypeId in u;
2009
+ class HandleImpl {
2010
+ parentSignal;
2011
+ [HandleTypeId];
2012
+ observers = new Set();
2013
+ _result = undefined;
2014
+ _controller;
2015
+ isRoot;
2016
+ constructor(parentSignal, controller) {
2017
+ this.parentSignal = parentSignal;
2018
+ this[HandleTypeId] = HandleTypeId;
2019
+ this.isRoot = controller !== undefined;
2020
+ this._controller = controller ?? new AbortController();
2021
+ if (!this.isRoot) {
2022
+ parentSignal.addEventListener("abort", this.unsafeAbort);
2023
+ }
2024
+ }
2025
+ unsafePoll() {
2026
+ return this._result ?? null;
2027
+ }
2028
+ unsafeAbort = () => {
2029
+ this._controller.abort();
2030
+ };
2031
+ emit(result) {
2032
+ if (this._result) {
2033
+ return;
2034
+ }
2035
+ this._result = result;
2036
+ if (!this.isRoot) {
2037
+ this.parentSignal.removeEventListener("abort", this.unsafeAbort);
2038
+ }
2039
+ this.observers.forEach(observer => observer(result));
2040
+ this.observers.clear();
2041
+ }
2042
+ addObserver(observer) {
2043
+ if (this._result) {
2044
+ return observer(this._result);
2045
+ }
2046
+ this.observers.add(observer);
2047
+ }
2048
+ removeObserver(observer) {
2049
+ this.observers.delete(observer);
2050
+ }
2051
+ get await() {
2052
+ return suspend(() => {
2053
+ if (this._result) {
2054
+ return succeed(this._result);
2055
+ }
2056
+ return async(resume => {
2057
+ function observer(result) {
2058
+ resume(succeed(result));
2059
+ }
2060
+ this.addObserver(observer);
2061
+ return sync(() => {
2062
+ this.removeObserver(observer);
2063
+ });
2064
+ });
2065
+ });
2066
+ }
2067
+ get join() {
2068
+ return flatMap(this.await, fromResult);
2069
+ }
2070
+ get abort() {
2071
+ return suspend(() => {
2072
+ this.unsafeAbort();
2073
+ return this.await;
2074
+ });
2075
+ }
2076
+ }
2077
+ /**
2078
+ * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
2079
+ * aborted.
2080
+ *
2081
+ * When the parent `Micro` finishes, this `Micro` will be aborted.
2082
+ *
2083
+ * @since 3.4.0
2084
+ * @experimental
2085
+ * @category handle & forking
2086
+ */
2087
+ export const fork = self => make(function (env, onResult) {
2088
+ const signal = envGet(env, currentAbortSignal);
2089
+ const handle = new HandleImpl(signal);
2090
+ const nextEnv = envMutate(env, map => {
2091
+ map[currentAbortController.key] = handle._controller;
2092
+ map[currentAbortSignal.key] = handle._controller.signal;
2093
+ return map;
2094
+ });
2095
+ yieldAdd(() => {
2096
+ self[runSymbol](nextEnv, result => {
2097
+ handle.emit(result);
2098
+ });
2099
+ });
2100
+ onResult(Either.right(handle));
2101
+ });
2102
+ /**
2103
+ * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
2104
+ * aborted.
2105
+ *
2106
+ * It will not be aborted when the parent `Micro` finishes.
2107
+ *
2108
+ * @since 3.4.0
2109
+ * @experimental
2110
+ * @category handle & forking
2111
+ */
2112
+ export const forkDaemon = self => make(function (env, onResult) {
2113
+ const controller = new AbortController();
2114
+ const handle = new HandleImpl(controller.signal, controller);
2115
+ const nextEnv = envMutate(env, map => {
2116
+ map[currentAbortController.key] = controller;
2117
+ map[currentAbortSignal.key] = controller.signal;
2118
+ return map;
2119
+ });
2120
+ yieldAdd(() => {
2121
+ self[runSymbol](nextEnv, result => {
2122
+ handle.emit(result);
2123
+ });
2124
+ });
2125
+ onResult(Either.right(handle));
2126
+ });
2127
+ /**
2128
+ * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
2129
+ * aborted.
2130
+ *
2131
+ * The lifetime of the handle will be attached to the provided `MicroScope`.
2132
+ *
2133
+ * @since 3.4.0
2134
+ * @experimental
2135
+ * @category handle & forking
2136
+ */
2137
+ export const forkIn = /*#__PURE__*/dual(2, (self, scope) => uninterruptibleMask(restore => flatMap(scope.fork, scope => tap(restore(forkDaemon(onResult(self, result => scope.close(result)))), fiber => scope.addFinalizer(_ => asVoid(fiber.abort))))));
2138
+ /**
2139
+ * Run the `Micro` effect in a new `Handle` that can be awaited, joined, or
2140
+ * aborted.
2141
+ *
2142
+ * The lifetime of the handle will be attached to the current `MicroScope`.
2143
+ *
2144
+ * @since 3.4.0
2145
+ * @experimental
2146
+ * @category handle & forking
2147
+ */
2148
+ export const forkScoped = self => flatMap(scope, scope => forkIn(self, scope));
2149
+ // ----------------------------------------------------------------------------
2150
+ // execution
2151
+ // ----------------------------------------------------------------------------
2152
+ /**
2153
+ * Execute the `Micro` effect and return a `Handle` that can be awaited, joined,
2154
+ * or aborted.
2155
+ *
2156
+ * You can listen for the result by adding an observer using the handle's
2157
+ * `addObserver` method.
2158
+ *
2159
+ * @since 3.4.0
2160
+ * @experimental
2161
+ * @category execution
2162
+ * @example
2163
+ * import * as Micro from "effect/Micro"
2164
+ *
2165
+ * const handle = Micro.succeed(42).pipe(
2166
+ * Micro.delay(1000),
2167
+ * Micro.runFork
2168
+ * )
2169
+ *
2170
+ * handle.addObserver((result) => {
2171
+ * console.log(result)
2172
+ * })
2173
+ */
2174
+ export const runFork = (effect, options) => {
2175
+ const controller = new AbortController();
2176
+ const refs = Object.create(null);
2177
+ refs[currentAbortController.key] = controller;
2178
+ refs[currentAbortSignal.key] = controller.signal;
2179
+ const env = envMake(refs);
2180
+ const handle = new HandleImpl(controller.signal, controller);
2181
+ effect[runSymbol](envSet(env, currentAbortSignal, handle._controller.signal), result => {
2182
+ handle.emit(result);
2183
+ });
2184
+ if (options?.signal) {
2185
+ if (options.signal.aborted) {
2186
+ handle.unsafeAbort();
2187
+ } else {
2188
+ options.signal.addEventListener("abort", () => handle.unsafeAbort());
2189
+ }
2190
+ }
2191
+ return handle;
2192
+ };
2193
+ /**
2194
+ * Execute the `Micro` effect and return a `Promise` that resolves with the
2195
+ * `Result` of the computation.
2196
+ *
2197
+ * @since 3.4.0
2198
+ * @experimental
2199
+ * @category execution
2200
+ */
2201
+ export const runPromiseResult = (effect, options) => new Promise((resolve, _reject) => {
2202
+ const handle = runFork(effect, options);
2203
+ handle.addObserver(resolve);
2204
+ });
2205
+ /**
2206
+ * Execute the `Micro` effect and return a `Promise` that resolves with the
2207
+ * successful value of the computation.
2208
+ *
2209
+ * @since 3.4.0
2210
+ * @experimental
2211
+ * @category execution
2212
+ */
2213
+ export const runPromise = (effect, options) => runPromiseResult(effect, options).then(result => {
2214
+ if (result._tag === "Left") {
2215
+ throw result.left;
2216
+ }
2217
+ return result.right;
2218
+ });
2219
+ /**
2220
+ * Attempt to execute the `Micro` effect synchronously and return the `Result`.
2221
+ *
2222
+ * If any asynchronous effects are encountered, the function will return a
2223
+ * FailureUnexpected containing the `Handle`.
2224
+ *
2225
+ * @since 3.4.0
2226
+ * @experimental
2227
+ * @category execution
2228
+ */
2229
+ export const runSyncResult = effect => {
2230
+ const handle = runFork(effect);
2231
+ while (yieldState.tasks.length > 0) {
2232
+ yieldRunTasks();
2233
+ }
2234
+ const result = handle.unsafePoll();
2235
+ if (result === null) {
2236
+ return ResultFailUnexpected(handle);
2237
+ }
2238
+ return result;
2239
+ };
2240
+ /**
2241
+ * Attempt to execute the `Micro` effect synchronously and return the success
2242
+ * value.
2243
+ *
2244
+ * @since 3.4.0
2245
+ * @experimental
2246
+ * @category execution
2247
+ */
2248
+ export const runSync = effect => {
2249
+ const result = runSyncResult(effect);
2250
+ if (result._tag === "Left") {
2251
+ throw result.left;
2252
+ }
2253
+ return result.right;
2254
+ };
2255
+ const YieldableError = /*#__PURE__*/function () {
2256
+ class YieldableError extends globalThis.Error {
2257
+ [runSymbol](_env, onResult) {
2258
+ onResult(ResultFail(this));
2259
+ }
2260
+ toString() {
2261
+ return this.message ? `${this.name}: ${this.message}` : this.name;
2262
+ }
2263
+ toJSON() {
2264
+ return {
2265
+ ...this
2266
+ };
2267
+ }
2268
+ [NodeInspectSymbol]() {
2269
+ const stack = this.stack;
2270
+ if (stack) {
2271
+ return `${this.toString()}\n${stack.split("\n").slice(1).join("\n")}`;
2272
+ }
2273
+ return this.toString();
2274
+ }
2275
+ }
2276
+ Object.assign(YieldableError.prototype, MicroProto, StructuralPrototype);
2277
+ return YieldableError;
2278
+ }();
2279
+ /**
2280
+ * @since 3.4.0
2281
+ * @experimental
2282
+ * @category errors
2283
+ */
2284
+ export const Error = /*#__PURE__*/function () {
2285
+ return class extends YieldableError {
2286
+ constructor(args) {
2287
+ super();
2288
+ if (args) {
2289
+ Object.assign(this, args);
2290
+ }
2291
+ }
2292
+ };
2293
+ }();
2294
+ /**
2295
+ * @since 3.4.0
2296
+ * @experimental
2297
+ * @category errors
2298
+ */
2299
+ export const TaggedError = tag => {
2300
+ class Base extends Error {
2301
+ _tag = tag;
2302
+ }
2303
+ ;
2304
+ Base.prototype.name = tag;
2305
+ return Base;
2306
+ };
2307
+ //# sourceMappingURL=Micro.js.map