Skip to content

Commit

Permalink
add combine and bindErr utils. Update internals for zip and bind. Rem…
Browse files Browse the repository at this point in the history
…ove zipAsync
  • Loading branch information
volf52 committed Jul 11, 2024
1 parent ad1836d commit d6e3780
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-apes-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@carbonteq/fp": minor
---

Add combine and bindErr utils. Remove zipAsync. Simplify zip and bind internally
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"devDependencies": {
"@biomejs/biome": "^1.8.3",
"@changesets/cli": "^2.27.7",
"@swc-node/register": "^1.10.3",
"@swc/core": "^1.6.6",
"@swc/jest": "^0.2.36",
"@tsconfig/node18": "^18.2.4",
Expand Down
91 changes: 71 additions & 20 deletions src/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,21 @@ export class UnwrappedOkWithErr extends Error {
}
}

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
function isPromise<T>(obj: any): obj is Promise<T> {
return (
!!obj &&
(typeof obj === "object" || typeof obj === "function") &&
typeof obj.then === "function"
);
}

export type UnitResult<E = never> = Result<UNIT, E>;

type Mapper<T, U> = (val: T) => U;
type AsyncMapper<T, U> = (val: T) => Promise<U>;
type PureResMapper<T, U, E> = (val: T) => Result<U, E>;
type PureAsyncResMapper<T, U, E> = (val: T) => Promise<Result<U, E>>;
type ResMapper<T, U, E> = (val: T) => Result<U, E>;
type AsyncResMapper<T, U, E> = (val: T) => Promise<Result<U, E>>;

type OkOrErr = "ok" | "err";
const okPred = <T, E extends Error>(el: Result<T, E>): boolean => el.isOk();
Expand Down Expand Up @@ -80,13 +89,13 @@ export class Result<T, E> {
}

unwrap(): T {
if (this.isErr()) {
if (this.val === Sentinel) {
if (this.error instanceof Error) throw this.error;

throw new UnwrappedOkWithErr(this);
}

return this.val as T;
return this.val;
}

unwrapOr(def: T): T {
Expand Down Expand Up @@ -190,12 +199,38 @@ export class Result<T, E> {
bind<U, E2>(
fn: (val: T) => Promise<Result<U, E | E2>>,
): Promise<Result<U, E | E2>>;
bind<U, E2>(
fn: PureResMapper<T, U, E | E2> | PureAsyncResMapper<T, U, E | E2>,
bind<U, E2>(fn: ResMapper<T, U, E | E2> | AsyncResMapper<T, U, E | E2>) {
if (this.val !== Sentinel) return fn(this.val);

return Result.Err(this.error);
}

/**
* For combining the errors only while retaining the original value.
* @example
* const r: Result<string, SomeError> = Result.Ok('42')
* const binderOk = (d: string) => Result.Ok<number, SomeOtherError>(0909)
* const binderErr = (d: string) => Result.Err<number, SomeOtherError>(new SomeOtherError())
*
* const res1 = r.bindErr(binderOk) // Result<string, SomeError | SomeOtherError> - Value: Result.Ok('42') - No change in Ok type
* const res2 = r.bindErr(binderErr) // Result<string, SomeError | SomeOtherError> - Value: Result.Err(new SomeOtherError())
*/
bindErr<E2>(fn: (val: T) => Result<unknown, E2>): Result<T, E | E2>;
bindErr<E2>(
fn: (val: T) => Promise<Result<unknown, E2>>,
): Promise<Result<T, E | E2>>;
bindErr<E2>(
fn: ResMapper<T, unknown, E | E2> | AsyncResMapper<T, unknown, E | E2>,
) {
if (this.isOk()) return fn(this.val as T);
if (this.val === Sentinel) return Result.Err(this.error);

const r = fn(this.val);

return Result.Err(this.error as E);
if (isPromise(r)) {
return r.then((result) => result.map((_) => this.val));
}

return r.map((_) => this.val);
}

/** For running infallible side-effects on the contained value. Up to the programmer to ensure the underlying function doesn't fail */
Expand All @@ -219,22 +254,34 @@ export class Result<T, E> {
return this;
}

/** For combining two results lazily. For the eager eval version, see {@link and} */
zip<U, E2>(f: (val: T) => Result<U, E2>): Result<[T, U], E | E2> {
if (this.error !== Sentinel) return Result.Err(this.error);
combine<U>(fn: (val: T) => U): Result<[T, U], E>;
combine<U>(fn: (val: T) => Promise<U>): Promise<Result<[T, U], E>>;
combine<U>(fn: Mapper<T, U> | AsyncMapper<T, U>) {
if (this.val === Sentinel) return Result.Err(this.error);

return f(this.val as T).map((u) => [this.val, u] as [T, U]);
const r = fn(this.val);
if (isPromise(r)) {
return r.then((u) => Result.Ok([this.val, u]) as Result<[T, U], E>);
}

return Result.Ok([this.val, r]) as Result<[T, U], E>;
}

/** For combining two results lazily. For the eager eval version, see {@link and} */
async zipAsync<U, E2>(
f: (val: T) => Promise<Result<U, E2>>,
): Promise<Result<[T, U], E | E2>> {
if (this.error !== Sentinel) return Promise.resolve(Result.Err(this.error));

return f(this.val as T).then((uRes) =>
uRes.map((u) => [this.val, u] as [T, U]),
);
zip<U, E2>(fn: (val: T) => Result<U, E2>): Result<[T, U], E | E2>;
zip<U, E2>(
fn: (val: T) => Promise<Result<U, E2>>,
): Promise<Result<[T, U], E | E2>>;
zip<U, E2>(fn: ResMapper<T, U, E | E2> | AsyncResMapper<T, U, E | E2>) {
if (this.val === Sentinel) return Result.Err(this.error);

const r = fn(this.val);

if (isPromise(r)) {
return r.then((other) => other.map((u) => [this.val, u] as [T, U]));
}

return r.map((u) => [this.val, u] as [T, U]);
}

//#region General combo functions
Expand Down Expand Up @@ -299,3 +346,7 @@ export class Result<T, E> {
}
//#endregion
}

const res1 = Result.Ok<string, Error>("3");
if (res1.isOk()) {
}
157 changes: 156 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,28 @@
human-id "^1.0.2"
prettier "^2.7.1"

"@emnapi/core@^1.1.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.2.0.tgz#7b738e5033738132bf6af0b8fae7b05249bdcbd7"
integrity sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==
dependencies:
"@emnapi/wasi-threads" "1.0.1"
tslib "^2.4.0"

"@emnapi/runtime@^1.1.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.2.0.tgz#71d018546c3a91f3b51106530edbc056b9f2f2e3"
integrity sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==
dependencies:
tslib "^2.4.0"

"@emnapi/[email protected]":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz#d7ae71fd2166b1c916c6cd2d0df2ef565a2e1a5b"
integrity sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==
dependencies:
tslib "^2.4.0"

"@fastify/deepmerge@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a"
Expand Down Expand Up @@ -1097,6 +1119,15 @@
globby "^11.0.0"
read-yaml-file "^1.1.0"

"@napi-rs/wasm-runtime@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz#d27788176f250d86e498081e3c5ff48a17606918"
integrity sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==
dependencies:
"@emnapi/core" "^1.1.0"
"@emnapi/runtime" "^1.1.0"
"@tybys/wasm-util" "^0.9.0"

"@nodelib/[email protected]":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
Expand All @@ -1118,6 +1149,58 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.0.tgz#c98eee3fba9af05c98a885f7c116d276ca1137f1"
integrity sha512-sJpH25yjQQf+59g4WAhrZYSiLiev2kFmHIvANeX8/ZAUEvtmRKmw/sCfK1cS6F6iRWNlSSjKbmahaY0ubS95ug==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.0.tgz#938dbe89665b536f3eb1cf01b31e6fcabb9d4f64"
integrity sha512-ETtWuoq5nmg1810bMeKCQ5vKq85Sy+arx7LDVEUFvkz4g0+6WP1SVYr4st7jBh8k6AhXAw1d7H5zRTL6Sfep/w==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.0.tgz#9c445d03d8faba1e6953af4367ecddfb2e7c7bab"
integrity sha512-0h8Tn0c2aUagCO0nNU0YwSqBbNBKrc4/0uSwM/gAKrzmjEbup2dZEDkvAoBzEFgGc8DFdvKv/uxydgJvpyAGZQ==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.0.tgz#1e7138abefad9196ff57969c31df761070a4728f"
integrity sha512-RtJAj35/v4mm4MIEwlz8nomcgEpktdgOoIRdVaneSDjfTSQdagC34Bx9TRGLKt5u3xgP4xYx0rFTSBCmJUJoSQ==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.0.tgz#bbfa9974d12b023621cb2340542d0080f43bfa5a"
integrity sha512-d9PBWbK3SCrj/018LoCyQ34LEEKZXyVwA/UCtRzCvZmgRxlRDmrim/xgl2IyXEqu3/9eeGnGnip1ceATGnAacA==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.0.tgz#e23f65cb567f40ec37f1ecbe252fcf5826b5817b"
integrity sha512-dv2YPpCk2SQNQI/NiPSr207bdsIBD/1Gn7zpz/r9o6cl0RucHRk4KsMRamkJvWR+jIw0CwGTsgQZZTImcObLCQ==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.0.tgz#96c65cef943f31c99a1fc4c2c385b24d28f35e0f"
integrity sha512-RdIxtyhPfxd8uUX2IkotnLHAkdrvVvEhv0ZNB31K6CtwVekZKWxSETzodN8+2LLNgp+4CClMHxhc59IapGUPKA==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.0.tgz#c43bc5c228edcd845c33f84ee23b58f6e43e026f"
integrity sha512-drqVsc2dj7rUdZ/UBzDxfyuPL8ZBjKYKiuW7RBrYKSOYKA4qNDIqB2qDUTv940WDF4WhrHFpHEjT6Y1Sp+Fvxw==
dependencies:
"@napi-rs/wasm-runtime" "^0.2.4"

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.0.tgz#8d66576a55590240622d9ed876aedd1b8575d77b"
integrity sha512-RbDplFsBJkj4huit8d7XG2wKQ7IMdQhLAUBeK02JzsDDrpNsgD1fa3YOy2oGO3GPUWEJXyhq1okFyyVIHrUf3g==

"@oxc-resolver/[email protected]":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.0.tgz#9000c9c197d0e86bcc3ec58378c6a46388cf180c"
integrity sha512-0atlXXYIzdzvXBlPwdFde3PppPyapb+KofI9jjM88na9ytsC7Unn9hlV7egr2JSaGKCiEBDK8zOxoG1ueEauVA==

"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
Expand Down Expand Up @@ -1236,6 +1319,32 @@
dependencies:
"@sinonjs/commons" "^3.0.0"

"@swc-node/core@^1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@swc-node/core/-/core-1.13.2.tgz#0b3b563edd2a8c951dbaeecfa1795b8cd1b29a30"
integrity sha512-skceAbeKUmEK8z1nxStJTTsbIInKqW4n4+ZCYFexy6UsHjsc7MAfR2v5QqNJr/Fl/j+yLY6UkXY2VUU63nEC/Q==

"@swc-node/register@^1.10.3":
version "1.10.3"
resolved "https://registry.yarnpkg.com/@swc-node/register/-/register-1.10.3.tgz#7f426fbbc069edd73b7231edb2a1199601fa2639"
integrity sha512-QSffEXDGh/A6q0SWGEmnvKOqrCY0EiOLhAaS9KGxe2+0RKSOIjuBjTDilBLKHltudNCDkEE6kBljwGz7xoAREA==
dependencies:
"@swc-node/core" "^1.13.2"
"@swc-node/sourcemap-support" "^0.5.1"
colorette "^2.0.20"
debug "^4.3.5"
oxc-resolver "^1.9.2"
pirates "^4.0.6"
tslib "^2.6.3"

"@swc-node/sourcemap-support@^0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz#0355540d62874891770ce1ba06838de186f098ff"
integrity sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==
dependencies:
source-map-support "^0.5.21"
tslib "^2.6.3"

"@swc/[email protected]":
version "1.6.6"
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.6.tgz#9488d50394cb08713c4321a940b48599c1c5e153"
Expand Down Expand Up @@ -1331,6 +1440,13 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.4.tgz#094efbdd70f697d37c09f34067bf41bc4a828ae3"
integrity sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ==

"@tybys/wasm-util@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355"
integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==
dependencies:
tslib "^2.4.0"

"@types/babel__core@^7.1.14":
version "7.20.1"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b"
Expand Down Expand Up @@ -1749,6 +1865,11 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==

colorette@^2.0.20:
version "2.0.20"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==

[email protected]:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
Expand Down Expand Up @@ -1802,7 +1923,7 @@ debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "2.1.2"

debug@^4.3.1:
debug@^4.3.1, debug@^4.3.5:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
Expand Down Expand Up @@ -3002,6 +3123,22 @@ outdent@^0.5.0:
resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff"
integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==

oxc-resolver@^1.9.2:
version "1.10.0"
resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-1.10.0.tgz#5a6d25bfec2ca8f7c504eae2bde699e7fcfa75a5"
integrity sha512-FkObNl6JVrbqvvRqXCQhYZvrJHqEJNAjWDuPxHx9CblwoYzL5zcM74Ba30ek3YUopaUSNit3ceaILqShAx+hgw==
optionalDependencies:
"@oxc-resolver/binding-darwin-arm64" "1.10.0"
"@oxc-resolver/binding-darwin-x64" "1.10.0"
"@oxc-resolver/binding-linux-arm-gnueabihf" "1.10.0"
"@oxc-resolver/binding-linux-arm64-gnu" "1.10.0"
"@oxc-resolver/binding-linux-arm64-musl" "1.10.0"
"@oxc-resolver/binding-linux-x64-gnu" "1.10.0"
"@oxc-resolver/binding-linux-x64-musl" "1.10.0"
"@oxc-resolver/binding-wasm32-wasi" "1.10.0"
"@oxc-resolver/binding-win32-arm64-msvc" "1.10.0"
"@oxc-resolver/binding-win32-x64-msvc" "1.10.0"

p-filter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c"
Expand Down Expand Up @@ -3120,6 +3257,11 @@ pirates@^4.0.4:
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==

pirates@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==

pkg-dir@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
Expand Down Expand Up @@ -3382,6 +3524,14 @@ [email protected]:
buffer-from "^1.0.0"
source-map "^0.6.0"

source-map-support@^0.5.21:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"

source-map@^0.6.0, source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
Expand Down Expand Up @@ -3531,6 +3681,11 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"

tslib@^2.4.0, tslib@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==

[email protected]:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
Expand Down

0 comments on commit d6e3780

Please sign in to comment.