@unthrown/boxed 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Benoit Travers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @unthrown/boxed
2
+
3
+ > [Boxed](https://boxed.cool) interop for
4
+ > [unthrown](https://github.com/btravstack/unthrown)'s `Result`.
5
+
6
+ ๐Ÿ“– **[Documentation](https://btravstack.github.io/unthrown/guide/interop)** ยท
7
+ [API Reference](https://btravstack.github.io/unthrown/api/boxed/)
8
+
9
+ ```sh
10
+ pnpm add @unthrown/boxed @bloodyowl/boxed
11
+ ```
12
+
13
+ Boxed's `Result` has two channels (`Ok`/`Error`) and no defect channel. Coming
14
+ **in**, every Boxed result is an `Ok` or `Error` โ€” never a `Defect`. Going
15
+ **out**, a `Defect` has nowhere to live, so `toBoxed` **forces** you to triage it
16
+ with `onDefect` โ€” no defect is ever silently folded into your domain error type.
17
+
18
+ ```ts
19
+ import { ok } from "unthrown";
20
+ import { toBoxed, fromBoxed } from "@unthrown/boxed";
21
+ import { Result } from "@bloodyowl/boxed";
22
+
23
+ toBoxed(ok(1), (cause) => ({ _tag: "Bug", cause })); // Result.Ok(1)
24
+ fromBoxed(Result.Ok(1)); // Result<number, never>
25
+ ```
26
+
27
+ - `toBoxed(r, onDefect)` / `fromBoxed(r)` โ€” sync `Result โ†” Result`.
28
+ - `toBoxedFuture(ar, onDefect)` / `fromBoxedFuture(future)` โ€” async
29
+ `AsyncResult โ†” Future<Result>`.
30
+
31
+ > Boxed's `Option` has no analogue here โ€” per unthrown's design, absence is
32
+ > expressed with `T | undefined` or `Result<T, NotFound>` (see `fromNullable`),
33
+ > not a dedicated `Option` type.
34
+
35
+ `@bloodyowl/boxed` is a peer dependency. (Boxed was formerly published as
36
+ `@swan-io/boxed`, now deprecated in favour of this maintained scope.)
37
+
38
+ ## License
39
+
40
+ [MIT](../../LICENSE) ยฉ Benoit TRAVERS
package/dist/index.cjs ADDED
@@ -0,0 +1,85 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _bloodyowl_boxed = require("@bloodyowl/boxed");
3
+ let unthrown = require("unthrown");
4
+ //#region src/index.ts
5
+ /**
6
+ * Convert a `Result` into a Boxed `Result`, triaging any defect.
7
+ *
8
+ * @remarks
9
+ * Boxed's `Result` has no defect channel, so `onDefect` **must** fold a
10
+ * `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,
11
+ * `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.
12
+ *
13
+ * @typeParam T - the success value type.
14
+ * @typeParam E - the modeled error type.
15
+ * @param result - the result to convert.
16
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
17
+ */
18
+ function toBoxed(result, onDefect) {
19
+ return result.match({
20
+ ok: (value) => _bloodyowl_boxed.Result.Ok(value),
21
+ err: (error) => _bloodyowl_boxed.Result.Error(error),
22
+ defect: (cause) => _bloodyowl_boxed.Result.Error(onDefect(cause))
23
+ });
24
+ }
25
+ /**
26
+ * Convert a Boxed `Result` into a `Result`.
27
+ *
28
+ * @remarks
29
+ * `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so
30
+ * the result is never a `Defect`.
31
+ *
32
+ * @typeParam T - the success value type.
33
+ * @typeParam E - the modeled error type.
34
+ * @param result - the Boxed result to convert.
35
+ */
36
+ function fromBoxed(result) {
37
+ return result.match({
38
+ Ok: (value) => (0, unthrown.ok)(value),
39
+ Error: (error) => (0, unthrown.err)(error)
40
+ });
41
+ }
42
+ /**
43
+ * Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any
44
+ * defect.
45
+ *
46
+ * @remarks
47
+ * The async counterpart of {@link toBoxed}: `onDefect` is required for the same
48
+ * reason. The `AsyncResult` is awaited (it never rejects) and its settled
49
+ * `Result` is converted, then resolved into the `Future`.
50
+ *
51
+ * @typeParam T - the success value type.
52
+ * @typeParam E - the modeled error type.
53
+ * @param asyncResult - the async result to convert.
54
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
55
+ */
56
+ function toBoxedFuture(asyncResult, onDefect) {
57
+ return _bloodyowl_boxed.Future.make((resolve) => {
58
+ settle(asyncResult).then((result) => {
59
+ resolve(toBoxed(result, onDefect));
60
+ });
61
+ });
62
+ }
63
+ /**
64
+ * Convert a Boxed `Future<Result>` into an `AsyncResult`.
65
+ *
66
+ * @remarks
67
+ * The async counterpart of {@link fromBoxed}. A `Result.Error` stays an `Err`;
68
+ * an *unexpected* rejection of the underlying promise becomes a `Defect`. The
69
+ * returned `AsyncResult` never throws when awaited.
70
+ *
71
+ * @typeParam T - the success value type.
72
+ * @typeParam E - the modeled error type.
73
+ * @param future - the Boxed future to convert.
74
+ */
75
+ function fromBoxedFuture(future) {
76
+ return (0, unthrown.fromSafePromise)(future.toPromise()).flatMap((result) => fromBoxed(result));
77
+ }
78
+ function settle(asyncResult) {
79
+ return (async () => await asyncResult)();
80
+ }
81
+ //#endregion
82
+ exports.fromBoxed = fromBoxed;
83
+ exports.fromBoxedFuture = fromBoxedFuture;
84
+ exports.toBoxed = toBoxed;
85
+ exports.toBoxedFuture = toBoxedFuture;
@@ -0,0 +1,61 @@
1
+ import { Future, Result } from "@bloodyowl/boxed";
2
+ import { AsyncResult, Result as Result$1 } from "unthrown";
3
+
4
+ //#region src/index.d.ts
5
+ /**
6
+ * Convert a `Result` into a Boxed `Result`, triaging any defect.
7
+ *
8
+ * @remarks
9
+ * Boxed's `Result` has no defect channel, so `onDefect` **must** fold a
10
+ * `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,
11
+ * `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.
12
+ *
13
+ * @typeParam T - the success value type.
14
+ * @typeParam E - the modeled error type.
15
+ * @param result - the result to convert.
16
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
17
+ */
18
+ declare function toBoxed<T, E>(result: Result$1<T, E>, onDefect: (cause: unknown) => E): Result<T, E>;
19
+ /**
20
+ * Convert a Boxed `Result` into a `Result`.
21
+ *
22
+ * @remarks
23
+ * `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so
24
+ * the result is never a `Defect`.
25
+ *
26
+ * @typeParam T - the success value type.
27
+ * @typeParam E - the modeled error type.
28
+ * @param result - the Boxed result to convert.
29
+ */
30
+ declare function fromBoxed<T, E>(result: Result<T, E>): Result$1<T, E>;
31
+ /**
32
+ * Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any
33
+ * defect.
34
+ *
35
+ * @remarks
36
+ * The async counterpart of {@link toBoxed}: `onDefect` is required for the same
37
+ * reason. The `AsyncResult` is awaited (it never rejects) and its settled
38
+ * `Result` is converted, then resolved into the `Future`.
39
+ *
40
+ * @typeParam T - the success value type.
41
+ * @typeParam E - the modeled error type.
42
+ * @param asyncResult - the async result to convert.
43
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
44
+ */
45
+ declare function toBoxedFuture<T, E>(asyncResult: AsyncResult<T, E>, onDefect: (cause: unknown) => E): Future<Result<T, E>>;
46
+ /**
47
+ * Convert a Boxed `Future<Result>` into an `AsyncResult`.
48
+ *
49
+ * @remarks
50
+ * The async counterpart of {@link fromBoxed}. A `Result.Error` stays an `Err`;
51
+ * an *unexpected* rejection of the underlying promise becomes a `Defect`. The
52
+ * returned `AsyncResult` never throws when awaited.
53
+ *
54
+ * @typeParam T - the success value type.
55
+ * @typeParam E - the modeled error type.
56
+ * @param future - the Boxed future to convert.
57
+ */
58
+ declare function fromBoxedFuture<T, E>(future: Future<Result<T, E>>): AsyncResult<T, E>;
59
+ //#endregion
60
+ export { fromBoxed, fromBoxedFuture, toBoxed, toBoxedFuture };
61
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;AAgCA;;;;;;;;;;;iBAAgB,OAAA,OACd,MAAA,EAAQ,QAAA,CAAO,CAAA,EAAG,CAAA,GAClB,QAAA,GAAW,KAAA,cAAmB,CAAA,GAC7B,MAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;;;;;;iBAmBF,SAAA,OAAgB,MAAA,EAAQ,MAAA,CAAY,CAAA,EAAG,CAAA,IAAK,QAAA,CAAO,CAAA,EAAG,CAAA;;AAnBnD;AAmBnB;;;;;;;;;;;;iBAqBgB,aAAA,OACd,WAAA,EAAa,WAAA,CAAY,CAAA,EAAG,CAAA,GAC5B,QAAA,GAAW,KAAA,cAAmB,CAAA,GAC7B,MAAA,CAAO,MAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;;;AAxB8C;AAqBvE;;;iBAuBgB,eAAA,OAAsB,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAY,CAAA,EAAG,CAAA,KAAM,WAAA,CAAY,CAAA,EAAG,CAAA"}
@@ -0,0 +1,61 @@
1
+ import { Future, Result } from "@bloodyowl/boxed";
2
+ import { AsyncResult, Result as Result$1 } from "unthrown";
3
+
4
+ //#region src/index.d.ts
5
+ /**
6
+ * Convert a `Result` into a Boxed `Result`, triaging any defect.
7
+ *
8
+ * @remarks
9
+ * Boxed's `Result` has no defect channel, so `onDefect` **must** fold a
10
+ * `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,
11
+ * `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.
12
+ *
13
+ * @typeParam T - the success value type.
14
+ * @typeParam E - the modeled error type.
15
+ * @param result - the result to convert.
16
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
17
+ */
18
+ declare function toBoxed<T, E>(result: Result$1<T, E>, onDefect: (cause: unknown) => E): Result<T, E>;
19
+ /**
20
+ * Convert a Boxed `Result` into a `Result`.
21
+ *
22
+ * @remarks
23
+ * `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so
24
+ * the result is never a `Defect`.
25
+ *
26
+ * @typeParam T - the success value type.
27
+ * @typeParam E - the modeled error type.
28
+ * @param result - the Boxed result to convert.
29
+ */
30
+ declare function fromBoxed<T, E>(result: Result<T, E>): Result$1<T, E>;
31
+ /**
32
+ * Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any
33
+ * defect.
34
+ *
35
+ * @remarks
36
+ * The async counterpart of {@link toBoxed}: `onDefect` is required for the same
37
+ * reason. The `AsyncResult` is awaited (it never rejects) and its settled
38
+ * `Result` is converted, then resolved into the `Future`.
39
+ *
40
+ * @typeParam T - the success value type.
41
+ * @typeParam E - the modeled error type.
42
+ * @param asyncResult - the async result to convert.
43
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
44
+ */
45
+ declare function toBoxedFuture<T, E>(asyncResult: AsyncResult<T, E>, onDefect: (cause: unknown) => E): Future<Result<T, E>>;
46
+ /**
47
+ * Convert a Boxed `Future<Result>` into an `AsyncResult`.
48
+ *
49
+ * @remarks
50
+ * The async counterpart of {@link fromBoxed}. A `Result.Error` stays an `Err`;
51
+ * an *unexpected* rejection of the underlying promise becomes a `Defect`. The
52
+ * returned `AsyncResult` never throws when awaited.
53
+ *
54
+ * @typeParam T - the success value type.
55
+ * @typeParam E - the modeled error type.
56
+ * @param future - the Boxed future to convert.
57
+ */
58
+ declare function fromBoxedFuture<T, E>(future: Future<Result<T, E>>): AsyncResult<T, E>;
59
+ //#endregion
60
+ export { fromBoxed, fromBoxedFuture, toBoxed, toBoxedFuture };
61
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;AAgCA;;;;;;;;;;;iBAAgB,OAAA,OACd,MAAA,EAAQ,QAAA,CAAO,CAAA,EAAG,CAAA,GAClB,QAAA,GAAW,KAAA,cAAmB,CAAA,GAC7B,MAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;;;;;;iBAmBF,SAAA,OAAgB,MAAA,EAAQ,MAAA,CAAY,CAAA,EAAG,CAAA,IAAK,QAAA,CAAO,CAAA,EAAG,CAAA;;AAnBnD;AAmBnB;;;;;;;;;;;;iBAqBgB,aAAA,OACd,WAAA,EAAa,WAAA,CAAY,CAAA,EAAG,CAAA,GAC5B,QAAA,GAAW,KAAA,cAAmB,CAAA,GAC7B,MAAA,CAAO,MAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;;;AAxB8C;AAqBvE;;;iBAuBgB,eAAA,OAAsB,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAY,CAAA,EAAG,CAAA,KAAM,WAAA,CAAY,CAAA,EAAG,CAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,83 @@
1
+ import { Future, Result } from "@bloodyowl/boxed";
2
+ import { err, fromSafePromise, ok } from "unthrown";
3
+ //#region src/index.ts
4
+ /**
5
+ * Convert a `Result` into a Boxed `Result`, triaging any defect.
6
+ *
7
+ * @remarks
8
+ * Boxed's `Result` has no defect channel, so `onDefect` **must** fold a
9
+ * `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,
10
+ * `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.
11
+ *
12
+ * @typeParam T - the success value type.
13
+ * @typeParam E - the modeled error type.
14
+ * @param result - the result to convert.
15
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
16
+ */
17
+ function toBoxed(result, onDefect) {
18
+ return result.match({
19
+ ok: (value) => Result.Ok(value),
20
+ err: (error) => Result.Error(error),
21
+ defect: (cause) => Result.Error(onDefect(cause))
22
+ });
23
+ }
24
+ /**
25
+ * Convert a Boxed `Result` into a `Result`.
26
+ *
27
+ * @remarks
28
+ * `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so
29
+ * the result is never a `Defect`.
30
+ *
31
+ * @typeParam T - the success value type.
32
+ * @typeParam E - the modeled error type.
33
+ * @param result - the Boxed result to convert.
34
+ */
35
+ function fromBoxed(result) {
36
+ return result.match({
37
+ Ok: (value) => ok(value),
38
+ Error: (error) => err(error)
39
+ });
40
+ }
41
+ /**
42
+ * Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any
43
+ * defect.
44
+ *
45
+ * @remarks
46
+ * The async counterpart of {@link toBoxed}: `onDefect` is required for the same
47
+ * reason. The `AsyncResult` is awaited (it never rejects) and its settled
48
+ * `Result` is converted, then resolved into the `Future`.
49
+ *
50
+ * @typeParam T - the success value type.
51
+ * @typeParam E - the modeled error type.
52
+ * @param asyncResult - the async result to convert.
53
+ * @param onDefect - folds a defect's unknown cause into a modeled `E`.
54
+ */
55
+ function toBoxedFuture(asyncResult, onDefect) {
56
+ return Future.make((resolve) => {
57
+ settle(asyncResult).then((result) => {
58
+ resolve(toBoxed(result, onDefect));
59
+ });
60
+ });
61
+ }
62
+ /**
63
+ * Convert a Boxed `Future<Result>` into an `AsyncResult`.
64
+ *
65
+ * @remarks
66
+ * The async counterpart of {@link fromBoxed}. A `Result.Error` stays an `Err`;
67
+ * an *unexpected* rejection of the underlying promise becomes a `Defect`. The
68
+ * returned `AsyncResult` never throws when awaited.
69
+ *
70
+ * @typeParam T - the success value type.
71
+ * @typeParam E - the modeled error type.
72
+ * @param future - the Boxed future to convert.
73
+ */
74
+ function fromBoxedFuture(future) {
75
+ return fromSafePromise(future.toPromise()).flatMap((result) => fromBoxed(result));
76
+ }
77
+ function settle(asyncResult) {
78
+ return (async () => await asyncResult)();
79
+ }
80
+ //#endregion
81
+ export { fromBoxed, fromBoxedFuture, toBoxed, toBoxedFuture };
82
+
83
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["BoxedResult"],"sources":["../src/index.ts"],"sourcesContent":["// @unthrown/boxed โ€” interop between unthrown's `Result`/`AsyncResult` and\n// Boxed's `Result`/`Future<Result>`.\n//\n// Boxed's `Result` has two channels (`Ok`/`Error`) and no defect channel.\n// Coming *in*, every Boxed result is an `Ok` or `Error` โ€” never a `Defect`.\n// Going *out*, a `Defect` has nowhere to live, so `toBoxed` forces you to triage\n// it with `onDefect` (Thesis #3): no defect is ever silently folded into your\n// domain error type.\n//\n// import { ok } from \"unthrown\";\n// import { toBoxed, fromBoxed } from \"@unthrown/boxed\";\n//\n// toBoxed(ok(1), (cause) => ({ _tag: \"Bug\", cause })); // Result.Ok(1)\n// fromBoxed(Result.Ok(1)); // Result<number, never>\n\nimport { Future, Result as BoxedResult } from \"@bloodyowl/boxed\";\nimport { err, fromSafePromise, ok } from \"unthrown\";\nimport type { AsyncResult, Result } from \"unthrown\";\n\n/**\n * Convert a `Result` into a Boxed `Result`, triaging any defect.\n *\n * @remarks\n * Boxed's `Result` has no defect channel, so `onDefect` **must** fold a\n * `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,\n * `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param result - the result to convert.\n * @param onDefect - folds a defect's unknown cause into a modeled `E`.\n */\nexport function toBoxed<T, E>(\n result: Result<T, E>,\n onDefect: (cause: unknown) => E,\n): BoxedResult<T, E> {\n return result.match<BoxedResult<T, E>>({\n ok: (value) => BoxedResult.Ok(value),\n err: (error) => BoxedResult.Error(error),\n defect: (cause) => BoxedResult.Error(onDefect(cause)),\n });\n}\n\n/**\n * Convert a Boxed `Result` into a `Result`.\n *\n * @remarks\n * `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so\n * the result is never a `Defect`.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param result - the Boxed result to convert.\n */\nexport function fromBoxed<T, E>(result: BoxedResult<T, E>): Result<T, E> {\n return result.match({\n Ok: (value) => ok(value),\n Error: (error) => err(error),\n });\n}\n\n/**\n * Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any\n * defect.\n *\n * @remarks\n * The async counterpart of {@link toBoxed}: `onDefect` is required for the same\n * reason. The `AsyncResult` is awaited (it never rejects) and its settled\n * `Result` is converted, then resolved into the `Future`.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param asyncResult - the async result to convert.\n * @param onDefect - folds a defect's unknown cause into a modeled `E`.\n */\nexport function toBoxedFuture<T, E>(\n asyncResult: AsyncResult<T, E>,\n onDefect: (cause: unknown) => E,\n): Future<BoxedResult<T, E>> {\n return Future.make<BoxedResult<T, E>>((resolve) => {\n void settle(asyncResult).then((result) => {\n resolve(toBoxed(result, onDefect));\n });\n });\n}\n\n/**\n * Convert a Boxed `Future<Result>` into an `AsyncResult`.\n *\n * @remarks\n * The async counterpart of {@link fromBoxed}. A `Result.Error` stays an `Err`;\n * an *unexpected* rejection of the underlying promise becomes a `Defect`. The\n * returned `AsyncResult` never throws when awaited.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param future - the Boxed future to convert.\n */\nexport function fromBoxedFuture<T, E>(future: Future<BoxedResult<T, E>>): AsyncResult<T, E> {\n return fromSafePromise(future.toPromise()).flatMap((result) => fromBoxed(result));\n}\n\nfunction settle<T, E>(asyncResult: AsyncResult<T, E>): Promise<Result<T, E>> {\n return (async () => await asyncResult)();\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,SAAgB,QACd,QACA,UACmB;CACnB,OAAO,OAAO,MAAyB;EACrC,KAAK,UAAUA,OAAY,GAAG,KAAK;EACnC,MAAM,UAAUA,OAAY,MAAM,KAAK;EACvC,SAAS,UAAUA,OAAY,MAAM,SAAS,KAAK,CAAC;CACtD,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,UAAgB,QAAyC;CACvE,OAAO,OAAO,MAAM;EAClB,KAAK,UAAU,GAAG,KAAK;EACvB,QAAQ,UAAU,IAAI,KAAK;CAC7B,CAAC;AACH;;;;;;;;;;;;;;;AAgBA,SAAgB,cACd,aACA,UAC2B;CAC3B,OAAO,OAAO,MAAyB,YAAY;EACjD,OAAY,WAAW,CAAC,CAAC,MAAM,WAAW;GACxC,QAAQ,QAAQ,QAAQ,QAAQ,CAAC;EACnC,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;;AAcA,SAAgB,gBAAsB,QAAsD;CAC1F,OAAO,gBAAgB,OAAO,UAAU,CAAC,CAAC,CAAC,SAAS,WAAW,UAAU,MAAM,CAAC;AAClF;AAEA,SAAS,OAAa,aAAuD;CAC3E,QAAQ,YAAY,MAAM,YAAA,CAAa;AACzC"}
package/docs/index.md ADDED
@@ -0,0 +1,147 @@
1
+ **@unthrown/boxed**
2
+
3
+ ***
4
+
5
+ # @unthrown/boxed
6
+
7
+ ## Functions
8
+
9
+ ### fromBoxed()
10
+
11
+ ```ts
12
+ function fromBoxed<T, E>(result): Result<T, E>;
13
+ ```
14
+
15
+ Defined in: index.ts:55
16
+
17
+ Convert a Boxed `Result` into a `Result`.
18
+
19
+ #### Type Parameters
20
+
21
+ | Type Parameter | Description |
22
+ | ------ | ------ |
23
+ | `T` | the success value type. |
24
+ | `E` | the modeled error type. |
25
+
26
+ #### Parameters
27
+
28
+ | Parameter | Type | Description |
29
+ | ------ | ------ | ------ |
30
+ | `result` | `Result`&lt;`T`, `E`&gt; | the Boxed result to convert. |
31
+
32
+ #### Returns
33
+
34
+ `Result`&lt;`T`, `E`&gt;
35
+
36
+ #### Remarks
37
+
38
+ `Result.Ok โ†’ Ok`, `Result.Error โ†’ Err`. Boxed's `Result` carries no defect, so
39
+ the result is never a `Defect`.
40
+
41
+ ***
42
+
43
+ ### fromBoxedFuture()
44
+
45
+ ```ts
46
+ function fromBoxedFuture<T, E>(future): AsyncResult<T, E>;
47
+ ```
48
+
49
+ Defined in: index.ts:99
50
+
51
+ Convert a Boxed `Future<Result>` into an `AsyncResult`.
52
+
53
+ #### Type Parameters
54
+
55
+ | Type Parameter | Description |
56
+ | ------ | ------ |
57
+ | `T` | the success value type. |
58
+ | `E` | the modeled error type. |
59
+
60
+ #### Parameters
61
+
62
+ | Parameter | Type | Description |
63
+ | ------ | ------ | ------ |
64
+ | `future` | `Future`&lt;`Result`&lt;`T`, `E`&gt;&gt; | the Boxed future to convert. |
65
+
66
+ #### Returns
67
+
68
+ `AsyncResult`&lt;`T`, `E`&gt;
69
+
70
+ #### Remarks
71
+
72
+ The async counterpart of [fromBoxed](#fromboxed). A `Result.Error` stays an `Err`;
73
+ an *unexpected* rejection of the underlying promise becomes a `Defect`. The
74
+ returned `AsyncResult` never throws when awaited.
75
+
76
+ ***
77
+
78
+ ### toBoxed()
79
+
80
+ ```ts
81
+ function toBoxed<T, E>(result, onDefect): Result<T, E>;
82
+ ```
83
+
84
+ Defined in: index.ts:33
85
+
86
+ Convert a `Result` into a Boxed `Result`, triaging any defect.
87
+
88
+ #### Type Parameters
89
+
90
+ | Type Parameter | Description |
91
+ | ------ | ------ |
92
+ | `T` | the success value type. |
93
+ | `E` | the modeled error type. |
94
+
95
+ #### Parameters
96
+
97
+ | Parameter | Type | Description |
98
+ | ------ | ------ | ------ |
99
+ | `result` | `Result`&lt;`T`, `E`&gt; | the result to convert. |
100
+ | `onDefect` | (`cause`) => `E` | folds a defect's unknown cause into a modeled `E`. |
101
+
102
+ #### Returns
103
+
104
+ `Result`&lt;`T`, `E`&gt;
105
+
106
+ #### Remarks
107
+
108
+ Boxed's `Result` has no defect channel, so `onDefect` **must** fold a
109
+ `Defect`'s cause into a modeled error `E` (an `Error`). `Ok โ†’ Result.Ok`,
110
+ `Err โ†’ Result.Error`, `Defect โ†’ Result.Error(onDefect(cause))`.
111
+
112
+ ***
113
+
114
+ ### toBoxedFuture()
115
+
116
+ ```ts
117
+ function toBoxedFuture<T, E>(asyncResult, onDefect): Future<Result<T, E>>;
118
+ ```
119
+
120
+ Defined in: index.ts:76
121
+
122
+ Convert an `AsyncResult` into a Boxed `Future<Result>`, triaging any
123
+ defect.
124
+
125
+ #### Type Parameters
126
+
127
+ | Type Parameter | Description |
128
+ | ------ | ------ |
129
+ | `T` | the success value type. |
130
+ | `E` | the modeled error type. |
131
+
132
+ #### Parameters
133
+
134
+ | Parameter | Type | Description |
135
+ | ------ | ------ | ------ |
136
+ | `asyncResult` | `AsyncResult`&lt;`T`, `E`&gt; | the async result to convert. |
137
+ | `onDefect` | (`cause`) => `E` | folds a defect's unknown cause into a modeled `E`. |
138
+
139
+ #### Returns
140
+
141
+ `Future`&lt;`Result`&lt;`T`, `E`&gt;&gt;
142
+
143
+ #### Remarks
144
+
145
+ The async counterpart of [toBoxed](#toboxed): `onDefect` is required for the same
146
+ reason. The `AsyncResult` is awaited (it never rejects) and its settled
147
+ `Result` is converted, then resolved into the `Future`.
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@unthrown/boxed",
3
+ "version": "0.1.0",
4
+ "description": "Boxed interop for unthrown",
5
+ "keywords": [
6
+ "boxed",
7
+ "errors-as-values",
8
+ "future",
9
+ "result",
10
+ "swan-io",
11
+ "typescript",
12
+ "unthrown"
13
+ ],
14
+ "homepage": "https://github.com/btravstack/unthrown#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/btravstack/unthrown/issues"
17
+ },
18
+ "license": "MIT",
19
+ "author": "Benoit TRAVERS <benoit.travers.fr@gmail.com>",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/btravstack/unthrown.git",
23
+ "directory": "packages/boxed"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "docs"
28
+ ],
29
+ "type": "module",
30
+ "main": "./dist/index.cjs",
31
+ "module": "./dist/index.mjs",
32
+ "types": "./dist/index.d.mts",
33
+ "exports": {
34
+ ".": {
35
+ "import": {
36
+ "types": "./dist/index.d.mts",
37
+ "default": "./dist/index.mjs"
38
+ },
39
+ "require": {
40
+ "types": "./dist/index.d.cts",
41
+ "default": "./dist/index.cjs"
42
+ }
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "dependencies": {
47
+ "unthrown": "0.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@bloodyowl/boxed": "3.4.0",
51
+ "@types/node": "24.13.2",
52
+ "@vitest/coverage-v8": "4.1.8",
53
+ "tsdown": "0.22.2",
54
+ "typedoc": "0.28.19",
55
+ "typedoc-plugin-markdown": "4.12.0",
56
+ "typescript": "6.0.3",
57
+ "vitest": "4.1.8",
58
+ "@unthrown/typedoc": "0.1.0",
59
+ "@unthrown/tsconfig": "0.1.0"
60
+ },
61
+ "peerDependencies": {
62
+ "@bloodyowl/boxed": "^3"
63
+ },
64
+ "engines": {
65
+ "node": ">=22.19"
66
+ },
67
+ "scripts": {
68
+ "build": "tsdown src/index.ts --format cjs,esm --dts --clean",
69
+ "build:docs": "typedoc",
70
+ "dev": "tsdown src/index.ts --format cjs,esm --dts --watch",
71
+ "test": "vitest run",
72
+ "typecheck": "tsc --noEmit"
73
+ }
74
+ }