@unthrown/effect 0.2.0 → 1.0.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/README.md CHANGED
@@ -16,12 +16,12 @@ failure (`Cause.fail` ↔ `Err`) from an unexpected one (`Cause.die` ↔ `Defect
16
16
  So `Result ↔ Exit` is a genuine **bijection**.
17
17
 
18
18
  ```ts
19
- import { ok, err } from "unthrown";
19
+ import { Ok, Err } from "unthrown";
20
20
  import { toExit, fromEffect, toEither } from "@unthrown/effect";
21
21
  import { Effect } from "effect";
22
22
 
23
- toExit(ok(1)); // Exit.succeed(1)
24
- toExit(err("e")); // Exit.fail("e") — a modeled Cause.fail
23
+ toExit(Ok(1)); // Exit.succeed(1)
24
+ toExit(Err("e")); // Exit.fail("e") — a modeled Cause.fail
25
25
 
26
26
  // Run an Effect and collect its outcome (die/interrupt become a Defect):
27
27
  await fromEffect(Effect.succeed(1)).match({ ok, err, defect: String });
package/dist/index.cjs CHANGED
@@ -17,9 +17,9 @@ let unthrown = require("unthrown");
17
17
  *
18
18
  * @example
19
19
  * ```ts
20
- * import { ok } from "unthrown";
20
+ * import { Ok } from "unthrown";
21
21
  * import { toExit } from "@unthrown/effect";
22
- * toExit(ok(1)); // Exit.succeed(1)
22
+ * toExit(Ok(1)); // Exit.succeed(1)
23
23
  * ```
24
24
  */
25
25
  function toExit(result) {
@@ -50,21 +50,21 @@ function toExit(result) {
50
50
  */
51
51
  function fromExit(exit) {
52
52
  return effect.Exit.match(exit, {
53
- onSuccess: (value) => (0, unthrown.ok)(value),
53
+ onSuccess: (value) => (0, unthrown.Ok)(value),
54
54
  onFailure: (cause) => {
55
55
  const die = effect.Cause.dieOption(cause);
56
56
  if (effect.Option.isSome(die)) return dieToResult(die.value);
57
57
  const failure = effect.Cause.failureOption(cause);
58
- if (effect.Option.isSome(failure)) return (0, unthrown.err)(failure.value);
58
+ if (effect.Option.isSome(failure)) return (0, unthrown.Err)(failure.value);
59
59
  return dieToResult(effect.Cause.squash(cause));
60
60
  }
61
61
  });
62
62
  }
63
63
  /**
64
- * Convert a `Result` into an Effect `Either`, triaging any defect.
64
+ * Convert a `Result` into an Effect `Either`, triaging any Defect.
65
65
  *
66
66
  * @remarks
67
- * `Either` has no defect channel, so a `Defect` cannot pass through silently —
67
+ * `Either` has no Defect channel, so a `Defect` cannot pass through silently —
68
68
  * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This
69
69
  * is the boundary-qualification rule (Thesis #3) applied on the way out:
70
70
  * `Ok → Right`, `Err → Left`, `Defect → Left(onDefect(cause))`.
@@ -72,7 +72,7 @@ function fromExit(exit) {
72
72
  * @typeParam T - the success value type.
73
73
  * @typeParam E - the modeled error type.
74
74
  * @param result - the result to convert.
75
- * @param onDefect - folds a defect's unknown cause into a modeled `E`.
75
+ * @param onDefect - folds a Defect's unknown cause into a modeled `E`.
76
76
  */
77
77
  function toEither(result, onDefect) {
78
78
  return result.match({
@@ -85,7 +85,7 @@ function toEither(result, onDefect) {
85
85
  * Convert an Effect `Either` into a `Result`.
86
86
  *
87
87
  * @remarks
88
- * `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is
88
+ * `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is
89
89
  * never a `Defect`.
90
90
  *
91
91
  * @typeParam T - the success value type.
@@ -94,8 +94,8 @@ function toEither(result, onDefect) {
94
94
  */
95
95
  function fromEither(either) {
96
96
  return effect.Either.match(either, {
97
- onLeft: (error) => (0, unthrown.err)(error),
98
- onRight: (value) => (0, unthrown.ok)(value)
97
+ onLeft: (error) => (0, unthrown.Err)(error),
98
+ onRight: (value) => (0, unthrown.Ok)(value)
99
99
  });
100
100
  }
101
101
  function toEffect(source) {
@@ -128,7 +128,7 @@ function resultToEffect(result) {
128
128
  function dieToResult(cause) {
129
129
  return (0, unthrown.fromThrowable)(() => {
130
130
  throw cause;
131
- }, unthrown.defect)();
131
+ }, unthrown.Defect)();
132
132
  }
133
133
  function settle(asyncResult) {
134
134
  return (async () => await asyncResult)();
package/dist/index.d.cts CHANGED
@@ -17,9 +17,9 @@ import { AsyncResult, Result } from "unthrown";
17
17
  *
18
18
  * @example
19
19
  * ```ts
20
- * import { ok } from "unthrown";
20
+ * import { Ok } from "unthrown";
21
21
  * import { toExit } from "@unthrown/effect";
22
- * toExit(ok(1)); // Exit.succeed(1)
22
+ * toExit(Ok(1)); // Exit.succeed(1)
23
23
  * ```
24
24
  */
25
25
  declare function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E>;
@@ -44,10 +44,10 @@ declare function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E>;
44
44
  */
45
45
  declare function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E>;
46
46
  /**
47
- * Convert a `Result` into an Effect `Either`, triaging any defect.
47
+ * Convert a `Result` into an Effect `Either`, triaging any Defect.
48
48
  *
49
49
  * @remarks
50
- * `Either` has no defect channel, so a `Defect` cannot pass through silently —
50
+ * `Either` has no Defect channel, so a `Defect` cannot pass through silently —
51
51
  * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This
52
52
  * is the boundary-qualification rule (Thesis #3) applied on the way out:
53
53
  * `Ok → Right`, `Err → Left`, `Defect → Left(onDefect(cause))`.
@@ -55,14 +55,14 @@ declare function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E>;
55
55
  * @typeParam T - the success value type.
56
56
  * @typeParam E - the modeled error type.
57
57
  * @param result - the result to convert.
58
- * @param onDefect - folds a defect's unknown cause into a modeled `E`.
58
+ * @param onDefect - folds a Defect's unknown cause into a modeled `E`.
59
59
  */
60
60
  declare function toEither<T, E>(result: Result<T, E>, onDefect: (cause: unknown) => E): Either.Either<T, E>;
61
61
  /**
62
62
  * Convert an Effect `Either` into a `Result`.
63
63
  *
64
64
  * @remarks
65
- * `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is
65
+ * `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is
66
66
  * never a `Defect`.
67
67
  *
68
68
  * @typeParam T - the success value type.
package/dist/index.d.mts CHANGED
@@ -17,9 +17,9 @@ import { AsyncResult, Result } from "unthrown";
17
17
  *
18
18
  * @example
19
19
  * ```ts
20
- * import { ok } from "unthrown";
20
+ * import { Ok } from "unthrown";
21
21
  * import { toExit } from "@unthrown/effect";
22
- * toExit(ok(1)); // Exit.succeed(1)
22
+ * toExit(Ok(1)); // Exit.succeed(1)
23
23
  * ```
24
24
  */
25
25
  declare function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E>;
@@ -44,10 +44,10 @@ declare function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E>;
44
44
  */
45
45
  declare function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E>;
46
46
  /**
47
- * Convert a `Result` into an Effect `Either`, triaging any defect.
47
+ * Convert a `Result` into an Effect `Either`, triaging any Defect.
48
48
  *
49
49
  * @remarks
50
- * `Either` has no defect channel, so a `Defect` cannot pass through silently —
50
+ * `Either` has no Defect channel, so a `Defect` cannot pass through silently —
51
51
  * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This
52
52
  * is the boundary-qualification rule (Thesis #3) applied on the way out:
53
53
  * `Ok → Right`, `Err → Left`, `Defect → Left(onDefect(cause))`.
@@ -55,14 +55,14 @@ declare function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E>;
55
55
  * @typeParam T - the success value type.
56
56
  * @typeParam E - the modeled error type.
57
57
  * @param result - the result to convert.
58
- * @param onDefect - folds a defect's unknown cause into a modeled `E`.
58
+ * @param onDefect - folds a Defect's unknown cause into a modeled `E`.
59
59
  */
60
60
  declare function toEither<T, E>(result: Result<T, E>, onDefect: (cause: unknown) => E): Either.Either<T, E>;
61
61
  /**
62
62
  * Convert an Effect `Either` into a `Result`.
63
63
  *
64
64
  * @remarks
65
- * `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is
65
+ * `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is
66
66
  * never a `Defect`.
67
67
  *
68
68
  * @typeParam T - the success value type.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Cause, Effect, Either, Exit, Option } from "effect";
2
- import { defect, err, fromSafePromise, fromThrowable, ok } from "unthrown";
2
+ import { Defect, Err, Ok, fromSafePromise, fromThrowable } from "unthrown";
3
3
  //#region src/index.ts
4
4
  /**
5
5
  * Convert a `Result` into an Effect `Exit` — a **bijection**, since both
@@ -16,9 +16,9 @@ import { defect, err, fromSafePromise, fromThrowable, ok } from "unthrown";
16
16
  *
17
17
  * @example
18
18
  * ```ts
19
- * import { ok } from "unthrown";
19
+ * import { Ok } from "unthrown";
20
20
  * import { toExit } from "@unthrown/effect";
21
- * toExit(ok(1)); // Exit.succeed(1)
21
+ * toExit(Ok(1)); // Exit.succeed(1)
22
22
  * ```
23
23
  */
24
24
  function toExit(result) {
@@ -49,21 +49,21 @@ function toExit(result) {
49
49
  */
50
50
  function fromExit(exit) {
51
51
  return Exit.match(exit, {
52
- onSuccess: (value) => ok(value),
52
+ onSuccess: (value) => Ok(value),
53
53
  onFailure: (cause) => {
54
54
  const die = Cause.dieOption(cause);
55
55
  if (Option.isSome(die)) return dieToResult(die.value);
56
56
  const failure = Cause.failureOption(cause);
57
- if (Option.isSome(failure)) return err(failure.value);
57
+ if (Option.isSome(failure)) return Err(failure.value);
58
58
  return dieToResult(Cause.squash(cause));
59
59
  }
60
60
  });
61
61
  }
62
62
  /**
63
- * Convert a `Result` into an Effect `Either`, triaging any defect.
63
+ * Convert a `Result` into an Effect `Either`, triaging any Defect.
64
64
  *
65
65
  * @remarks
66
- * `Either` has no defect channel, so a `Defect` cannot pass through silently —
66
+ * `Either` has no Defect channel, so a `Defect` cannot pass through silently —
67
67
  * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This
68
68
  * is the boundary-qualification rule (Thesis #3) applied on the way out:
69
69
  * `Ok → Right`, `Err → Left`, `Defect → Left(onDefect(cause))`.
@@ -71,7 +71,7 @@ function fromExit(exit) {
71
71
  * @typeParam T - the success value type.
72
72
  * @typeParam E - the modeled error type.
73
73
  * @param result - the result to convert.
74
- * @param onDefect - folds a defect's unknown cause into a modeled `E`.
74
+ * @param onDefect - folds a Defect's unknown cause into a modeled `E`.
75
75
  */
76
76
  function toEither(result, onDefect) {
77
77
  return result.match({
@@ -84,7 +84,7 @@ function toEither(result, onDefect) {
84
84
  * Convert an Effect `Either` into a `Result`.
85
85
  *
86
86
  * @remarks
87
- * `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is
87
+ * `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is
88
88
  * never a `Defect`.
89
89
  *
90
90
  * @typeParam T - the success value type.
@@ -93,8 +93,8 @@ function toEither(result, onDefect) {
93
93
  */
94
94
  function fromEither(either) {
95
95
  return Either.match(either, {
96
- onLeft: (error) => err(error),
97
- onRight: (value) => ok(value)
96
+ onLeft: (error) => Err(error),
97
+ onRight: (value) => Ok(value)
98
98
  });
99
99
  }
100
100
  function toEffect(source) {
@@ -127,7 +127,7 @@ function resultToEffect(result) {
127
127
  function dieToResult(cause) {
128
128
  return fromThrowable(() => {
129
129
  throw cause;
130
- }, defect)();
130
+ }, Defect)();
131
131
  }
132
132
  function settle(asyncResult) {
133
133
  return (async () => await asyncResult)();
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["// @unthrown/effect — interop between unthrown's `Result`/`AsyncResult` and\n// Effect's `Exit`, `Either`, and `Effect`.\n//\n// Effect is the one neighbour that shares unthrown's three-channel shape: an\n// `Exit<A, E>` is `Success` | `Failure(Cause)`, and a `Cause` distinguishes a\n// modeled failure (`Cause.fail`, ↔ `Err`) from an unexpected one (`Cause.die`,\n// ↔ `Defect`). So `Result ↔ Exit` is a genuine bijection — the showcase here.\n//\n// import { ok } from \"unthrown\";\n// import { toExit, fromEffect } from \"@unthrown/effect\";\n//\n// toExit(ok(1)); // Exit.succeed(1)\n// await fromEffect(Effect.succeed(1)).match({ ok, err, defect });\n//\n// `Either` has only two channels, so converting a `Result` *into* an `Either`\n// forces you to triage the defect with `onDefect` (Thesis #3): there is no\n// silent path that drops it.\n\nimport { Cause, Effect, Either, Exit, Option } from \"effect\";\nimport { defect, err, fromSafePromise, fromThrowable, ok } from \"unthrown\";\nimport type { AsyncResult, Result } from \"unthrown\";\n\n/**\n * Convert a `Result` into an Effect `Exit` — a **bijection**, since both\n * carry three channels.\n *\n * @remarks\n * `Ok → Exit.succeed`, `Err → Exit.fail` (a modeled `Cause.fail`), and\n * `Defect → Exit.die` (an unexpected `Cause.die`). Round-trips with\n * {@link fromExit}.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param result - the result to convert.\n *\n * @example\n * ```ts\n * import { ok } from \"unthrown\";\n * import { toExit } from \"@unthrown/effect\";\n * toExit(ok(1)); // Exit.succeed(1)\n * ```\n */\nexport function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E> {\n return result.match<Exit.Exit<T, E>>({\n ok: (value) => Exit.succeed(value),\n err: (error) => Exit.fail(error),\n defect: (cause) => Exit.die(cause),\n });\n}\n\n/**\n * Convert an Effect `Exit` into a `Result` — the inverse of\n * {@link toExit}.\n *\n * @remarks\n * `Exit.Success → Ok`. For a failure, the enclosing `Cause` is reduced:\n *\n * - a `Cause.die` becomes a `Defect`,\n * - otherwise a `Cause.fail` becomes the modeled `Err`,\n * - a pure interruption (or empty cause) becomes a `Defect`.\n *\n * A `Defect` **dominates** a modeled failure in a composite cause — the same\n * rule unthrown's `all` uses, on the principle that an unexpected failure is the\n * more severe signal.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param exit - the exit to convert.\n */\nexport function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E> {\n return Exit.match(exit, {\n onSuccess: (value) => ok(value),\n onFailure: (cause) => {\n const die = Cause.dieOption(cause);\n if (Option.isSome(die)) return dieToResult<T, E>(die.value);\n const failure = Cause.failureOption(cause);\n if (Option.isSome(failure)) return err(failure.value);\n // No modeled failure and no die: a pure interruption (or empty cause).\n return dieToResult<T, E>(Cause.squash(cause));\n },\n });\n}\n\n/**\n * Convert a `Result` into an Effect `Either`, triaging any defect.\n *\n * @remarks\n * `Either` has no defect channel, so a `Defect` cannot pass through silently —\n * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This\n * is the boundary-qualification rule (Thesis #3) applied on the way out:\n * `Ok → Right`, `Err → Left`, `Defect → Left(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 toEither<T, E>(\n result: Result<T, E>,\n onDefect: (cause: unknown) => E,\n): Either.Either<T, E> {\n return result.match<Either.Either<T, E>>({\n ok: (value) => Either.right(value),\n err: (error) => Either.left(error),\n defect: (cause) => Either.left(onDefect(cause)),\n });\n}\n\n/**\n * Convert an Effect `Either` into a `Result`.\n *\n * @remarks\n * `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is\n * never a `Defect`.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param either - the either to convert.\n */\nexport function fromEither<T, E>(either: Either.Either<T, E>): Result<T, E> {\n return Either.match(either, {\n onLeft: (error) => err(error),\n onRight: (value) => ok(value),\n });\n}\n\n/**\n * Lift a `Result` or `AsyncResult` into an `Effect`.\n *\n * @remarks\n * `Ok → Effect.succeed`, `Err → Effect.fail`, `Defect → Effect.die`. The\n * resulting `Effect` needs no environment (`R = never`). An `AsyncResult` is\n * awaited inside the effect (it never rejects), so this is the `AsyncResult →\n * Effect` direction too.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param source - the result, or async result, to lift.\n */\nexport function toEffect<T, E>(source: Result<T, E>): Effect.Effect<T, E>;\nexport function toEffect<T, E>(source: AsyncResult<T, E>): Effect.Effect<T, E>;\nexport function toEffect<T, E>(source: Result<T, E> | AsyncResult<T, E>): Effect.Effect<T, E> {\n if (isAsyncResult(source)) {\n return Effect.flatMap(\n Effect.promise(() => settle(source)),\n (result) => resultToEffect(result),\n );\n }\n return resultToEffect(source);\n}\n\n/**\n * Run an `Effect` and collect its outcome as an `AsyncResult`.\n *\n * @remarks\n * The effect must need no environment (`R = never`). It is run to an `Exit`\n * (which never rejects), then folded with {@link fromExit}: success → `Ok`, a\n * modeled failure → `Err`, a die/interruption → `Defect`. The returned\n * `AsyncResult` never throws when awaited.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param effect - the effect to run.\n */\nexport function fromEffect<T, E>(effect: Effect.Effect<T, E>): AsyncResult<T, E> {\n return fromSafePromise(Effect.runPromiseExit(effect)).flatMap((exit) => fromExit(exit));\n}\n\nfunction resultToEffect<T, E>(result: Result<T, E>): Effect.Effect<T, E> {\n return result.match<Effect.Effect<T, E>>({\n ok: (value) => Effect.succeed(value),\n err: (error) => Effect.fail(error),\n defect: (cause) => Effect.die(cause),\n });\n}\n\n// Effect's `die`/interruption channel is an un-triaged failure crossing into\n// unthrown; replaying it through the throwable boundary lands it in the `Defect`\n// state — the sanctioned (boundary-only) way to mint a defect `Result`.\nfunction dieToResult<T, E>(cause: unknown): Result<T, E> {\n // The thunk always throws, so its `T` return is honest; `qualify` is `defect`,\n // so the modeled error is `never` — widened to `E` here (there is no `Err`).\n return fromThrowable((): T => {\n throw cause;\n }, defect)() as Result<T, E>;\n}\n\nfunction settle<T, E>(asyncResult: AsyncResult<T, E>): Promise<Result<T, E>> {\n return (async () => await asyncResult)();\n}\n\nfunction isAsyncResult<T, E>(\n source: Result<T, E> | AsyncResult<T, E>,\n): source is AsyncResult<T, E> {\n return typeof (source as { then?: unknown }).then === \"function\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,OAAa,QAAuC;CAClE,OAAO,OAAO,MAAuB;EACnC,KAAK,UAAU,KAAK,QAAQ,KAAK;EACjC,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,SAAS,UAAU,KAAK,IAAI,KAAK;CACnC,CAAC;AACH;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,SAAe,MAAqC;CAClE,OAAO,KAAK,MAAM,MAAM;EACtB,YAAY,UAAU,GAAG,KAAK;EAC9B,YAAY,UAAU;GACpB,MAAM,MAAM,MAAM,UAAU,KAAK;GACjC,IAAI,OAAO,OAAO,GAAG,GAAG,OAAO,YAAkB,IAAI,KAAK;GAC1D,MAAM,UAAU,MAAM,cAAc,KAAK;GACzC,IAAI,OAAO,OAAO,OAAO,GAAG,OAAO,IAAI,QAAQ,KAAK;GAEpD,OAAO,YAAkB,MAAM,OAAO,KAAK,CAAC;EAC9C;CACF,CAAC;AACH;;;;;;;;;;;;;;;AAgBA,SAAgB,SACd,QACA,UACqB;CACrB,OAAO,OAAO,MAA2B;EACvC,KAAK,UAAU,OAAO,MAAM,KAAK;EACjC,MAAM,UAAU,OAAO,KAAK,KAAK;EACjC,SAAS,UAAU,OAAO,KAAK,SAAS,KAAK,CAAC;CAChD,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,WAAiB,QAA2C;CAC1E,OAAO,OAAO,MAAM,QAAQ;EAC1B,SAAS,UAAU,IAAI,KAAK;EAC5B,UAAU,UAAU,GAAG,KAAK;CAC9B,CAAC;AACH;AAiBA,SAAgB,SAAe,QAA+D;CAC5F,IAAI,cAAc,MAAM,GACtB,OAAO,OAAO,QACZ,OAAO,cAAc,OAAO,MAAM,CAAC,IAClC,WAAW,eAAe,MAAM,CACnC;CAEF,OAAO,eAAe,MAAM;AAC9B;;;;;;;;;;;;;;AAeA,SAAgB,WAAiB,QAAgD;CAC/E,OAAO,gBAAgB,OAAO,eAAe,MAAM,CAAC,CAAC,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC;AACxF;AAEA,SAAS,eAAqB,QAA2C;CACvE,OAAO,OAAO,MAA2B;EACvC,KAAK,UAAU,OAAO,QAAQ,KAAK;EACnC,MAAM,UAAU,OAAO,KAAK,KAAK;EACjC,SAAS,UAAU,OAAO,IAAI,KAAK;CACrC,CAAC;AACH;AAKA,SAAS,YAAkB,OAA8B;CAGvD,OAAO,oBAAuB;EAC5B,MAAM;CACR,GAAG,MAAM,CAAC,CAAC;AACb;AAEA,SAAS,OAAa,aAAuD;CAC3E,QAAQ,YAAY,MAAM,YAAA,CAAa;AACzC;AAEA,SAAS,cACP,QAC6B;CAC7B,OAAO,OAAQ,OAA8B,SAAS;AACxD"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["// @unthrown/effect — interop between unthrown's `Result`/`AsyncResult` and\n// Effect's `Exit`, `Either`, and `Effect`.\n//\n// Effect is the one neighbour that shares unthrown's three-channel shape: an\n// `Exit<A, E>` is `Success` | `Failure(Cause)`, and a `Cause` distinguishes a\n// modeled failure (`Cause.fail`, ↔ `Err`) from an unexpected one (`Cause.die`,\n// ↔ `Defect`). So `Result ↔ Exit` is a genuine bijection — the showcase here.\n//\n// import { Ok } from \"unthrown\";\n// import { toExit, fromEffect } from \"@unthrown/effect\";\n//\n// toExit(Ok(1)); // Exit.succeed(1)\n// await fromEffect(Effect.succeed(1)).match({ ok, err, defect });\n//\n// `Either` has only two channels, so converting a `Result` *into* an `Either`\n// forces you to triage the Defect with `onDefect` (Thesis #3): there is no\n// silent path that drops it.\n\nimport { Cause, Effect, Either, Exit, Option } from \"effect\";\nimport { Defect, Err, fromSafePromise, fromThrowable, Ok } from \"unthrown\";\nimport type { AsyncResult, Result } from \"unthrown\";\n\n/**\n * Convert a `Result` into an Effect `Exit` — a **bijection**, since both\n * carry three channels.\n *\n * @remarks\n * `Ok → Exit.succeed`, `Err → Exit.fail` (a modeled `Cause.fail`), and\n * `Defect → Exit.die` (an unexpected `Cause.die`). Round-trips with\n * {@link fromExit}.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param result - the result to convert.\n *\n * @example\n * ```ts\n * import { Ok } from \"unthrown\";\n * import { toExit } from \"@unthrown/effect\";\n * toExit(Ok(1)); // Exit.succeed(1)\n * ```\n */\nexport function toExit<T, E>(result: Result<T, E>): Exit.Exit<T, E> {\n return result.match<Exit.Exit<T, E>>({\n ok: (value) => Exit.succeed(value),\n err: (error) => Exit.fail(error),\n defect: (cause) => Exit.die(cause),\n });\n}\n\n/**\n * Convert an Effect `Exit` into a `Result` — the inverse of\n * {@link toExit}.\n *\n * @remarks\n * `Exit.Success → Ok`. For a failure, the enclosing `Cause` is reduced:\n *\n * - a `Cause.die` becomes a `Defect`,\n * - otherwise a `Cause.fail` becomes the modeled `Err`,\n * - a pure interruption (or empty cause) becomes a `Defect`.\n *\n * A `Defect` **dominates** a modeled failure in a composite cause — the same\n * rule unthrown's `all` uses, on the principle that an unexpected failure is the\n * more severe signal.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param exit - the exit to convert.\n */\nexport function fromExit<T, E>(exit: Exit.Exit<T, E>): Result<T, E> {\n return Exit.match(exit, {\n onSuccess: (value) => Ok(value),\n onFailure: (cause) => {\n const die = Cause.dieOption(cause);\n if (Option.isSome(die)) return dieToResult<T, E>(die.value);\n const failure = Cause.failureOption(cause);\n if (Option.isSome(failure)) return Err(failure.value);\n // No modeled failure and no die: a pure interruption (or empty cause).\n return dieToResult<T, E>(Cause.squash(cause));\n },\n });\n}\n\n/**\n * Convert a `Result` into an Effect `Either`, triaging any Defect.\n *\n * @remarks\n * `Either` has no Defect channel, so a `Defect` cannot pass through silently —\n * `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This\n * is the boundary-qualification rule (Thesis #3) applied on the way out:\n * `Ok → Right`, `Err → Left`, `Defect → Left(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 toEither<T, E>(\n result: Result<T, E>,\n onDefect: (cause: unknown) => E,\n): Either.Either<T, E> {\n return result.match<Either.Either<T, E>>({\n ok: (value) => Either.right(value),\n err: (error) => Either.left(error),\n defect: (cause) => Either.left(onDefect(cause)),\n });\n}\n\n/**\n * Convert an Effect `Either` into a `Result`.\n *\n * @remarks\n * `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is\n * never a `Defect`.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param either - the either to convert.\n */\nexport function fromEither<T, E>(either: Either.Either<T, E>): Result<T, E> {\n return Either.match(either, {\n onLeft: (error) => Err(error),\n onRight: (value) => Ok(value),\n });\n}\n\n/**\n * Lift a `Result` or `AsyncResult` into an `Effect`.\n *\n * @remarks\n * `Ok → Effect.succeed`, `Err → Effect.fail`, `Defect → Effect.die`. The\n * resulting `Effect` needs no environment (`R = never`). An `AsyncResult` is\n * awaited inside the effect (it never rejects), so this is the `AsyncResult →\n * Effect` direction too.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param source - the result, or async result, to lift.\n */\nexport function toEffect<T, E>(source: Result<T, E>): Effect.Effect<T, E>;\nexport function toEffect<T, E>(source: AsyncResult<T, E>): Effect.Effect<T, E>;\nexport function toEffect<T, E>(source: Result<T, E> | AsyncResult<T, E>): Effect.Effect<T, E> {\n if (isAsyncResult(source)) {\n return Effect.flatMap(\n Effect.promise(() => settle(source)),\n (result) => resultToEffect(result),\n );\n }\n return resultToEffect(source);\n}\n\n/**\n * Run an `Effect` and collect its outcome as an `AsyncResult`.\n *\n * @remarks\n * The effect must need no environment (`R = never`). It is run to an `Exit`\n * (which never rejects), then folded with {@link fromExit}: success → `Ok`, a\n * modeled failure → `Err`, a die/interruption → `Defect`. The returned\n * `AsyncResult` never throws when awaited.\n *\n * @typeParam T - the success value type.\n * @typeParam E - the modeled error type.\n * @param effect - the effect to run.\n */\nexport function fromEffect<T, E>(effect: Effect.Effect<T, E>): AsyncResult<T, E> {\n return fromSafePromise(Effect.runPromiseExit(effect)).flatMap((exit) => fromExit(exit));\n}\n\nfunction resultToEffect<T, E>(result: Result<T, E>): Effect.Effect<T, E> {\n return result.match<Effect.Effect<T, E>>({\n ok: (value) => Effect.succeed(value),\n err: (error) => Effect.fail(error),\n defect: (cause) => Effect.die(cause),\n });\n}\n\n// Effect's `die`/interruption channel is an un-triaged failure crossing into\n// unthrown; replaying it through the throwable boundary lands it in the `Defect`\n// state — the sanctioned (boundary-only) way to mint a Defect `Result`.\nfunction dieToResult<T, E>(cause: unknown): Result<T, E> {\n // The thunk always throws, so its `T` return is honest; `qualify` is `Defect`,\n // so the modeled error is `never` — widened to `E` here (there is no `Err`).\n return fromThrowable((): T => {\n throw cause;\n }, Defect)() as Result<T, E>;\n}\n\nfunction settle<T, E>(asyncResult: AsyncResult<T, E>): Promise<Result<T, E>> {\n return (async () => await asyncResult)();\n}\n\nfunction isAsyncResult<T, E>(\n source: Result<T, E> | AsyncResult<T, E>,\n): source is AsyncResult<T, E> {\n return typeof (source as { then?: unknown }).then === \"function\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,OAAa,QAAuC;CAClE,OAAO,OAAO,MAAuB;EACnC,KAAK,UAAU,KAAK,QAAQ,KAAK;EACjC,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,SAAS,UAAU,KAAK,IAAI,KAAK;CACnC,CAAC;AACH;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,SAAe,MAAqC;CAClE,OAAO,KAAK,MAAM,MAAM;EACtB,YAAY,UAAU,GAAG,KAAK;EAC9B,YAAY,UAAU;GACpB,MAAM,MAAM,MAAM,UAAU,KAAK;GACjC,IAAI,OAAO,OAAO,GAAG,GAAG,OAAO,YAAkB,IAAI,KAAK;GAC1D,MAAM,UAAU,MAAM,cAAc,KAAK;GACzC,IAAI,OAAO,OAAO,OAAO,GAAG,OAAO,IAAI,QAAQ,KAAK;GAEpD,OAAO,YAAkB,MAAM,OAAO,KAAK,CAAC;EAC9C;CACF,CAAC;AACH;;;;;;;;;;;;;;;AAgBA,SAAgB,SACd,QACA,UACqB;CACrB,OAAO,OAAO,MAA2B;EACvC,KAAK,UAAU,OAAO,MAAM,KAAK;EACjC,MAAM,UAAU,OAAO,KAAK,KAAK;EACjC,SAAS,UAAU,OAAO,KAAK,SAAS,KAAK,CAAC;CAChD,CAAC;AACH;;;;;;;;;;;;AAaA,SAAgB,WAAiB,QAA2C;CAC1E,OAAO,OAAO,MAAM,QAAQ;EAC1B,SAAS,UAAU,IAAI,KAAK;EAC5B,UAAU,UAAU,GAAG,KAAK;CAC9B,CAAC;AACH;AAiBA,SAAgB,SAAe,QAA+D;CAC5F,IAAI,cAAc,MAAM,GACtB,OAAO,OAAO,QACZ,OAAO,cAAc,OAAO,MAAM,CAAC,IAClC,WAAW,eAAe,MAAM,CACnC;CAEF,OAAO,eAAe,MAAM;AAC9B;;;;;;;;;;;;;;AAeA,SAAgB,WAAiB,QAAgD;CAC/E,OAAO,gBAAgB,OAAO,eAAe,MAAM,CAAC,CAAC,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC;AACxF;AAEA,SAAS,eAAqB,QAA2C;CACvE,OAAO,OAAO,MAA2B;EACvC,KAAK,UAAU,OAAO,QAAQ,KAAK;EACnC,MAAM,UAAU,OAAO,KAAK,KAAK;EACjC,SAAS,UAAU,OAAO,IAAI,KAAK;CACrC,CAAC;AACH;AAKA,SAAS,YAAkB,OAA8B;CAGvD,OAAO,oBAAuB;EAC5B,MAAM;CACR,GAAG,MAAM,CAAC,CAAC;AACb;AAEA,SAAS,OAAa,aAAuD;CAC3E,QAAQ,YAAY,MAAM,YAAA,CAAa;AACzC;AAEA,SAAS,cACP,QAC6B;CAC7B,OAAO,OAAQ,OAA8B,SAAS;AACxD"}
package/docs/index.md CHANGED
@@ -12,7 +12,7 @@
12
12
  function fromEffect<T, E>(effect): AsyncResult<T, E>;
13
13
  ```
14
14
 
15
- Defined in: [index.ts:165](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L165)
15
+ Defined in: [index.ts:165](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L165)
16
16
 
17
17
  Run an `Effect` and collect its outcome as an `AsyncResult`.
18
18
 
@@ -48,7 +48,7 @@ modeled failure → `Err`, a die/interruption → `Defect`. The returned
48
48
  function fromEither<T, E>(either): Result<T, E>;
49
49
  ```
50
50
 
51
- Defined in: [index.ts:120](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L120)
51
+ Defined in: [index.ts:120](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L120)
52
52
 
53
53
  Convert an Effect `Either` into a `Result`.
54
54
 
@@ -71,7 +71,7 @@ Convert an Effect `Either` into a `Result`.
71
71
 
72
72
  #### Remarks
73
73
 
74
- `Right → Ok`, `Left → Err`. An `Either` carries no defect, so the result is
74
+ `Right → Ok`, `Left → Err`. An `Either` carries no Defect, so the result is
75
75
  never a `Defect`.
76
76
 
77
77
  ***
@@ -82,7 +82,7 @@ never a `Defect`.
82
82
  function fromExit<T, E>(exit): Result<T, E>;
83
83
  ```
84
84
 
85
- Defined in: [index.ts:70](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L70)
85
+ Defined in: [index.ts:70](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L70)
86
86
 
87
87
  Convert an Effect `Exit` into a `Result` — the inverse of
88
88
  [toExit](#toexit).
@@ -126,7 +126,7 @@ more severe signal.
126
126
  function toEffect<T, E>(source): Effect<T, E>;
127
127
  ```
128
128
 
129
- Defined in: [index.ts:140](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L140)
129
+ Defined in: [index.ts:140](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L140)
130
130
 
131
131
  Lift a `Result` or `AsyncResult` into an `Effect`.
132
132
 
@@ -160,7 +160,7 @@ Effect` direction too.
160
160
  function toEffect<T, E>(source): Effect<T, E>;
161
161
  ```
162
162
 
163
- Defined in: [index.ts:141](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L141)
163
+ Defined in: [index.ts:141](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L141)
164
164
 
165
165
  Lift a `Result` or `AsyncResult` into an `Effect`.
166
166
 
@@ -196,9 +196,9 @@ Effect` direction too.
196
196
  function toEither<T, E>(result, onDefect): Either<T, E>;
197
197
  ```
198
198
 
199
- Defined in: [index.ts:98](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L98)
199
+ Defined in: [index.ts:98](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L98)
200
200
 
201
- Convert a `Result` into an Effect `Either`, triaging any defect.
201
+ Convert a `Result` into an Effect `Either`, triaging any Defect.
202
202
 
203
203
  #### Type Parameters
204
204
 
@@ -212,7 +212,7 @@ Convert a `Result` into an Effect `Either`, triaging any defect.
212
212
  | Parameter | Type | Description |
213
213
  | ------ | ------ | ------ |
214
214
  | `result` | `Result`&lt;`T`, `E`&gt; | the result to convert. |
215
- | `onDefect` | (`cause`) => `E` | folds a defect's unknown cause into a modeled `E`. |
215
+ | `onDefect` | (`cause`) => `E` | folds a Defect's unknown cause into a modeled `E`. |
216
216
 
217
217
  #### Returns
218
218
 
@@ -220,7 +220,7 @@ Convert a `Result` into an Effect `Either`, triaging any defect.
220
220
 
221
221
  #### Remarks
222
222
 
223
- `Either` has no defect channel, so a `Defect` cannot pass through silently —
223
+ `Either` has no Defect channel, so a `Defect` cannot pass through silently —
224
224
  `onDefect` **must** fold its cause into a modeled error `E` (a `Left`). This
225
225
  is the boundary-qualification rule (Thesis #3) applied on the way out:
226
226
  `Ok → Right`, `Err → Left`, `Defect → Left(onDefect(cause))`.
@@ -233,7 +233,7 @@ is the boundary-qualification rule (Thesis #3) applied on the way out:
233
233
  function toExit<T, E>(result): Exit<T, E>;
234
234
  ```
235
235
 
236
- Defined in: [index.ts:43](https://github.com/btravstack/unthrown/blob/400cfa972078ebe2522248d056e2f198b8101e81/packages/effect/src/index.ts#L43)
236
+ Defined in: [index.ts:43](https://github.com/btravstack/unthrown/blob/fa4c17ddc81bb2075e8f48dfcc49e5e04d951dd1/packages/effect/src/index.ts#L43)
237
237
 
238
238
  Convert a `Result` into an Effect `Exit` — a **bijection**, since both
239
239
  carry three channels.
@@ -264,7 +264,7 @@ carry three channels.
264
264
  #### Example
265
265
 
266
266
  ```ts
267
- import { ok } from "unthrown";
267
+ import { Ok } from "unthrown";
268
268
  import { toExit } from "@unthrown/effect";
269
- toExit(ok(1)); // Exit.succeed(1)
269
+ toExit(Ok(1)); // Exit.succeed(1)
270
270
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unthrown/effect",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "description": "Effect interop for unthrown",
5
5
  "keywords": [
6
6
  "effect",
@@ -44,7 +44,7 @@
44
44
  "./package.json": "./package.json"
45
45
  },
46
46
  "dependencies": {
47
- "unthrown": "0.2.0"
47
+ "unthrown": "1.0.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "24.13.2",