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.
- package/Micro/package.json +6 -0
- package/dist/cjs/Array.js +18 -3
- package/dist/cjs/Array.js.map +1 -1
- package/dist/cjs/Chunk.js +13 -2
- package/dist/cjs/Chunk.js.map +1 -1
- package/dist/cjs/Effect.js +110 -8
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/Either.js +31 -1
- package/dist/cjs/Either.js.map +1 -1
- package/dist/cjs/ManagedRuntime.js.map +1 -1
- package/dist/cjs/Micro.js +2383 -0
- package/dist/cjs/Micro.js.map +1 -0
- package/dist/cjs/Option.js +1 -2
- package/dist/cjs/Option.js.map +1 -1
- package/dist/cjs/Schedule.js +2 -2
- package/dist/cjs/Stream.js.map +1 -1
- package/dist/cjs/Tuple.js +16 -9
- package/dist/cjs/Tuple.js.map +1 -1
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/core-effect.js +4 -2
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/core.js +12 -2
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +32 -0
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/stream.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/Array.d.ts +14 -0
- package/dist/dts/Array.d.ts.map +1 -1
- package/dist/dts/Cause.d.ts +1 -1
- package/dist/dts/Chunk.d.ts +11 -0
- package/dist/dts/Chunk.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +109 -5
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/Either.d.ts +35 -0
- package/dist/dts/Either.d.ts.map +1 -1
- package/dist/dts/ManagedRuntime.d.ts +15 -0
- package/dist/dts/ManagedRuntime.d.ts.map +1 -1
- package/dist/dts/Micro.d.ts +2002 -0
- package/dist/dts/Micro.d.ts.map +1 -0
- package/dist/dts/Option.d.ts +2 -0
- package/dist/dts/Option.d.ts.map +1 -1
- package/dist/dts/Schedule.d.ts +2 -2
- package/dist/dts/Stream.d.ts +45 -6
- package/dist/dts/Stream.d.ts.map +1 -1
- package/dist/dts/Tuple.d.ts +18 -0
- package/dist/dts/Tuple.d.ts.map +1 -1
- package/dist/dts/index.d.ts +7 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core-effect.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
- package/dist/esm/Array.js +14 -0
- package/dist/esm/Array.js.map +1 -1
- package/dist/esm/Chunk.js +11 -0
- package/dist/esm/Chunk.js.map +1 -1
- package/dist/esm/Effect.js +107 -5
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/Either.js +30 -0
- package/dist/esm/Either.js.map +1 -1
- package/dist/esm/ManagedRuntime.js.map +1 -1
- package/dist/esm/Micro.js +2307 -0
- package/dist/esm/Micro.js.map +1 -0
- package/dist/esm/Option.js +1 -1
- package/dist/esm/Option.js.map +1 -1
- package/dist/esm/Schedule.js +2 -2
- package/dist/esm/Stream.js.map +1 -1
- package/dist/esm/Tuple.js +15 -8
- package/dist/esm/Tuple.js.map +1 -1
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/core-effect.js +2 -0
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/core.js +10 -1
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +32 -0
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/stream.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +9 -1
- package/src/Array.ts +15 -0
- package/src/Cause.ts +1 -1
- package/src/Chunk.ts +12 -0
- package/src/Effect.ts +117 -5
- package/src/Either.ts +51 -0
- package/src/ManagedRuntime.ts +16 -0
- package/src/Micro.ts +3826 -0
- package/src/Option.ts +12 -1
- package/src/Schedule.ts +2 -2
- package/src/Stream.ts +60 -8
- package/src/Tuple.ts +18 -8
- package/src/index.ts +8 -0
- package/src/internal/core-effect.ts +33 -0
- package/src/internal/core.ts +18 -1
- package/src/internal/fiberRuntime.ts +32 -0
- package/src/internal/stream.ts +8 -4
- 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
|