unthrown 5.2.0 → 5.3.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 +74 -5
- package/dist/index.d.cts +61 -6
- package/dist/index.d.mts +61 -6
- package/dist/index.mjs +74 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1288,6 +1288,72 @@ function fromPromise(promise, qualify, ..._guard) {
|
|
|
1288
1288
|
function fromSafePromise(promise) {
|
|
1289
1289
|
return new AsyncRes((typeof promise === "function" ? Promise.resolve().then(promise) : Promise.resolve(promise)).then((value) => okRes(value), (cause) => defectRes(cause)));
|
|
1290
1290
|
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1293
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1294
|
+
*
|
|
1295
|
+
* @remarks
|
|
1296
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1297
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1298
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1299
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1300
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1301
|
+
* its own turn, long after the executor body returned).
|
|
1302
|
+
*
|
|
1303
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1304
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1305
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1306
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1307
|
+
* site, not a silently-`unknown` channel.
|
|
1308
|
+
*
|
|
1309
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1310
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1311
|
+
* `new Promise`.
|
|
1312
|
+
*
|
|
1313
|
+
* @typeParam T - the success type.
|
|
1314
|
+
* @typeParam E - the modeled error type.
|
|
1315
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1316
|
+
*
|
|
1317
|
+
* @category Interop
|
|
1318
|
+
*
|
|
1319
|
+
* @example
|
|
1320
|
+
* ```ts
|
|
1321
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1322
|
+
*
|
|
1323
|
+
* const listen = (port: number) =>
|
|
1324
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1325
|
+
* server.once("error", (cause) =>
|
|
1326
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1327
|
+
* );
|
|
1328
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1329
|
+
* });
|
|
1330
|
+
* ```
|
|
1331
|
+
*/
|
|
1332
|
+
function fromExecutor(executor) {
|
|
1333
|
+
let resolve;
|
|
1334
|
+
const promise = new Promise((r) => {
|
|
1335
|
+
resolve = r;
|
|
1336
|
+
});
|
|
1337
|
+
const settle = (result) => {
|
|
1338
|
+
if (isDefectMarker(result)) {
|
|
1339
|
+
resolve(defectRes(result.cause));
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
if (!isResult(result)) {
|
|
1343
|
+
if (isThenable(result)) Promise.resolve(result).then(void 0, () => void 0);
|
|
1344
|
+
resolve(defectRes(/* @__PURE__ */ new TypeError("unthrown: fromExecutor's settle received a non-Result value")));
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
resolve(result);
|
|
1348
|
+
};
|
|
1349
|
+
try {
|
|
1350
|
+
const returned = executor(settle, defect);
|
|
1351
|
+
if (isThenable(returned)) Promise.resolve(returned).then(void 0, (cause) => settle(defect(cause)));
|
|
1352
|
+
} catch (cause) {
|
|
1353
|
+
settle(defect(cause));
|
|
1354
|
+
}
|
|
1355
|
+
return new AsyncRes(promise);
|
|
1356
|
+
}
|
|
1291
1357
|
function qualifyToResult(cause, qualify) {
|
|
1292
1358
|
try {
|
|
1293
1359
|
const q = qualify(cause, defect);
|
|
@@ -1542,14 +1608,15 @@ const Result = {
|
|
|
1542
1608
|
/**
|
|
1543
1609
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1544
1610
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1545
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1546
|
-
* {@link AsyncResult.
|
|
1547
|
-
* {@link AsyncResult.allFromDict}.
|
|
1611
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1612
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1613
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1548
1614
|
*
|
|
1549
1615
|
* @remarks
|
|
1550
1616
|
* 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
|
|
1617
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1618
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1619
|
+
* than on {@link Result}; the namespace
|
|
1553
1620
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1554
1621
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1555
1622
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1574,6 +1641,7 @@ const AsyncResult = {
|
|
|
1574
1641
|
Ok: OkAsync,
|
|
1575
1642
|
Err: ErrAsync,
|
|
1576
1643
|
Do: DoAsync,
|
|
1644
|
+
fromExecutor,
|
|
1577
1645
|
fromPromise,
|
|
1578
1646
|
fromSafePromise,
|
|
1579
1647
|
all: allAsync,
|
|
@@ -1686,6 +1754,7 @@ exports.all = all;
|
|
|
1686
1754
|
exports.allAsync = allAsync;
|
|
1687
1755
|
exports.allFromDict = allFromDict;
|
|
1688
1756
|
exports.allFromDictAsync = allFromDictAsync;
|
|
1757
|
+
exports.fromExecutor = fromExecutor;
|
|
1689
1758
|
exports.fromNullable = fromNullable;
|
|
1690
1759
|
exports.fromPromise = fromPromise;
|
|
1691
1760
|
exports.fromSafePromise = fromSafePromise;
|
package/dist/index.d.cts
CHANGED
|
@@ -1720,6 +1720,59 @@ declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qua
|
|
|
1720
1720
|
* ```
|
|
1721
1721
|
*/
|
|
1722
1722
|
declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult$1<T, never>;
|
|
1723
|
+
/**
|
|
1724
|
+
* The settler a {@link fromExecutor} executor receives. Settles the pending
|
|
1725
|
+
* `AsyncResult` **once** — later calls are no-ops, exactly as `resolve` is on a
|
|
1726
|
+
* `Promise`.
|
|
1727
|
+
*
|
|
1728
|
+
* @typeParam T - the success type.
|
|
1729
|
+
* @typeParam E - the modeled error type.
|
|
1730
|
+
*
|
|
1731
|
+
* @category Types
|
|
1732
|
+
*/
|
|
1733
|
+
type Settle<T, E> = (result: Result$1<T, E> | Defect) => void;
|
|
1734
|
+
/**
|
|
1735
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1736
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1737
|
+
*
|
|
1738
|
+
* @remarks
|
|
1739
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1740
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1741
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1742
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1743
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1744
|
+
* its own turn, long after the executor body returned).
|
|
1745
|
+
*
|
|
1746
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1747
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1748
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1749
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1750
|
+
* site, not a silently-`unknown` channel.
|
|
1751
|
+
*
|
|
1752
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1753
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1754
|
+
* `new Promise`.
|
|
1755
|
+
*
|
|
1756
|
+
* @typeParam T - the success type.
|
|
1757
|
+
* @typeParam E - the modeled error type.
|
|
1758
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1759
|
+
*
|
|
1760
|
+
* @category Interop
|
|
1761
|
+
*
|
|
1762
|
+
* @example
|
|
1763
|
+
* ```ts
|
|
1764
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1765
|
+
*
|
|
1766
|
+
* const listen = (port: number) =>
|
|
1767
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1768
|
+
* server.once("error", (cause) =>
|
|
1769
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1770
|
+
* );
|
|
1771
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1772
|
+
* });
|
|
1773
|
+
* ```
|
|
1774
|
+
*/
|
|
1775
|
+
declare function fromExecutor<T = never, E = never>(executor: (settle: Settle<T, E>, defect: (cause: unknown) => Defect) => void): AsyncResult$1<T, E>;
|
|
1723
1776
|
/**
|
|
1724
1777
|
* The success channel of {@link all} / {@link allAsync}: a **positional tuple**
|
|
1725
1778
|
* for a fixed-length input (including the empty tuple), or a homogeneous
|
|
@@ -1892,14 +1945,15 @@ type Result<T, E> = Result$1<T, E>;
|
|
|
1892
1945
|
/**
|
|
1893
1946
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1894
1947
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1895
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1896
|
-
* {@link AsyncResult.
|
|
1897
|
-
* {@link AsyncResult.allFromDict}.
|
|
1948
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1949
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1950
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1898
1951
|
*
|
|
1899
1952
|
* @remarks
|
|
1900
1953
|
* 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
|
|
1954
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1955
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1956
|
+
* than on {@link Result}; the namespace
|
|
1903
1957
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1904
1958
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1905
1959
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1924,6 +1978,7 @@ declare const AsyncResult: {
|
|
|
1924
1978
|
readonly Ok: typeof OkAsync;
|
|
1925
1979
|
readonly Err: typeof ErrAsync;
|
|
1926
1980
|
readonly Do: typeof DoAsync;
|
|
1981
|
+
readonly fromExecutor: typeof fromExecutor;
|
|
1927
1982
|
readonly fromPromise: typeof fromPromise;
|
|
1928
1983
|
readonly fromSafePromise: typeof fromSafePromise;
|
|
1929
1984
|
readonly all: typeof allAsync;
|
|
@@ -2052,4 +2107,4 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
|
2052
2107
|
readonly name?: string;
|
|
2053
2108
|
}): TaggedErrorConstructor<Tag>;
|
|
2054
2109
|
//#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 };
|
|
2110
|
+
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
|
@@ -1720,6 +1720,59 @@ declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qua
|
|
|
1720
1720
|
* ```
|
|
1721
1721
|
*/
|
|
1722
1722
|
declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult$1<T, never>;
|
|
1723
|
+
/**
|
|
1724
|
+
* The settler a {@link fromExecutor} executor receives. Settles the pending
|
|
1725
|
+
* `AsyncResult` **once** — later calls are no-ops, exactly as `resolve` is on a
|
|
1726
|
+
* `Promise`.
|
|
1727
|
+
*
|
|
1728
|
+
* @typeParam T - the success type.
|
|
1729
|
+
* @typeParam E - the modeled error type.
|
|
1730
|
+
*
|
|
1731
|
+
* @category Types
|
|
1732
|
+
*/
|
|
1733
|
+
type Settle<T, E> = (result: Result$1<T, E> | Defect) => void;
|
|
1734
|
+
/**
|
|
1735
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1736
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1737
|
+
*
|
|
1738
|
+
* @remarks
|
|
1739
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1740
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1741
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1742
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1743
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1744
|
+
* its own turn, long after the executor body returned).
|
|
1745
|
+
*
|
|
1746
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1747
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1748
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1749
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1750
|
+
* site, not a silently-`unknown` channel.
|
|
1751
|
+
*
|
|
1752
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1753
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1754
|
+
* `new Promise`.
|
|
1755
|
+
*
|
|
1756
|
+
* @typeParam T - the success type.
|
|
1757
|
+
* @typeParam E - the modeled error type.
|
|
1758
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1759
|
+
*
|
|
1760
|
+
* @category Interop
|
|
1761
|
+
*
|
|
1762
|
+
* @example
|
|
1763
|
+
* ```ts
|
|
1764
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1765
|
+
*
|
|
1766
|
+
* const listen = (port: number) =>
|
|
1767
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1768
|
+
* server.once("error", (cause) =>
|
|
1769
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1770
|
+
* );
|
|
1771
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1772
|
+
* });
|
|
1773
|
+
* ```
|
|
1774
|
+
*/
|
|
1775
|
+
declare function fromExecutor<T = never, E = never>(executor: (settle: Settle<T, E>, defect: (cause: unknown) => Defect) => void): AsyncResult$1<T, E>;
|
|
1723
1776
|
/**
|
|
1724
1777
|
* The success channel of {@link all} / {@link allAsync}: a **positional tuple**
|
|
1725
1778
|
* for a fixed-length input (including the empty tuple), or a homogeneous
|
|
@@ -1892,14 +1945,15 @@ type Result<T, E> = Result$1<T, E>;
|
|
|
1892
1945
|
/**
|
|
1893
1946
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1894
1947
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1895
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1896
|
-
* {@link AsyncResult.
|
|
1897
|
-
* {@link AsyncResult.allFromDict}.
|
|
1948
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1949
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1950
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1898
1951
|
*
|
|
1899
1952
|
* @remarks
|
|
1900
1953
|
* 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
|
|
1954
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1955
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1956
|
+
* than on {@link Result}; the namespace
|
|
1903
1957
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1904
1958
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1905
1959
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1924,6 +1978,7 @@ declare const AsyncResult: {
|
|
|
1924
1978
|
readonly Ok: typeof OkAsync;
|
|
1925
1979
|
readonly Err: typeof ErrAsync;
|
|
1926
1980
|
readonly Do: typeof DoAsync;
|
|
1981
|
+
readonly fromExecutor: typeof fromExecutor;
|
|
1927
1982
|
readonly fromPromise: typeof fromPromise;
|
|
1928
1983
|
readonly fromSafePromise: typeof fromSafePromise;
|
|
1929
1984
|
readonly all: typeof allAsync;
|
|
@@ -2052,4 +2107,4 @@ declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
|
2052
2107
|
readonly name?: string;
|
|
2053
2108
|
}): TaggedErrorConstructor<Tag>;
|
|
2054
2109
|
//#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 };
|
|
2110
|
+
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
|
@@ -1287,6 +1287,72 @@ function fromPromise(promise, qualify, ..._guard) {
|
|
|
1287
1287
|
function fromSafePromise(promise) {
|
|
1288
1288
|
return new AsyncRes((typeof promise === "function" ? Promise.resolve().then(promise) : Promise.resolve(promise)).then((value) => okRes(value), (cause) => defectRes(cause)));
|
|
1289
1289
|
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Build an {@link AsyncResult} from a callback-style API — this library's
|
|
1292
|
+
* answer to `new Promise((resolve, reject) => …)`.
|
|
1293
|
+
*
|
|
1294
|
+
* @remarks
|
|
1295
|
+
* The settler takes a **`Result`**, not a value-or-reason pair: the caller names
|
|
1296
|
+
* the variant, so no `unknown` can enter `E` and there is no `qualify` to pass.
|
|
1297
|
+
* For a failure that is *not* modeled, settle the injected `defect` helper's
|
|
1298
|
+
* marker — the same injection `qualify` receives, and the only way to reach the
|
|
1299
|
+
* defect channel from inside an asynchronous callback (a `throw` there runs in
|
|
1300
|
+
* its own turn, long after the executor body returned).
|
|
1301
|
+
*
|
|
1302
|
+
* `T` and `E` cannot be inferred from the body, since `settle` is a parameter.
|
|
1303
|
+
* Supply them explicitly, or let them flow from an annotated target. Absent
|
|
1304
|
+
* either, both default to `never` (Thesis #3: no path may produce `unknown` in
|
|
1305
|
+
* `E`) — so an unannotated call is a compile error at the `settle(...)` call
|
|
1306
|
+
* site, not a silently-`unknown` channel.
|
|
1307
|
+
*
|
|
1308
|
+
* An executor that never settles yields an `AsyncResult` that never resolves —
|
|
1309
|
+
* the one hazard {@link fromPromise} does not have, and identical to
|
|
1310
|
+
* `new Promise`.
|
|
1311
|
+
*
|
|
1312
|
+
* @typeParam T - the success type.
|
|
1313
|
+
* @typeParam E - the modeled error type.
|
|
1314
|
+
* @param executor - runs immediately; receives the settler and the `defect` helper.
|
|
1315
|
+
*
|
|
1316
|
+
* @category Interop
|
|
1317
|
+
*
|
|
1318
|
+
* @example
|
|
1319
|
+
* ```ts
|
|
1320
|
+
* import { fromExecutor, Err, Ok } from "unthrown";
|
|
1321
|
+
*
|
|
1322
|
+
* const listen = (port: number) =>
|
|
1323
|
+
* fromExecutor<Server, PortInUse>((settle, defect) => {
|
|
1324
|
+
* server.once("error", (cause) =>
|
|
1325
|
+
* isAddrInUse(cause) ? settle(Err(new PortInUse(port))) : settle(defect(cause)),
|
|
1326
|
+
* );
|
|
1327
|
+
* server.listen(port, () => settle(Ok(server)));
|
|
1328
|
+
* });
|
|
1329
|
+
* ```
|
|
1330
|
+
*/
|
|
1331
|
+
function fromExecutor(executor) {
|
|
1332
|
+
let resolve;
|
|
1333
|
+
const promise = new Promise((r) => {
|
|
1334
|
+
resolve = r;
|
|
1335
|
+
});
|
|
1336
|
+
const settle = (result) => {
|
|
1337
|
+
if (isDefectMarker(result)) {
|
|
1338
|
+
resolve(defectRes(result.cause));
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
if (!isResult(result)) {
|
|
1342
|
+
if (isThenable(result)) Promise.resolve(result).then(void 0, () => void 0);
|
|
1343
|
+
resolve(defectRes(/* @__PURE__ */ new TypeError("unthrown: fromExecutor's settle received a non-Result value")));
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
resolve(result);
|
|
1347
|
+
};
|
|
1348
|
+
try {
|
|
1349
|
+
const returned = executor(settle, defect);
|
|
1350
|
+
if (isThenable(returned)) Promise.resolve(returned).then(void 0, (cause) => settle(defect(cause)));
|
|
1351
|
+
} catch (cause) {
|
|
1352
|
+
settle(defect(cause));
|
|
1353
|
+
}
|
|
1354
|
+
return new AsyncRes(promise);
|
|
1355
|
+
}
|
|
1290
1356
|
function qualifyToResult(cause, qualify) {
|
|
1291
1357
|
try {
|
|
1292
1358
|
const q = qualify(cause, defect);
|
|
@@ -1541,14 +1607,15 @@ const Result = {
|
|
|
1541
1607
|
/**
|
|
1542
1608
|
* Companion object grouping the **`AsyncResult`-producing** entry points under
|
|
1543
1609
|
* the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
|
|
1544
|
-
* {@link AsyncResult.Do}, {@link AsyncResult.
|
|
1545
|
-
* {@link AsyncResult.
|
|
1546
|
-
* {@link AsyncResult.allFromDict}.
|
|
1610
|
+
* {@link AsyncResult.Do}, {@link AsyncResult.fromExecutor},
|
|
1611
|
+
* {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
|
|
1612
|
+
* {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
|
|
1547
1613
|
*
|
|
1548
1614
|
* @remarks
|
|
1549
1615
|
* 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
|
|
1616
|
+
* **return**, so the pre-lifted constructors, `fromExecutor`,
|
|
1617
|
+
* `fromPromise`/`fromSafePromise`, and the async aggregates sit here rather
|
|
1618
|
+
* than on {@link Result}; the namespace
|
|
1552
1619
|
* already conveys "async", so the members drop the `Async` suffix their free
|
|
1553
1620
|
* functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
|
|
1554
1621
|
* `ErrAsync`; `AsyncResult.Do` is `DoAsync`; `AsyncResult.all` is `allAsync`;
|
|
@@ -1573,6 +1640,7 @@ const AsyncResult = {
|
|
|
1573
1640
|
Ok: OkAsync,
|
|
1574
1641
|
Err: ErrAsync,
|
|
1575
1642
|
Do: DoAsync,
|
|
1643
|
+
fromExecutor,
|
|
1576
1644
|
fromPromise,
|
|
1577
1645
|
fromSafePromise,
|
|
1578
1646
|
all: allAsync,
|
|
@@ -1669,4 +1737,4 @@ function TaggedError(tag, options) {
|
|
|
1669
1737
|
return TaggedErrorBase;
|
|
1670
1738
|
}
|
|
1671
1739
|
//#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 };
|
|
1740
|
+
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 };
|