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