From 905244a57d7b2e890634d7bcf9b314c8d1f7450e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 23 Aug 2023 20:55:46 +0200 Subject: [PATCH] fix: hide getters from console and pass `cause` --- README.md | 2 +- src/error.ts | 28 +++++++++++++++++++++++----- test/index.test.ts | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index df2a042..8ac446e 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Parsed error body is available with `error.data`. You may also use `FetchError` ```ts await ofetch("https://google.com/404"); -// FetchError: [GET] "https://google/404": 404 "Not Found" +// FetchError: [GET] "https://google/404": 404 Not Found // at async main (/project/playground.ts:4:3) ``` diff --git a/src/error.ts b/src/error.ts index 66ab594..2d8f7cf 100644 --- a/src/error.ts +++ b/src/error.ts @@ -5,8 +5,7 @@ import type { FetchResponse, } from "./fetch"; -export class FetchError extends Error { - name = "FetchError"; +export interface IFetchError extends Error { request?: FetchRequest; options?: FetchOptions; response?: FetchResponse; @@ -17,7 +16,23 @@ export class FetchError extends Error { statusMessage?: string; } -export function createFetchError(ctx: FetchContext): FetchError { +export class FetchError extends Error implements IFetchError { + constructor(message: string, opts?: { cause: unknown }) { + // @ts-ignore https://v8.dev/features/error-cause + super(message, opts); + + this.name = "FetchError"; + + // Polyfill cause for other runtimes + if (opts?.cause && !this.cause) { + this.cause = opts.cause; + } + } +} + +export function createFetchError( + ctx: FetchContext +): IFetchError { const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; const method = @@ -26,14 +41,17 @@ export function createFetchError(ctx: FetchContext): FetchError { const requestStr = `[${method}] ${JSON.stringify(url)}`; const statusStr = ctx.response - ? `${ctx.response.status} ${JSON.stringify(ctx.response.statusText)}` + ? `${ctx.response.status} ${ctx.response.statusText}` : ""; const message = `${requestStr}: ${statusStr}${ errorMessage ? ` ${errorMessage}` : "" }`; - const fetchError: FetchError = new FetchError(message); + const fetchError: FetchError = new FetchError( + message, + ctx.error ? { cause: ctx.error } : undefined + ); for (const key of ["request", "options", "response"] as const) { Object.defineProperty(fetchError, key, { diff --git a/test/index.test.ts b/test/index.test.ts index 8558ab3..de25338 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -306,7 +306,7 @@ describe("ofetch", () => { (error) => error ); expect(error.toString()).toBe( - 'FetchError: [POST] "http://localhost:3000/403": 403 "Forbidden"' + 'FetchError: [POST] "http://localhost:3000/403": 403 Forbidden' ); expect(error.request).to.equal(getURL("403")); expect(error.options.method).to.equal("POST");