Repository: karen-irc/option-t
Pull request #1476 (2022-11-20 16:43:26)

Implement `fromPromiseSettledResultToResult()`


Patch:
diff --git a/docs/idiom/README.md b/docs/idiom/README.md
index e7824d31..e3541d78 100644
--- a/docs/idiom/README.md
+++ b/docs/idiom/README.md
@@ -10,4 +10,3 @@ But we often need a glue code for the interoperability to JavaScript world.
 This document provides some idioms of this library for the interoperability to JavaScript world.
 
 * [Express Progressive data](./express_progress.md)
-* [Convert from PromiseSettledResult<T>) to `PlainResult`](./from_promise_settled_result.md)
diff --git a/docs/idiom/from_promise_settled_result.md b/docs/idiom/from_promise_settled_result.md
deleted file mode 100644
index 78590675..00000000
--- a/docs/idiom/from_promise_settled_result.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Convert from PromiseSettledResult<T>) to `PlainResult`
-
-```typescript
-import type { Result, createOk, createErr } from 'option-t/PlainResult/Result';
-
-function convertFromPromiseSettledResultToPlainResult<T>(input: PromiseSettledResult<T>): Result<T, unknown> {
-    switch (input.status) {
-        case 'fulfilled': {
-            const value = input.value;
-            const ok = createOk(value);
-            return ok;
-        }
-        case 'rejected': {
-            const reason = input.reason;
-            const err = createErr(reason);
-            return err;
-        }
-        default:
-            throw new TypeError(`unknown PromiseSettledResult status: ${input.status}`);
-    }
-}
-```
diff --git a/docs/public_api_list.md b/docs/public_api_list.md
index 18572840..9862b9f8 100644
--- a/docs/public_api_list.md
+++ b/docs/public_api_list.md
@@ -104,6 +104,7 @@
 - [option-t/PlainResult/equal](../src/PlainResult/equal.ts)
 - [option-t/PlainResult/expect](../src/PlainResult/expect.ts)
 - [option-t/PlainResult/flatten](../src/PlainResult/flatten.ts)
+- [option-t/PlainResult/fromPromiseSettledResult](../src/PlainResult/fromPromiseSettledResult.ts)
 - [option-t/PlainResult/inspect](../src/PlainResult/inspect.ts)
 - [option-t/PlainResult/map](../src/PlainResult/map.ts)
 - [option-t/PlainResult/mapAsync](../src/PlainResult/mapAsync.ts)
diff --git a/src/PlainResult/fromPromiseSettledResult.ts b/src/PlainResult/fromPromiseSettledResult.ts
new file mode 100644
index 00000000..e4f144c7
--- /dev/null
+++ b/src/PlainResult/fromPromiseSettledResult.ts
@@ -0,0 +1,27 @@
+import { type Result, createOk, createErr } from './Result.js';
+
+/**
+ *  Convert {@link PromiseSettledResult<T>} returned by {@link Promise.allSettled} to {@link Result}
+ */
+export function fromPromiseSettledResultToResult<T>(
+    input: PromiseSettledResult<T>
+): Result<T, unknown> {
+    const status = input.status;
+    switch (status) {
+        case 'fulfilled': {
+            const value = input.value;
+            const ok = createOk(value);
+            return ok;
+        }
+        case 'rejected': {
+            const reason = input.reason;
+            const err = createErr(reason);
+            return err;
+        }
+        default: {
+            const statusStr = String(status);
+            const message = `\`PromiseSettledResult.status=${statusStr}\` is not supported`;
+            throw new TypeError(message);
+        }
+    }
+}
diff --git a/tools/pkg_files.json b/tools/pkg_files.json
index 706a419d..6959c45b 100644
--- a/tools/pkg_files.json
+++ b/tools/pkg_files.json
@@ -195,6 +195,8 @@
     "cjs/PlainResult/expect.cjs": null,
     "cjs/PlainResult/flatten.d.cts": null,
     "cjs/PlainResult/flatten.cjs": null,
+    "cjs/PlainResult/fromPromiseSettledResult.d.cts": null,
+    "cjs/PlainResult/fromPromiseSettledResult.cjs": null,
     "cjs/PlainResult/index.d.cts": null,
     "cjs/PlainResult/index.cjs": null,
     "cjs/PlainResult/inspect.d.cts": null,
@@ -290,7 +292,6 @@
     "cjs/index.d.cts": null,
     "cjs/index.cjs": null,
     "docs/idiom/express_progress.md": null,
-    "docs/idiom/from_promise_settled_result.md": null,
     "docs/idiom/README.md": null,
     "docs/deprecated_apis.md": null,
     "docs/how_to_import.md": null,
@@ -490,6 +491,8 @@
     "esm/PlainResult/expect.js": null,
     "esm/PlainResult/flatten.d.ts": null,
     "esm/PlainResult/flatten.js": null,
+    "esm/PlainResult/fromPromiseSettledResult.d.ts": null,
+    "esm/PlainResult/fromPromiseSettledResult.js": null,
     "esm/PlainResult/index.d.ts": null,
     "esm/PlainResult/index.js": null,
     "esm/PlainResult/inspect.d.ts": null,
@@ -680,6 +683,7 @@
     "lib/PlainResult/equal.d.ts": null,
     "lib/PlainResult/expect.d.ts": null,
     "lib/PlainResult/flatten.d.ts": null,
+    "lib/PlainResult/fromPromiseSettledResult.d.ts": null,
     "lib/PlainResult/index.d.ts": null,
     "lib/PlainResult/inspect.d.ts": null,
     "lib/PlainResult/map.d.ts": null,
diff --git a/tools/public_api/table.mjs b/tools/public_api/table.mjs
index 9908eda2..5c0be297 100644
--- a/tools/public_api/table.mjs
+++ b/tools/public_api/table.mjs
@@ -547,6 +547,11 @@ export const apiTable = Object.freeze({
             'flattenForResult'
         ]
     },
+    'PlainResult/fromPromiseSettledResult': {
+        'exports': [
+            'fromPromiseSettledResultToResult'
+        ]
+    },
     'PlainResult/inspect': {
         'exports': [
             'inspectOkOfResult',
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 380ae9f2..18c2dabe 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -9,6 +9,7 @@
         "lib": [                                   /* Specify library files to be included in the compilation. */
             "ES5",
             "ES2015.Promise",
+            "ES2020.Promise",
             "ES2022.Error",
         ],
         // "allowJs": true,                             /* Allow javascript files to be compiled. */


Test patch:
diff --git a/__tests__/PlainResult/from_promise_settled_result.test.mjs b/__tests__/PlainResult/from_promise_settled_result.test.mjs
new file mode 100644
index 00000000..f1d14979
--- /dev/null
+++ b/__tests__/PlainResult/from_promise_settled_result.test.mjs
@@ -0,0 +1,42 @@
+import test from 'ava';
+
+import { isOk, isErr } from '../../__dist/esm/PlainResult/Result.js';
+import { fromPromiseSettledResultToResult } from '../../__dist/esm/PlainResult/fromPromiseSettledResult.js';
+import { unwrapOkFromResult, unwrapErrFromResult } from '../../__dist/esm/PlainResult/unwrap.js';
+
+test('should be Ok(T)', async (t) => {
+    const VALUE_T = Symbol('value');
+    const [input] = await Promise.allSettled([Promise.resolve(VALUE_T)]);
+    t.is(input.status, 'fulfilled');
+
+    const actual = fromPromiseSettledResultToResult(input);
+    t.true(isOk(actual), 'should be Ok');
+    t.is(unwrapOkFromResult(actual), VALUE_T, 'should be the wrapped value');
+});
+
+test('should be Err(T)', async (t) => {
+    const VALUE_E = Symbol('error');
+    const [input] = await Promise.allSettled([Promise.reject(VALUE_E)]);
+    t.is(input.status, 'rejected');
+
+    const actual = fromPromiseSettledResultToResult(input);
+    t.true(isErr(actual), 'should be Ok');
+    t.is(unwrapErrFromResult(actual), VALUE_E, 'should be the wrapped value');
+});
+
+test('should throw error if the input is not supported type', async (t) => {
+    const status = `unknown_${Math.random()}`;
+    const unknownPromiseSettledResult = {
+        status,
+    };
+
+    t.throws(
+        () => {
+            fromPromiseSettledResultToResult(unknownPromiseSettledResult);
+        },
+        {
+            instanceOf: TypeError,
+            message: `\`PromiseSettledResult.status=${status}\` is not supported`,
+        }
+    );
+});