unthrown 5.2.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +150 -142
- package/dist/index.d.cts +69 -17
- package/dist/index.d.mts +69 -17
- package/dist/index.mjs +150 -143
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -135,7 +135,7 @@ const universal = pattern(() => true);
|
|
|
135
135
|
/**
|
|
136
136
|
* The pattern namespace (unthrown's own; the former ts-pattern `P`):
|
|
137
137
|
*
|
|
138
|
-
* - `P._`
|
|
138
|
+
* - `P._` — the universal catch-all, and an **escape hatch** rather
|
|
139
139
|
* than the default: matching the error channel means naming its cases, so
|
|
140
140
|
* reach for this only where they cannot be named. Matches anything, and
|
|
141
141
|
* (because its phantom type is `unknown`) makes the builder provably
|
|
@@ -153,25 +153,22 @@ const universal = pattern(() => true);
|
|
|
153
153
|
* branch's parameter to that variant, payload included. The workhorse of the
|
|
154
154
|
* error channel: `matcher.with(P.tag("NotFound"), (e) => …)`. It composes like
|
|
155
155
|
* any other pattern — in a grouped arm
|
|
156
|
-
* (`.with(P.tag("A"), P.tag("B"), handler)`)
|
|
156
|
+
* (`.with(P.tag("A"), P.tag("B"), handler)`).
|
|
157
157
|
* - `P.instanceOf(Cls)` — an `instanceof` check, narrowing to the class
|
|
158
158
|
* instance type (for union members that are not tagged, e.g. a third-party
|
|
159
159
|
* error class).
|
|
160
|
-
* - `P.when(guard)` — an arbitrary type-guard predicate.
|
|
161
|
-
*
|
|
162
|
-
*
|
|
160
|
+
* - `P.when(guard)` — an arbitrary type-guard predicate. Also the way to match
|
|
161
|
+
* a primitive shape (`P.when((v): v is string => typeof v === "string")`),
|
|
162
|
+
* and grouping patterns under one handler is what a `.with(a, b, handler)`
|
|
163
|
+
* arm already does.
|
|
163
164
|
*
|
|
164
165
|
* @category Constructors
|
|
165
166
|
*/
|
|
166
167
|
const P = Object.freeze({
|
|
167
168
|
_: universal,
|
|
168
|
-
any: universal,
|
|
169
169
|
tag: (value) => ({ _tag: value }),
|
|
170
170
|
instanceOf: (cls) => pattern((value) => value instanceof cls),
|
|
171
|
-
when: (guard) => pattern(guard)
|
|
172
|
-
union: (...patterns) => pattern((value) => patterns.some((sub) => matches(sub, value))),
|
|
173
|
-
string: pattern((value) => typeof value === "string"),
|
|
174
|
-
number: pattern((value) => typeof value === "number")
|
|
171
|
+
when: (guard) => pattern(guard)
|
|
175
172
|
});
|
|
176
173
|
//#endregion
|
|
177
174
|
//#region src/defect.ts
|
|
@@ -569,6 +566,30 @@ function passThrough(self) {
|
|
|
569
566
|
return self;
|
|
570
567
|
}
|
|
571
568
|
/**
|
|
569
|
+
* Runtime thenable probe, shared by the combinator-side net below and the
|
|
570
|
+
* boundary nets in `interop.ts`.
|
|
571
|
+
*
|
|
572
|
+
* @remarks
|
|
573
|
+
* Reading `.then` can itself **throw** — a hostile getter, or a Proxy `get`
|
|
574
|
+
* trap — so this is deliberately not a total function, and every caller must
|
|
575
|
+
* account for that. Two shapes are sanctioned, and there is no third:
|
|
576
|
+
*
|
|
577
|
+
* - inside a `try` that routes the throw to a `Defect` (the boundaries in
|
|
578
|
+
* `interop.ts`, where a hostile value arriving at a triage point *is* an
|
|
579
|
+
* unmodeled failure and should surface as one); or
|
|
580
|
+
* - through {@link silenceIfThenable}, for a value being **discarded**, where
|
|
581
|
+
* there is no Defect channel to route to and the only correct answer is to
|
|
582
|
+
* drop it without throwing.
|
|
583
|
+
*
|
|
584
|
+
* Calling it bare, outside both, is a bug: the throw escapes into whatever
|
|
585
|
+
* context invoked it.
|
|
586
|
+
*
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function isThenable(x) {
|
|
590
|
+
return (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function";
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
572
593
|
* Adopt-and-silence a thenable a combinator is about to **discard**.
|
|
573
594
|
*
|
|
574
595
|
* @remarks
|
|
@@ -589,7 +610,7 @@ function passThrough(self) {
|
|
|
589
610
|
*/
|
|
590
611
|
function silenceIfThenable(value) {
|
|
591
612
|
try {
|
|
592
|
-
if ((
|
|
613
|
+
if (isThenable(value)) Promise.resolve(value).then(void 0, () => void 0);
|
|
593
614
|
} catch {}
|
|
594
615
|
}
|
|
595
616
|
/**
|
|
@@ -670,18 +691,29 @@ var AsyncRes = class AsyncRes {
|
|
|
670
691
|
constructor(promise) {
|
|
671
692
|
this.#promise = promise;
|
|
672
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* Lift a **synchronous** `Result` combinator over the wrapped promise.
|
|
696
|
+
*
|
|
697
|
+
* @remarks
|
|
698
|
+
* Every method below that does no `await` of its own is exactly its `Res`
|
|
699
|
+
* twin applied to the settled `Result` — same tag check, same try/catch, same
|
|
700
|
+
* throw→defect net. Delegating instead of restating it keeps the two surfaces
|
|
701
|
+
* from drifting: a fix to the sync combinator is the fix to the async one.
|
|
702
|
+
* The methods that DO await a callback's result (`flatMap`, `flatTap`,
|
|
703
|
+
* `bind`, `flatMapErrCases`, `flatTapErrCases`, `recoverDefect` — the ones
|
|
704
|
+
* whose callback may hand back an `AsyncResult`) genuinely differ and are
|
|
705
|
+
* still written out in full.
|
|
706
|
+
*
|
|
707
|
+
* @internal
|
|
708
|
+
*/
|
|
709
|
+
#lift(f) {
|
|
710
|
+
return new AsyncRes(this.#promise.then(f));
|
|
711
|
+
}
|
|
673
712
|
then(onfulfilled, onrejected) {
|
|
674
713
|
return this.#promise.then(onfulfilled, onrejected);
|
|
675
714
|
}
|
|
676
715
|
map(f) {
|
|
677
|
-
return
|
|
678
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
679
|
-
try {
|
|
680
|
-
return okRes(f(r.value));
|
|
681
|
-
} catch (cause) {
|
|
682
|
-
return defectRes(cause);
|
|
683
|
-
}
|
|
684
|
-
}));
|
|
716
|
+
return this.#lift((r) => r.map(f));
|
|
685
717
|
}
|
|
686
718
|
flatMap(f) {
|
|
687
719
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -695,15 +727,7 @@ var AsyncRes = class AsyncRes {
|
|
|
695
727
|
}));
|
|
696
728
|
}
|
|
697
729
|
tap(f) {
|
|
698
|
-
return
|
|
699
|
-
if (r.tag !== "Ok") return r;
|
|
700
|
-
try {
|
|
701
|
-
silenceIfThenable(f(r.value));
|
|
702
|
-
return r;
|
|
703
|
-
} catch (cause) {
|
|
704
|
-
return defectRes(cause);
|
|
705
|
-
}
|
|
706
|
-
}));
|
|
730
|
+
return this.#lift((r) => r.tap(f));
|
|
707
731
|
}
|
|
708
732
|
flatTap(f) {
|
|
709
733
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -734,45 +758,19 @@ var AsyncRes = class AsyncRes {
|
|
|
734
758
|
}));
|
|
735
759
|
}
|
|
736
760
|
let(name, f) {
|
|
737
|
-
return
|
|
738
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
739
|
-
try {
|
|
740
|
-
return okRes({
|
|
741
|
-
...scopeOf(r.value),
|
|
742
|
-
[name]: f(r.value)
|
|
743
|
-
});
|
|
744
|
-
} catch (cause) {
|
|
745
|
-
return defectRes(cause);
|
|
746
|
-
}
|
|
747
|
-
}));
|
|
761
|
+
return this.#lift((r) => r.let(name, f));
|
|
748
762
|
}
|
|
749
763
|
as(value) {
|
|
750
|
-
return
|
|
764
|
+
return this.#lift((r) => r.as(value));
|
|
751
765
|
}
|
|
752
766
|
discard() {
|
|
753
|
-
return
|
|
767
|
+
return this.#lift((r) => r.discard());
|
|
754
768
|
}
|
|
755
769
|
ensure(predicate, onFail) {
|
|
756
|
-
return
|
|
757
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
758
|
-
try {
|
|
759
|
-
return predicate(r.value) ? r : errRes(onFail(r.value));
|
|
760
|
-
} catch (cause) {
|
|
761
|
-
return defectRes(cause);
|
|
762
|
-
}
|
|
763
|
-
}));
|
|
770
|
+
return this.#lift((r) => r.ensure(predicate, onFail));
|
|
764
771
|
}
|
|
765
772
|
mapErrCases(f) {
|
|
766
|
-
return
|
|
767
|
-
if (r.tag !== "Err") return passThrough(r);
|
|
768
|
-
try {
|
|
769
|
-
const out = runMatch(f, r.error);
|
|
770
|
-
if (isDefectMarker(out)) return defectRes(out.cause);
|
|
771
|
-
return errRes(out);
|
|
772
|
-
} catch (cause) {
|
|
773
|
-
return defectRes(cause);
|
|
774
|
-
}
|
|
775
|
-
}));
|
|
773
|
+
return this.#lift((r) => r.mapErrCases(f));
|
|
776
774
|
}
|
|
777
775
|
flatMapErrCases(f) {
|
|
778
776
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -789,29 +787,10 @@ var AsyncRes = class AsyncRes {
|
|
|
789
787
|
}));
|
|
790
788
|
}
|
|
791
789
|
recoverErrCases(f) {
|
|
792
|
-
return
|
|
793
|
-
if (r.tag !== "Err") return passThrough(r);
|
|
794
|
-
try {
|
|
795
|
-
const out = runMatch(f, r.error);
|
|
796
|
-
if (isDefectMarker(out)) return defectRes(out.cause);
|
|
797
|
-
return okRes(out);
|
|
798
|
-
} catch (cause) {
|
|
799
|
-
return defectRes(cause);
|
|
800
|
-
}
|
|
801
|
-
}));
|
|
790
|
+
return this.#lift((r) => r.recoverErrCases(f));
|
|
802
791
|
}
|
|
803
792
|
tapErrCases(f) {
|
|
804
|
-
return
|
|
805
|
-
if (r.tag !== "Err") return r;
|
|
806
|
-
try {
|
|
807
|
-
const out = runMatch(f, r.error);
|
|
808
|
-
if (isDefectMarker(out)) return observerThrowToDefect(out.cause, r.error);
|
|
809
|
-
silenceIfThenable(out);
|
|
810
|
-
return r;
|
|
811
|
-
} catch (cause) {
|
|
812
|
-
return observerThrowToDefect(cause, r.error);
|
|
813
|
-
}
|
|
814
|
-
}));
|
|
793
|
+
return this.#lift((r) => r.tapErrCases(f));
|
|
815
794
|
}
|
|
816
795
|
flatTapErrCases(f) {
|
|
817
796
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -839,26 +818,10 @@ var AsyncRes = class AsyncRes {
|
|
|
839
818
|
}));
|
|
840
819
|
}
|
|
841
820
|
tapDefect(f) {
|
|
842
|
-
return
|
|
843
|
-
if (r.tag !== "Defect") return r;
|
|
844
|
-
try {
|
|
845
|
-
silenceIfThenable(f(r.cause));
|
|
846
|
-
return r;
|
|
847
|
-
} catch (cause) {
|
|
848
|
-
return observerThrowToDefect(cause, r.cause);
|
|
849
|
-
}
|
|
850
|
-
}));
|
|
821
|
+
return this.#lift((r) => r.tapDefect(f));
|
|
851
822
|
}
|
|
852
823
|
tapFailure(f) {
|
|
853
|
-
return
|
|
854
|
-
if (r.tag === "Ok") return r;
|
|
855
|
-
try {
|
|
856
|
-
silenceIfThenable(f(r));
|
|
857
|
-
return r;
|
|
858
|
-
} catch (cause) {
|
|
859
|
-
return observerThrowToDefect(cause, r.tag === "Err" ? r.error : r.cause);
|
|
860
|
-
}
|
|
861
|
-
}));
|
|
824
|
+
return this.#lift((r) => r.tapFailure(f));
|
|
862
825
|
}
|
|
863
826
|
match(cases) {
|
|
864
827
|
return this.#promise.then((r) => r.match(cases));
|
|
@@ -1288,6 +1251,72 @@ function fromPromise(promise, qualify, ..._guard) {
|
|
|
1288
1251
|
function fromSafePromise(promise) {
|
|
1289
1252
|
return new AsyncRes((typeof promise === "function" ? Promise.resolve().then(promise) : Promise.resolve(promise)).then((value) => okRes(value), (cause) => defectRes(cause)));
|
|
1290
1253
|
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1256
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1257
|
+
*
|
|
1258
|
+
* @remarks
|
|
1259
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1260
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1261
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1262
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1263
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1264
|
+
* its own turn, long after the executor body returned).
|
|
1265
|
+
*
|
|
1266
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1267
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1268
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1269
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1270
|
+
* site, not a silently-`unknown` channel.
|
|
1271
|
+
*
|
|
1272
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1273
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1274
|
+
* `new Promise`.
|
|
1275
|
+
*
|
|
1276
|
+
* @typeParam T - the success type.
|
|
1277
|
+
* @typeParam E - the modeled error type.
|
|
1278
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1279
|
+
*
|
|
1280
|
+
* @category Interop
|
|
1281
|
+
*
|
|
1282
|
+
* @example
|
|
1283
|
+
* ```ts
|
|
1284
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1285
|
+
*
|
|
1286
|
+
* const listen = (port: number) =>
|
|
1287
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1288
|
+
* server.once("error", (cause) =>
|
|
1289
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1290
|
+
* );
|
|
1291
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1292
|
+
* });
|
|
1293
|
+
* ```
|
|
1294
|
+
*/
|
|
1295
|
+
function fromExecutor(executor) {
|
|
1296
|
+
let resolve;
|
|
1297
|
+
const promise = new Promise((r) => {
|
|
1298
|
+
resolve = r;
|
|
1299
|
+
});
|
|
1300
|
+
const settle = (result) => {
|
|
1301
|
+
if (isDefectMarker(result)) {
|
|
1302
|
+
resolve(defectRes(result.cause));
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
if (!isResult(result)) {
|
|
1306
|
+
silenceIfThenable(result);
|
|
1307
|
+
resolve(defectRes(/* @__PURE__ */ new TypeError("unthrown: fromExecutor's settle received a non-Result value")));
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
resolve(result);
|
|
1311
|
+
};
|
|
1312
|
+
try {
|
|
1313
|
+
const returned = executor(settle, defect);
|
|
1314
|
+
if (isThenable(returned)) Promise.resolve(returned).then(void 0, (cause) => settle(defect(cause)));
|
|
1315
|
+
} catch (cause) {
|
|
1316
|
+
settle(defect(cause));
|
|
1317
|
+
}
|
|
1318
|
+
return new AsyncRes(promise);
|
|
1319
|
+
}
|
|
1291
1320
|
function qualifyToResult(cause, qualify) {
|
|
1292
1321
|
try {
|
|
1293
1322
|
const q = qualify(cause, defect);
|
|
@@ -1328,15 +1357,6 @@ function thenableReturnDefect(value) {
|
|
|
1328
1357
|
return defectRes(/* @__PURE__ */ new TypeError("unthrown: fromThrowable/fromSafeThrowable wrap a SYNCHRONOUS function, but `fn` returned a thenable — its rejection would escape qualification. Use fromPromise/fromSafePromise instead."));
|
|
1329
1358
|
}
|
|
1330
1359
|
/**
|
|
1331
|
-
* Runtime thenable probe for the belt-and-braces guards above. Called inside the
|
|
1332
|
-
* caller's `try`, so even a hostile `.then` getter lands on the Defect path.
|
|
1333
|
-
*
|
|
1334
|
-
* @internal
|
|
1335
|
-
*/
|
|
1336
|
-
function isThenable(x) {
|
|
1337
|
-
return (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function";
|
|
1338
|
-
}
|
|
1339
|
-
/**
|
|
1340
1360
|
* Fold an array of settled `Result`s: first `Err` wins, any `Defect` dominates,
|
|
1341
1361
|
* else `Ok` of the values array.
|
|
1342
1362
|
*
|
|
@@ -1365,32 +1385,23 @@ function foldArray(results) {
|
|
|
1365
1385
|
}
|
|
1366
1386
|
/**
|
|
1367
1387
|
* Fold a record of settled `Result`s with the same rules, else `Ok` of the
|
|
1368
|
-
* record of values.
|
|
1369
|
-
*
|
|
1388
|
+
* record of values.
|
|
1389
|
+
*
|
|
1390
|
+
* @remarks
|
|
1391
|
+
* The positional fold already implements every rule (first `Err` wins, any
|
|
1392
|
+
* `Defect` dominates, a non-`Result` element becomes a `Defect`), so this pairs
|
|
1393
|
+
* the keys back onto its success value rather than restating them.
|
|
1394
|
+
*
|
|
1395
|
+
* `Object.fromEntries` is what makes a caller-supplied `"__proto__"` key safe:
|
|
1396
|
+
* it builds each key with CreateDataProperty, which defines an own property
|
|
1397
|
+
* instead of invoking the `__proto__` setter — the same guarantee the previous
|
|
1398
|
+
* explicit `Object.defineProperty` loop bought by hand.
|
|
1370
1399
|
*
|
|
1371
1400
|
* @internal
|
|
1372
1401
|
*/
|
|
1373
1402
|
function foldRecord(results) {
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
const values = {};
|
|
1377
|
-
for (const [key, r] of Object.entries(results)) {
|
|
1378
|
-
if (!isResult(r)) {
|
|
1379
|
-
firstDefect ??= nonResultDefect();
|
|
1380
|
-
break;
|
|
1381
|
-
}
|
|
1382
|
-
if (r.tag === "Defect") {
|
|
1383
|
-
firstDefect ??= r;
|
|
1384
|
-
break;
|
|
1385
|
-
} else if (r.tag === "Err") firstErr ??= r;
|
|
1386
|
-
else Object.defineProperty(values, key, {
|
|
1387
|
-
value: r.value,
|
|
1388
|
-
enumerable: true,
|
|
1389
|
-
writable: true,
|
|
1390
|
-
configurable: true
|
|
1391
|
-
});
|
|
1392
|
-
}
|
|
1393
|
-
return firstDefect ?? firstErr ?? Ok(values);
|
|
1403
|
+
const keys = Object.keys(results);
|
|
1404
|
+
return foldArray(Object.values(results)).map((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]])));
|
|
1394
1405
|
}
|
|
1395
1406
|
/**
|
|
1396
1407
|
* Collect a tuple/array of {@link Result}s into a single `Result` of all their
|
|
@@ -1488,14 +1499,8 @@ function allAsync(results) {
|
|
|
1488
1499
|
* ```
|
|
1489
1500
|
*/
|
|
1490
1501
|
function allFromDictAsync(results) {
|
|
1491
|
-
const
|
|
1492
|
-
return new AsyncRes(Promise.all(
|
|
1493
|
-
const byKey = Object.create(null);
|
|
1494
|
-
entries.forEach(([key], i) => {
|
|
1495
|
-
byKey[key] = resolved[i];
|
|
1496
|
-
});
|
|
1497
|
-
return foldRecord(byKey);
|
|
1498
|
-
}));
|
|
1502
|
+
const keys = Object.keys(results);
|
|
1503
|
+
return new AsyncRes(Promise.all(Object.values(results).map((ar) => Promise.resolve(ar).then((x) => x, (cause) => defectRes(cause)))).then((resolved) => foldArray(resolved).map((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]])))));
|
|
1499
1504
|
}
|
|
1500
1505
|
//#endregion
|
|
1501
1506
|
//#region src/facade.ts
|
|
@@ -1542,14 +1547,15 @@ const Result = {
|
|
|
1542
1547
|
/**
|
|
1543
1548
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1544
1549
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1545
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1546
|
-
* {@link AsyncResult.
|
|
1547
|
-
* {@link AsyncResult.allFromDict}.
|
|
1550
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1551
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1552
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1548
1553
|
*
|
|
1549
1554
|
* @remarks
|
|
1550
1555
|
* The async sibling of {@link Result}. Statics are grouped by what they
|
|
1551
|
-
* **return**, so the pre-lifted constructors, `
|
|
1552
|
-
* and the async aggregates sit here rather
|
|
1556
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1557
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1558
|
+
* than on {@link Result}; the namespace
|
|
1553
1559
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1554
1560
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1555
1561
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1574,6 +1580,7 @@ const AsyncResult = {
|
|
|
1574
1580
|
Ok: OkAsync,
|
|
1575
1581
|
Err: ErrAsync,
|
|
1576
1582
|
Do: DoAsync,
|
|
1583
|
+
fromExecutor,
|
|
1577
1584
|
fromPromise,
|
|
1578
1585
|
fromSafePromise,
|
|
1579
1586
|
all: allAsync,
|
|
@@ -1686,6 +1693,7 @@ exports.all = all;
|
|
|
1686
1693
|
exports.allAsync = allAsync;
|
|
1687
1694
|
exports.allFromDict = allFromDict;
|
|
1688
1695
|
exports.allFromDictAsync = allFromDictAsync;
|
|
1696
|
+
exports.fromExecutor = fromExecutor;
|
|
1689
1697
|
exports.fromNullable = fromNullable;
|
|
1690
1698
|
exports.fromPromise = fromPromise;
|
|
1691
1699
|
exports.fromSafePromise = fromSafePromise;
|
package/dist/index.d.cts
CHANGED
|
@@ -44,7 +44,7 @@ type PatternMatcher<M> = {
|
|
|
44
44
|
readonly [MATCHES]?: M;
|
|
45
45
|
};
|
|
46
46
|
/**
|
|
47
|
-
* The statically-known universal pattern — the type of `P._`
|
|
47
|
+
* The statically-known universal pattern — the type of `P._` only.
|
|
48
48
|
* The phantom `UNIVERSAL` marker is *required*, so no other
|
|
49
49
|
* `PatternMatcher<unknown>` (e.g. a `P.when` guard that happens to be
|
|
50
50
|
* universal) is assignable: the catch-all `.with` overload must only fire for
|
|
@@ -127,7 +127,7 @@ type PinTooLate = {
|
|
|
127
127
|
*/
|
|
128
128
|
type Matcher<E, Remaining, O, Declared = Unset> = {
|
|
129
129
|
/**
|
|
130
|
-
* The catch-all arm: `.with(P._, handler)`
|
|
130
|
+
* The catch-all arm: `.with(P._, handler)` — the
|
|
131
131
|
* wildcard **escape hatch**, not the way to handle a concrete error union
|
|
132
132
|
* (name those cases; `@unthrown/oxlint`'s `no-catch-all-pattern`, in its
|
|
133
133
|
* `recommended` preset, flags the wildcard).
|
|
@@ -225,7 +225,7 @@ declare function match<const E>(value: E): Matcher<E, E, never>;
|
|
|
225
225
|
/**
|
|
226
226
|
* The pattern namespace (unthrown's own; the former ts-pattern `P`):
|
|
227
227
|
*
|
|
228
|
-
* - `P._`
|
|
228
|
+
* - `P._` — the universal catch-all, and an **escape hatch** rather
|
|
229
229
|
* than the default: matching the error channel means naming its cases, so
|
|
230
230
|
* reach for this only where they cannot be named. Matches anything, and
|
|
231
231
|
* (because its phantom type is `unknown`) makes the builder provably
|
|
@@ -243,27 +243,24 @@ declare function match<const E>(value: E): Matcher<E, E, never>;
|
|
|
243
243
|
* branch's parameter to that variant, payload included. The workhorse of the
|
|
244
244
|
* error channel: `matcher.with(P.tag("NotFound"), (e) => …)`. It composes like
|
|
245
245
|
* any other pattern — in a grouped arm
|
|
246
|
-
* (`.with(P.tag("A"), P.tag("B"), handler)`)
|
|
246
|
+
* (`.with(P.tag("A"), P.tag("B"), handler)`).
|
|
247
247
|
* - `P.instanceOf(Cls)` — an `instanceof` check, narrowing to the class
|
|
248
248
|
* instance type (for union members that are not tagged, e.g. a third-party
|
|
249
249
|
* error class).
|
|
250
|
-
* - `P.when(guard)` — an arbitrary type-guard predicate.
|
|
251
|
-
*
|
|
252
|
-
*
|
|
250
|
+
* - `P.when(guard)` — an arbitrary type-guard predicate. Also the way to match
|
|
251
|
+
* a primitive shape (`P.when((v): v is string => typeof v === "string")`),
|
|
252
|
+
* and grouping patterns under one handler is what a `.with(a, b, handler)`
|
|
253
|
+
* arm already does.
|
|
253
254
|
*
|
|
254
255
|
* @category Constructors
|
|
255
256
|
*/
|
|
256
257
|
declare const P: Readonly<{
|
|
257
258
|
_: UniversalPattern;
|
|
258
|
-
any: UniversalPattern;
|
|
259
259
|
tag: <const Tag extends string>(value: Tag) => {
|
|
260
260
|
_tag: Tag;
|
|
261
261
|
};
|
|
262
262
|
instanceOf: <C extends abstract new (...args: never[]) => unknown>(cls: C) => PatternMatcher<InstanceType<C>>;
|
|
263
263
|
when: <G>(guard: (value: unknown) => value is G) => PatternMatcher<G>;
|
|
264
|
-
union: <const Pts extends readonly [unknown, ...unknown[]]>(...patterns: Pts) => PatternMatcher<MatchedOf<Pts[number]>>;
|
|
265
|
-
string: PatternMatcher<string>;
|
|
266
|
-
number: PatternMatcher<number>;
|
|
267
264
|
}>;
|
|
268
265
|
//#endregion
|
|
269
266
|
//#region src/types.d.ts
|
|
@@ -1720,6 +1717,59 @@ declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qua
|
|
|
1720
1717
|
* ```
|
|
1721
1718
|
*/
|
|
1722
1719
|
declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult$1<T, never>;
|
|
1720
|
+
/**
|
|
1721
|
+
* The settler a {@link fromExecutor} executor receives. Settles the pending
|
|
1722
|
+
* `AsyncResult` **once** — later calls are no-ops, exactly as `resolve` is on a
|
|
1723
|
+
* `Promise`.
|
|
1724
|
+
*
|
|
1725
|
+
* @typeParam T - the success type.
|
|
1726
|
+
* @typeParam E - the modeled error type.
|
|
1727
|
+
*
|
|
1728
|
+
* @category Types
|
|
1729
|
+
*/
|
|
1730
|
+
type Settle<T, E> = (result: Result$1<T, E> | Defect) => void;
|
|
1731
|
+
/**
|
|
1732
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1733
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1734
|
+
*
|
|
1735
|
+
* @remarks
|
|
1736
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1737
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1738
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1739
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1740
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1741
|
+
* its own turn, long after the executor body returned).
|
|
1742
|
+
*
|
|
1743
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1744
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1745
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1746
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1747
|
+
* site, not a silently-`unknown` channel.
|
|
1748
|
+
*
|
|
1749
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1750
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1751
|
+
* `new Promise`.
|
|
1752
|
+
*
|
|
1753
|
+
* @typeParam T - the success type.
|
|
1754
|
+
* @typeParam E - the modeled error type.
|
|
1755
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1756
|
+
*
|
|
1757
|
+
* @category Interop
|
|
1758
|
+
*
|
|
1759
|
+
* @example
|
|
1760
|
+
* ```ts
|
|
1761
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1762
|
+
*
|
|
1763
|
+
* const listen = (port: number) =>
|
|
1764
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1765
|
+
* server.once("error", (cause) =>
|
|
1766
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1767
|
+
* );
|
|
1768
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1769
|
+
* });
|
|
1770
|
+
* ```
|
|
1771
|
+
*/
|
|
1772
|
+
declare function fromExecutor<T = never, E = never>(executor: (settle: Settle<T, E>, defect: (cause: unknown) => Defect) => void): AsyncResult$1<T, E>;
|
|
1723
1773
|
/**
|
|
1724
1774
|
* The success channel of {@link all} / {@link allAsync}: a **positional tuple**
|
|
1725
1775
|
* for a fixed-length input (including the empty tuple), or a homogeneous
|
|
@@ -1892,14 +1942,15 @@ type Result<T, E> = Result$1<T, E>;
|
|
|
1892
1942
|
/**
|
|
1893
1943
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1894
1944
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1895
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1896
|
-
* {@link AsyncResult.
|
|
1897
|
-
* {@link AsyncResult.allFromDict}.
|
|
1945
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1946
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1947
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1898
1948
|
*
|
|
1899
1949
|
* @remarks
|
|
1900
1950
|
* The async sibling of {@link Result}. Statics are grouped by what they
|
|
1901
|
-
* **return**, so the pre-lifted constructors, `
|
|
1902
|
-
* and the async aggregates sit here rather
|
|
1951
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1952
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1953
|
+
* than on {@link Result}; the namespace
|
|
1903
1954
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1904
1955
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1905
1956
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1924,6 +1975,7 @@ declare const AsyncResult: {
|
|
|
1924
1975
|
readonly Ok: typeof OkAsync;
|
|
1925
1976
|
readonly Err: typeof ErrAsync;
|
|
1926
1977
|
readonly Do: typeof DoAsync;
|
|
1978
|
+
readonly fromExecutor: typeof fromExecutor;
|
|
1927
1979
|
readonly fromPromise: typeof fromPromise;
|
|
1928
1980
|
readonly fromSafePromise: typeof fromSafePromise;
|
|
1929
1981
|
readonly all: typeof allAsync;
|
|
@@ -2052,4 +2104,4 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
|
2052
2104
|
readonly name?: string;
|
|
2053
2105
|
}): TaggedErrorConstructor<Tag>;
|
|
2054
2106
|
//#endregion
|
|
2055
|
-
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, DoAsync, Err, ErrAsync, type ErrMatcher, type ErrOf, type ErrView, type FailureView, GetError, type Matcher, NonExhaustiveError, type NotThenable, Ok, OkAsync, type OkOf, type OkView, P, type PatternMatcher, Result, type ResultMethods, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, type UniversalPattern, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|
|
2107
|
+
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, DoAsync, Err, ErrAsync, type ErrMatcher, type ErrOf, type ErrView, type FailureView, GetError, type Matcher, NonExhaustiveError, type NotThenable, Ok, OkAsync, type OkOf, type OkView, P, type PatternMatcher, Result, type ResultMethods, type Settle, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, type UniversalPattern, all, allAsync, allFromDict, allFromDictAsync, fromExecutor, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|
package/dist/index.d.mts
CHANGED
|
@@ -44,7 +44,7 @@ type PatternMatcher<M> = {
|
|
|
44
44
|
readonly [MATCHES]?: M;
|
|
45
45
|
};
|
|
46
46
|
/**
|
|
47
|
-
* The statically-known universal pattern — the type of `P._`
|
|
47
|
+
* The statically-known universal pattern — the type of `P._` only.
|
|
48
48
|
* The phantom `UNIVERSAL` marker is *required*, so no other
|
|
49
49
|
* `PatternMatcher<unknown>` (e.g. a `P.when` guard that happens to be
|
|
50
50
|
* universal) is assignable: the catch-all `.with` overload must only fire for
|
|
@@ -127,7 +127,7 @@ type PinTooLate = {
|
|
|
127
127
|
*/
|
|
128
128
|
type Matcher<E, Remaining, O, Declared = Unset> = {
|
|
129
129
|
/**
|
|
130
|
-
* The catch-all arm: `.with(P._, handler)`
|
|
130
|
+
* The catch-all arm: `.with(P._, handler)` — the
|
|
131
131
|
* wildcard **escape hatch**, not the way to handle a concrete error union
|
|
132
132
|
* (name those cases; `@unthrown/oxlint`'s `no-catch-all-pattern`, in its
|
|
133
133
|
* `recommended` preset, flags the wildcard).
|
|
@@ -225,7 +225,7 @@ declare function match<const E>(value: E): Matcher<E, E, never>;
|
|
|
225
225
|
/**
|
|
226
226
|
* The pattern namespace (unthrown's own; the former ts-pattern `P`):
|
|
227
227
|
*
|
|
228
|
-
* - `P._`
|
|
228
|
+
* - `P._` — the universal catch-all, and an **escape hatch** rather
|
|
229
229
|
* than the default: matching the error channel means naming its cases, so
|
|
230
230
|
* reach for this only where they cannot be named. Matches anything, and
|
|
231
231
|
* (because its phantom type is `unknown`) makes the builder provably
|
|
@@ -243,27 +243,24 @@ declare function match<const E>(value: E): Matcher<E, E, never>;
|
|
|
243
243
|
* branch's parameter to that variant, payload included. The workhorse of the
|
|
244
244
|
* error channel: `matcher.with(P.tag("NotFound"), (e) => …)`. It composes like
|
|
245
245
|
* any other pattern — in a grouped arm
|
|
246
|
-
* (`.with(P.tag("A"), P.tag("B"), handler)`)
|
|
246
|
+
* (`.with(P.tag("A"), P.tag("B"), handler)`).
|
|
247
247
|
* - `P.instanceOf(Cls)` — an `instanceof` check, narrowing to the class
|
|
248
248
|
* instance type (for union members that are not tagged, e.g. a third-party
|
|
249
249
|
* error class).
|
|
250
|
-
* - `P.when(guard)` — an arbitrary type-guard predicate.
|
|
251
|
-
*
|
|
252
|
-
*
|
|
250
|
+
* - `P.when(guard)` — an arbitrary type-guard predicate. Also the way to match
|
|
251
|
+
* a primitive shape (`P.when((v): v is string => typeof v === "string")`),
|
|
252
|
+
* and grouping patterns under one handler is what a `.with(a, b, handler)`
|
|
253
|
+
* arm already does.
|
|
253
254
|
*
|
|
254
255
|
* @category Constructors
|
|
255
256
|
*/
|
|
256
257
|
declare const P: Readonly<{
|
|
257
258
|
_: UniversalPattern;
|
|
258
|
-
any: UniversalPattern;
|
|
259
259
|
tag: <const Tag extends string>(value: Tag) => {
|
|
260
260
|
_tag: Tag;
|
|
261
261
|
};
|
|
262
262
|
instanceOf: <C extends abstract new (...args: never[]) => unknown>(cls: C) => PatternMatcher<InstanceType<C>>;
|
|
263
263
|
when: <G>(guard: (value: unknown) => value is G) => PatternMatcher<G>;
|
|
264
|
-
union: <const Pts extends readonly [unknown, ...unknown[]]>(...patterns: Pts) => PatternMatcher<MatchedOf<Pts[number]>>;
|
|
265
|
-
string: PatternMatcher<string>;
|
|
266
|
-
number: PatternMatcher<number>;
|
|
267
264
|
}>;
|
|
268
265
|
//#endregion
|
|
269
266
|
//#region src/types.d.ts
|
|
@@ -1720,6 +1717,59 @@ declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qua
|
|
|
1720
1717
|
* ```
|
|
1721
1718
|
*/
|
|
1722
1719
|
declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult$1<T, never>;
|
|
1720
|
+
/**
|
|
1721
|
+
* The settler a {@link fromExecutor} executor receives. Settles the pending
|
|
1722
|
+
* `AsyncResult` **once** — later calls are no-ops, exactly as `resolve` is on a
|
|
1723
|
+
* `Promise`.
|
|
1724
|
+
*
|
|
1725
|
+
* @typeParam T - the success type.
|
|
1726
|
+
* @typeParam E - the modeled error type.
|
|
1727
|
+
*
|
|
1728
|
+
* @category Types
|
|
1729
|
+
*/
|
|
1730
|
+
type Settle<T, E> = (result: Result$1<T, E> | Defect) => void;
|
|
1731
|
+
/**
|
|
1732
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1733
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1734
|
+
*
|
|
1735
|
+
* @remarks
|
|
1736
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1737
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1738
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1739
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1740
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1741
|
+
* its own turn, long after the executor body returned).
|
|
1742
|
+
*
|
|
1743
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1744
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1745
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1746
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1747
|
+
* site, not a silently-`unknown` channel.
|
|
1748
|
+
*
|
|
1749
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1750
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1751
|
+
* `new Promise`.
|
|
1752
|
+
*
|
|
1753
|
+
* @typeParam T - the success type.
|
|
1754
|
+
* @typeParam E - the modeled error type.
|
|
1755
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1756
|
+
*
|
|
1757
|
+
* @category Interop
|
|
1758
|
+
*
|
|
1759
|
+
* @example
|
|
1760
|
+
* ```ts
|
|
1761
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1762
|
+
*
|
|
1763
|
+
* const listen = (port: number) =>
|
|
1764
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1765
|
+
* server.once("error", (cause) =>
|
|
1766
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1767
|
+
* );
|
|
1768
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1769
|
+
* });
|
|
1770
|
+
* ```
|
|
1771
|
+
*/
|
|
1772
|
+
declare function fromExecutor<T = never, E = never>(executor: (settle: Settle<T, E>, defect: (cause: unknown) => Defect) => void): AsyncResult$1<T, E>;
|
|
1723
1773
|
/**
|
|
1724
1774
|
* The success channel of {@link all} / {@link allAsync}: a **positional tuple**
|
|
1725
1775
|
* for a fixed-length input (including the empty tuple), or a homogeneous
|
|
@@ -1892,14 +1942,15 @@ type Result<T, E> = Result$1<T, E>;
|
|
|
1892
1942
|
/**
|
|
1893
1943
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1894
1944
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1895
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1896
|
-
* {@link AsyncResult.
|
|
1897
|
-
* {@link AsyncResult.allFromDict}.
|
|
1945
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1946
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1947
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1898
1948
|
*
|
|
1899
1949
|
* @remarks
|
|
1900
1950
|
* The async sibling of {@link Result}. Statics are grouped by what they
|
|
1901
|
-
* **return**, so the pre-lifted constructors, `
|
|
1902
|
-
* and the async aggregates sit here rather
|
|
1951
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1952
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1953
|
+
* than on {@link Result}; the namespace
|
|
1903
1954
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1904
1955
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1905
1956
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1924,6 +1975,7 @@ declare const AsyncResult: {
|
|
|
1924
1975
|
readonly Ok: typeof OkAsync;
|
|
1925
1976
|
readonly Err: typeof ErrAsync;
|
|
1926
1977
|
readonly Do: typeof DoAsync;
|
|
1978
|
+
readonly fromExecutor: typeof fromExecutor;
|
|
1927
1979
|
readonly fromPromise: typeof fromPromise;
|
|
1928
1980
|
readonly fromSafePromise: typeof fromSafePromise;
|
|
1929
1981
|
readonly all: typeof allAsync;
|
|
@@ -2052,4 +2104,4 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
|
2052
2104
|
readonly name?: string;
|
|
2053
2105
|
}): TaggedErrorConstructor<Tag>;
|
|
2054
2106
|
//#endregion
|
|
2055
|
-
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, DoAsync, Err, ErrAsync, type ErrMatcher, type ErrOf, type ErrView, type FailureView, GetError, type Matcher, NonExhaustiveError, type NotThenable, Ok, OkAsync, type OkOf, type OkView, P, type PatternMatcher, Result, type ResultMethods, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, type UniversalPattern, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|
|
2107
|
+
export { type AsyncErrOf, type AsyncOkOf, AsyncResult, type AsyncResultMethods, type Awaitable, type DefectView, Do, DoAsync, Err, ErrAsync, type ErrMatcher, type ErrOf, type ErrView, type FailureView, GetError, type Matcher, NonExhaustiveError, type NotThenable, Ok, OkAsync, type OkOf, type OkView, P, type PatternMatcher, Result, type ResultMethods, type Settle, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, type UniversalPattern, all, allAsync, allFromDict, allFromDictAsync, fromExecutor, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|
package/dist/index.mjs
CHANGED
|
@@ -134,7 +134,7 @@ const universal = pattern(() => true);
|
|
|
134
134
|
/**
|
|
135
135
|
* The pattern namespace (unthrown's own; the former ts-pattern `P`):
|
|
136
136
|
*
|
|
137
|
-
* - `P._`
|
|
137
|
+
* - `P._` — the universal catch-all, and an **escape hatch** rather
|
|
138
138
|
* than the default: matching the error channel means naming its cases, so
|
|
139
139
|
* reach for this only where they cannot be named. Matches anything, and
|
|
140
140
|
* (because its phantom type is `unknown`) makes the builder provably
|
|
@@ -152,25 +152,22 @@ const universal = pattern(() => true);
|
|
|
152
152
|
* branch's parameter to that variant, payload included. The workhorse of the
|
|
153
153
|
* error channel: `matcher.with(P.tag("NotFound"), (e) => …)`. It composes like
|
|
154
154
|
* any other pattern — in a grouped arm
|
|
155
|
-
* (`.with(P.tag("A"), P.tag("B"), handler)`)
|
|
155
|
+
* (`.with(P.tag("A"), P.tag("B"), handler)`).
|
|
156
156
|
* - `P.instanceOf(Cls)` — an `instanceof` check, narrowing to the class
|
|
157
157
|
* instance type (for union members that are not tagged, e.g. a third-party
|
|
158
158
|
* error class).
|
|
159
|
-
* - `P.when(guard)` — an arbitrary type-guard predicate.
|
|
160
|
-
*
|
|
161
|
-
*
|
|
159
|
+
* - `P.when(guard)` — an arbitrary type-guard predicate. Also the way to match
|
|
160
|
+
* a primitive shape (`P.when((v): v is string => typeof v === "string")`),
|
|
161
|
+
* and grouping patterns under one handler is what a `.with(a, b, handler)`
|
|
162
|
+
* arm already does.
|
|
162
163
|
*
|
|
163
164
|
* @category Constructors
|
|
164
165
|
*/
|
|
165
166
|
const P = Object.freeze({
|
|
166
167
|
_: universal,
|
|
167
|
-
any: universal,
|
|
168
168
|
tag: (value) => ({ _tag: value }),
|
|
169
169
|
instanceOf: (cls) => pattern((value) => value instanceof cls),
|
|
170
|
-
when: (guard) => pattern(guard)
|
|
171
|
-
union: (...patterns) => pattern((value) => patterns.some((sub) => matches(sub, value))),
|
|
172
|
-
string: pattern((value) => typeof value === "string"),
|
|
173
|
-
number: pattern((value) => typeof value === "number")
|
|
170
|
+
when: (guard) => pattern(guard)
|
|
174
171
|
});
|
|
175
172
|
//#endregion
|
|
176
173
|
//#region src/defect.ts
|
|
@@ -568,6 +565,30 @@ function passThrough(self) {
|
|
|
568
565
|
return self;
|
|
569
566
|
}
|
|
570
567
|
/**
|
|
568
|
+
* Runtime thenable probe, shared by the combinator-side net below and the
|
|
569
|
+
* boundary nets in `interop.ts`.
|
|
570
|
+
*
|
|
571
|
+
* @remarks
|
|
572
|
+
* Reading `.then` can itself **throw** — a hostile getter, or a Proxy `get`
|
|
573
|
+
* trap — so this is deliberately not a total function, and every caller must
|
|
574
|
+
* account for that. Two shapes are sanctioned, and there is no third:
|
|
575
|
+
*
|
|
576
|
+
* - inside a `try` that routes the throw to a `Defect` (the boundaries in
|
|
577
|
+
* `interop.ts`, where a hostile value arriving at a triage point *is* an
|
|
578
|
+
* unmodeled failure and should surface as one); or
|
|
579
|
+
* - through {@link silenceIfThenable}, for a value being **discarded**, where
|
|
580
|
+
* there is no Defect channel to route to and the only correct answer is to
|
|
581
|
+
* drop it without throwing.
|
|
582
|
+
*
|
|
583
|
+
* Calling it bare, outside both, is a bug: the throw escapes into whatever
|
|
584
|
+
* context invoked it.
|
|
585
|
+
*
|
|
586
|
+
* @internal
|
|
587
|
+
*/
|
|
588
|
+
function isThenable(x) {
|
|
589
|
+
return (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function";
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
571
592
|
* Adopt-and-silence a thenable a combinator is about to **discard**.
|
|
572
593
|
*
|
|
573
594
|
* @remarks
|
|
@@ -588,7 +609,7 @@ function passThrough(self) {
|
|
|
588
609
|
*/
|
|
589
610
|
function silenceIfThenable(value) {
|
|
590
611
|
try {
|
|
591
|
-
if ((
|
|
612
|
+
if (isThenable(value)) Promise.resolve(value).then(void 0, () => void 0);
|
|
592
613
|
} catch {}
|
|
593
614
|
}
|
|
594
615
|
/**
|
|
@@ -669,18 +690,29 @@ var AsyncRes = class AsyncRes {
|
|
|
669
690
|
constructor(promise) {
|
|
670
691
|
this.#promise = promise;
|
|
671
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Lift a **synchronous** `Result` combinator over the wrapped promise.
|
|
695
|
+
*
|
|
696
|
+
* @remarks
|
|
697
|
+
* Every method below that does no `await` of its own is exactly its `Res`
|
|
698
|
+
* twin applied to the settled `Result` — same tag check, same try/catch, same
|
|
699
|
+
* throw→defect net. Delegating instead of restating it keeps the two surfaces
|
|
700
|
+
* from drifting: a fix to the sync combinator is the fix to the async one.
|
|
701
|
+
* The methods that DO await a callback's result (`flatMap`, `flatTap`,
|
|
702
|
+
* `bind`, `flatMapErrCases`, `flatTapErrCases`, `recoverDefect` — the ones
|
|
703
|
+
* whose callback may hand back an `AsyncResult`) genuinely differ and are
|
|
704
|
+
* still written out in full.
|
|
705
|
+
*
|
|
706
|
+
* @internal
|
|
707
|
+
*/
|
|
708
|
+
#lift(f) {
|
|
709
|
+
return new AsyncRes(this.#promise.then(f));
|
|
710
|
+
}
|
|
672
711
|
then(onfulfilled, onrejected) {
|
|
673
712
|
return this.#promise.then(onfulfilled, onrejected);
|
|
674
713
|
}
|
|
675
714
|
map(f) {
|
|
676
|
-
return
|
|
677
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
678
|
-
try {
|
|
679
|
-
return okRes(f(r.value));
|
|
680
|
-
} catch (cause) {
|
|
681
|
-
return defectRes(cause);
|
|
682
|
-
}
|
|
683
|
-
}));
|
|
715
|
+
return this.#lift((r) => r.map(f));
|
|
684
716
|
}
|
|
685
717
|
flatMap(f) {
|
|
686
718
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -694,15 +726,7 @@ var AsyncRes = class AsyncRes {
|
|
|
694
726
|
}));
|
|
695
727
|
}
|
|
696
728
|
tap(f) {
|
|
697
|
-
return
|
|
698
|
-
if (r.tag !== "Ok") return r;
|
|
699
|
-
try {
|
|
700
|
-
silenceIfThenable(f(r.value));
|
|
701
|
-
return r;
|
|
702
|
-
} catch (cause) {
|
|
703
|
-
return defectRes(cause);
|
|
704
|
-
}
|
|
705
|
-
}));
|
|
729
|
+
return this.#lift((r) => r.tap(f));
|
|
706
730
|
}
|
|
707
731
|
flatTap(f) {
|
|
708
732
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -733,45 +757,19 @@ var AsyncRes = class AsyncRes {
|
|
|
733
757
|
}));
|
|
734
758
|
}
|
|
735
759
|
let(name, f) {
|
|
736
|
-
return
|
|
737
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
738
|
-
try {
|
|
739
|
-
return okRes({
|
|
740
|
-
...scopeOf(r.value),
|
|
741
|
-
[name]: f(r.value)
|
|
742
|
-
});
|
|
743
|
-
} catch (cause) {
|
|
744
|
-
return defectRes(cause);
|
|
745
|
-
}
|
|
746
|
-
}));
|
|
760
|
+
return this.#lift((r) => r.let(name, f));
|
|
747
761
|
}
|
|
748
762
|
as(value) {
|
|
749
|
-
return
|
|
763
|
+
return this.#lift((r) => r.as(value));
|
|
750
764
|
}
|
|
751
765
|
discard() {
|
|
752
|
-
return
|
|
766
|
+
return this.#lift((r) => r.discard());
|
|
753
767
|
}
|
|
754
768
|
ensure(predicate, onFail) {
|
|
755
|
-
return
|
|
756
|
-
if (r.tag !== "Ok") return passThrough(r);
|
|
757
|
-
try {
|
|
758
|
-
return predicate(r.value) ? r : errRes(onFail(r.value));
|
|
759
|
-
} catch (cause) {
|
|
760
|
-
return defectRes(cause);
|
|
761
|
-
}
|
|
762
|
-
}));
|
|
769
|
+
return this.#lift((r) => r.ensure(predicate, onFail));
|
|
763
770
|
}
|
|
764
771
|
mapErrCases(f) {
|
|
765
|
-
return
|
|
766
|
-
if (r.tag !== "Err") return passThrough(r);
|
|
767
|
-
try {
|
|
768
|
-
const out = runMatch(f, r.error);
|
|
769
|
-
if (isDefectMarker(out)) return defectRes(out.cause);
|
|
770
|
-
return errRes(out);
|
|
771
|
-
} catch (cause) {
|
|
772
|
-
return defectRes(cause);
|
|
773
|
-
}
|
|
774
|
-
}));
|
|
772
|
+
return this.#lift((r) => r.mapErrCases(f));
|
|
775
773
|
}
|
|
776
774
|
flatMapErrCases(f) {
|
|
777
775
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -788,29 +786,10 @@ var AsyncRes = class AsyncRes {
|
|
|
788
786
|
}));
|
|
789
787
|
}
|
|
790
788
|
recoverErrCases(f) {
|
|
791
|
-
return
|
|
792
|
-
if (r.tag !== "Err") return passThrough(r);
|
|
793
|
-
try {
|
|
794
|
-
const out = runMatch(f, r.error);
|
|
795
|
-
if (isDefectMarker(out)) return defectRes(out.cause);
|
|
796
|
-
return okRes(out);
|
|
797
|
-
} catch (cause) {
|
|
798
|
-
return defectRes(cause);
|
|
799
|
-
}
|
|
800
|
-
}));
|
|
789
|
+
return this.#lift((r) => r.recoverErrCases(f));
|
|
801
790
|
}
|
|
802
791
|
tapErrCases(f) {
|
|
803
|
-
return
|
|
804
|
-
if (r.tag !== "Err") return r;
|
|
805
|
-
try {
|
|
806
|
-
const out = runMatch(f, r.error);
|
|
807
|
-
if (isDefectMarker(out)) return observerThrowToDefect(out.cause, r.error);
|
|
808
|
-
silenceIfThenable(out);
|
|
809
|
-
return r;
|
|
810
|
-
} catch (cause) {
|
|
811
|
-
return observerThrowToDefect(cause, r.error);
|
|
812
|
-
}
|
|
813
|
-
}));
|
|
792
|
+
return this.#lift((r) => r.tapErrCases(f));
|
|
814
793
|
}
|
|
815
794
|
flatTapErrCases(f) {
|
|
816
795
|
return new AsyncRes(this.#promise.then(async (r) => {
|
|
@@ -838,26 +817,10 @@ var AsyncRes = class AsyncRes {
|
|
|
838
817
|
}));
|
|
839
818
|
}
|
|
840
819
|
tapDefect(f) {
|
|
841
|
-
return
|
|
842
|
-
if (r.tag !== "Defect") return r;
|
|
843
|
-
try {
|
|
844
|
-
silenceIfThenable(f(r.cause));
|
|
845
|
-
return r;
|
|
846
|
-
} catch (cause) {
|
|
847
|
-
return observerThrowToDefect(cause, r.cause);
|
|
848
|
-
}
|
|
849
|
-
}));
|
|
820
|
+
return this.#lift((r) => r.tapDefect(f));
|
|
850
821
|
}
|
|
851
822
|
tapFailure(f) {
|
|
852
|
-
return
|
|
853
|
-
if (r.tag === "Ok") return r;
|
|
854
|
-
try {
|
|
855
|
-
silenceIfThenable(f(r));
|
|
856
|
-
return r;
|
|
857
|
-
} catch (cause) {
|
|
858
|
-
return observerThrowToDefect(cause, r.tag === "Err" ? r.error : r.cause);
|
|
859
|
-
}
|
|
860
|
-
}));
|
|
823
|
+
return this.#lift((r) => r.tapFailure(f));
|
|
861
824
|
}
|
|
862
825
|
match(cases) {
|
|
863
826
|
return this.#promise.then((r) => r.match(cases));
|
|
@@ -1287,6 +1250,72 @@ function fromPromise(promise, qualify, ..._guard) {
|
|
|
1287
1250
|
function fromSafePromise(promise) {
|
|
1288
1251
|
return new AsyncRes((typeof promise === "function" ? Promise.resolve().then(promise) : Promise.resolve(promise)).then((value) => okRes(value), (cause) => defectRes(cause)));
|
|
1289
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1255
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1256
|
+
*
|
|
1257
|
+
* @remarks
|
|
1258
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1259
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1260
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1261
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1262
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1263
|
+
* its own turn, long after the executor body returned).
|
|
1264
|
+
*
|
|
1265
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1266
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1267
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1268
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1269
|
+
* site, not a silently-`unknown` channel.
|
|
1270
|
+
*
|
|
1271
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1272
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1273
|
+
* `new Promise`.
|
|
1274
|
+
*
|
|
1275
|
+
* @typeParam T - the success type.
|
|
1276
|
+
* @typeParam E - the modeled error type.
|
|
1277
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1278
|
+
*
|
|
1279
|
+
* @category Interop
|
|
1280
|
+
*
|
|
1281
|
+
* @example
|
|
1282
|
+
* ```ts
|
|
1283
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1284
|
+
*
|
|
1285
|
+
* const listen = (port: number) =>
|
|
1286
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1287
|
+
* server.once("error", (cause) =>
|
|
1288
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1289
|
+
* );
|
|
1290
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1291
|
+
* });
|
|
1292
|
+
* ```
|
|
1293
|
+
*/
|
|
1294
|
+
function fromExecutor(executor) {
|
|
1295
|
+
let resolve;
|
|
1296
|
+
const promise = new Promise((r) => {
|
|
1297
|
+
resolve = r;
|
|
1298
|
+
});
|
|
1299
|
+
const settle = (result) => {
|
|
1300
|
+
if (isDefectMarker(result)) {
|
|
1301
|
+
resolve(defectRes(result.cause));
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
if (!isResult(result)) {
|
|
1305
|
+
silenceIfThenable(result);
|
|
1306
|
+
resolve(defectRes(/* @__PURE__ */ new TypeError("unthrown: fromExecutor's settle received a non-Result value")));
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
resolve(result);
|
|
1310
|
+
};
|
|
1311
|
+
try {
|
|
1312
|
+
const returned = executor(settle, defect);
|
|
1313
|
+
if (isThenable(returned)) Promise.resolve(returned).then(void 0, (cause) => settle(defect(cause)));
|
|
1314
|
+
} catch (cause) {
|
|
1315
|
+
settle(defect(cause));
|
|
1316
|
+
}
|
|
1317
|
+
return new AsyncRes(promise);
|
|
1318
|
+
}
|
|
1290
1319
|
function qualifyToResult(cause, qualify) {
|
|
1291
1320
|
try {
|
|
1292
1321
|
const q = qualify(cause, defect);
|
|
@@ -1327,15 +1356,6 @@ function thenableReturnDefect(value) {
|
|
|
1327
1356
|
return defectRes(/* @__PURE__ */ new TypeError("unthrown: fromThrowable/fromSafeThrowable wrap a SYNCHRONOUS function, but `fn` returned a thenable — its rejection would escape qualification. Use fromPromise/fromSafePromise instead."));
|
|
1328
1357
|
}
|
|
1329
1358
|
/**
|
|
1330
|
-
* Runtime thenable probe for the belt-and-braces guards above. Called inside the
|
|
1331
|
-
* caller's `try`, so even a hostile `.then` getter lands on the Defect path.
|
|
1332
|
-
*
|
|
1333
|
-
* @internal
|
|
1334
|
-
*/
|
|
1335
|
-
function isThenable(x) {
|
|
1336
|
-
return (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function";
|
|
1337
|
-
}
|
|
1338
|
-
/**
|
|
1339
1359
|
* Fold an array of settled `Result`s: first `Err` wins, any `Defect` dominates,
|
|
1340
1360
|
* else `Ok` of the values array.
|
|
1341
1361
|
*
|
|
@@ -1364,32 +1384,23 @@ function foldArray(results) {
|
|
|
1364
1384
|
}
|
|
1365
1385
|
/**
|
|
1366
1386
|
* Fold a record of settled `Result`s with the same rules, else `Ok` of the
|
|
1367
|
-
* record of values.
|
|
1368
|
-
*
|
|
1387
|
+
* record of values.
|
|
1388
|
+
*
|
|
1389
|
+
* @remarks
|
|
1390
|
+
* The positional fold already implements every rule (first `Err` wins, any
|
|
1391
|
+
* `Defect` dominates, a non-`Result` element becomes a `Defect`), so this pairs
|
|
1392
|
+
* the keys back onto its success value rather than restating them.
|
|
1393
|
+
*
|
|
1394
|
+
* `Object.fromEntries` is what makes a caller-supplied `"__proto__"` key safe:
|
|
1395
|
+
* it builds each key with CreateDataProperty, which defines an own property
|
|
1396
|
+
* instead of invoking the `__proto__` setter — the same guarantee the previous
|
|
1397
|
+
* explicit `Object.defineProperty` loop bought by hand.
|
|
1369
1398
|
*
|
|
1370
1399
|
* @internal
|
|
1371
1400
|
*/
|
|
1372
1401
|
function foldRecord(results) {
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
const values = {};
|
|
1376
|
-
for (const [key, r] of Object.entries(results)) {
|
|
1377
|
-
if (!isResult(r)) {
|
|
1378
|
-
firstDefect ??= nonResultDefect();
|
|
1379
|
-
break;
|
|
1380
|
-
}
|
|
1381
|
-
if (r.tag === "Defect") {
|
|
1382
|
-
firstDefect ??= r;
|
|
1383
|
-
break;
|
|
1384
|
-
} else if (r.tag === "Err") firstErr ??= r;
|
|
1385
|
-
else Object.defineProperty(values, key, {
|
|
1386
|
-
value: r.value,
|
|
1387
|
-
enumerable: true,
|
|
1388
|
-
writable: true,
|
|
1389
|
-
configurable: true
|
|
1390
|
-
});
|
|
1391
|
-
}
|
|
1392
|
-
return firstDefect ?? firstErr ?? Ok(values);
|
|
1402
|
+
const keys = Object.keys(results);
|
|
1403
|
+
return foldArray(Object.values(results)).map((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]])));
|
|
1393
1404
|
}
|
|
1394
1405
|
/**
|
|
1395
1406
|
* Collect a tuple/array of {@link Result}s into a single `Result` of all their
|
|
@@ -1487,14 +1498,8 @@ function allAsync(results) {
|
|
|
1487
1498
|
* ```
|
|
1488
1499
|
*/
|
|
1489
1500
|
function allFromDictAsync(results) {
|
|
1490
|
-
const
|
|
1491
|
-
return new AsyncRes(Promise.all(
|
|
1492
|
-
const byKey = Object.create(null);
|
|
1493
|
-
entries.forEach(([key], i) => {
|
|
1494
|
-
byKey[key] = resolved[i];
|
|
1495
|
-
});
|
|
1496
|
-
return foldRecord(byKey);
|
|
1497
|
-
}));
|
|
1501
|
+
const keys = Object.keys(results);
|
|
1502
|
+
return new AsyncRes(Promise.all(Object.values(results).map((ar) => Promise.resolve(ar).then((x) => x, (cause) => defectRes(cause)))).then((resolved) => foldArray(resolved).map((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]])))));
|
|
1498
1503
|
}
|
|
1499
1504
|
//#endregion
|
|
1500
1505
|
//#region src/facade.ts
|
|
@@ -1541,14 +1546,15 @@ const Result = {
|
|
|
1541
1546
|
/**
|
|
1542
1547
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1543
1548
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1544
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1545
|
-
* {@link AsyncResult.
|
|
1546
|
-
* {@link AsyncResult.allFromDict}.
|
|
1549
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1550
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1551
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1547
1552
|
*
|
|
1548
1553
|
* @remarks
|
|
1549
1554
|
* The async sibling of {@link Result}. Statics are grouped by what they
|
|
1550
|
-
* **return**, so the pre-lifted constructors, `
|
|
1551
|
-
* and the async aggregates sit here rather
|
|
1555
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1556
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1557
|
+
* than on {@link Result}; the namespace
|
|
1552
1558
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1553
1559
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1554
1560
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1573,6 +1579,7 @@ const AsyncResult = {
|
|
|
1573
1579
|
Ok: OkAsync,
|
|
1574
1580
|
Err: ErrAsync,
|
|
1575
1581
|
Do: DoAsync,
|
|
1582
|
+
fromExecutor,
|
|
1576
1583
|
fromPromise,
|
|
1577
1584
|
fromSafePromise,
|
|
1578
1585
|
all: allAsync,
|
|
@@ -1669,4 +1676,4 @@ function TaggedError(tag, options) {
|
|
|
1669
1676
|
return TaggedErrorBase;
|
|
1670
1677
|
}
|
|
1671
1678
|
//#endregion
|
|
1672
|
-
export { AsyncResult, Do, DoAsync, Err, ErrAsync, GetError, NonExhaustiveError, Ok, OkAsync, P, Result, TaggedError, all, allAsync, allFromDict, allFromDictAsync, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|
|
1679
|
+
export { AsyncResult, Do, DoAsync, Err, ErrAsync, GetError, NonExhaustiveError, Ok, OkAsync, P, Result, TaggedError, all, allAsync, allFromDict, allFromDictAsync, fromExecutor, fromNullable, fromPromise, fromSafePromise, fromSafeThrowable, fromThrowable, isDefect, isErr, isOk, isResult, match };
|