From cfd45a908bdf3ba3bd7f273aabd92fb63c013886 Mon Sep 17 00:00:00 2001 From: Julien Elbaz Date: Sat, 29 Jun 2024 06:53:08 +0200 Subject: [PATCH] :art: Enhance errorType and allow disabling it --- src/config.ts | 4 ++-- src/core.ts | 4 ++-- src/resolver.ts | 24 ++++++++++++++++++------ src/types.ts | 6 ++++-- test/node/wretch.spec.ts | 10 ++++++++++ 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/config.ts b/src/config.ts index 6daebbd..f9e67b0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,5 @@ import { mix } from "./utils.js" -import type { Config } from "./types.js" +import type { Config, ErrorType } from "./types.js" declare const global @@ -94,7 +94,7 @@ export function setPolyfills(polyfills: object, replace = false) { * * If null, defaults to "text". */ -export function setErrorType(errorType: string) { +export function setErrorType(errorType: ErrorType) { config.errorType = errorType } diff --git a/src/core.ts b/src/core.ts index 2db630f..889b349 100644 --- a/src/core.ts +++ b/src/core.ts @@ -2,7 +2,7 @@ import { mix, extractContentType, isLikelyJsonMime } from "./utils.js" import { JSON_MIME, CONTENT_TYPE_HEADER, CATCHER_FALLBACK } from "./constants.js" import { resolver } from "./resolver.js" import config from "./config.js" -import type { Wretch } from "./types.js" +import type { Wretch, ErrorType } from "./types.js" export const core: Wretch = { _url: "", @@ -16,7 +16,7 @@ export const core: Wretch = { addon(addon) { return { ...this, _addons: [...this._addons, addon], ...addon.wretch } }, - errorType(errorType: string) { + errorType(errorType: ErrorType) { return { ...this, _config: { diff --git a/src/resolver.ts b/src/resolver.ts index 1c4848a..fd6f0ac 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -56,17 +56,29 @@ export const resolver = (wretch: T & Wretch) => { err["cause"] = referenceError err.stack = err.stack + "\nCAUSE: " + referenceError.stack err.response = response + err.status = response.status err.url = finalUrl + if (response.type === "opaque") { throw err } - return response.text().then((body: string) => { - err.message = body - if (config.errorType === "json" || response.headers.get("Content-Type")?.split(";")[0] === "application/json") { - try { err.json = JSON.parse(body) } catch (e) { /* ignore */ } + + const jsonErrorType = config.errorType === "json" || response.headers.get("Content-Type")?.split(";")[0] === "application/json" + const bodyPromise = + !config.errorType ? Promise.resolve(response.body) : + jsonErrorType ? response.text() : + response[config.errorType]() + + return bodyPromise.then((body: unknown) => { + err.message = typeof body === "string" ? body : response.statusText + if(body) { + if(jsonErrorType && typeof body === "string") { + err.text = body + err.json = JSON.parse(body) + } else { + err[config.errorType] = body + } } - err.text = body - err["status"] = response.status throw err }) } diff --git a/src/types.ts b/src/types.ts index ffb822d..e5914a6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,7 +83,7 @@ export interface Wretch { * @category Helpers * @param method - The method to call on the Fetch response to read the body and use it as the Error message */ - errorType(this: Self & Wretch, method: string): this + errorType(this: Self & Wretch, method: ErrorType): this /** * Sets non-global polyfills - for instance in browserless environments. @@ -733,12 +733,14 @@ export interface WretchResponseChain { fetchError: (this: Self & WretchResponseChain, cb: WretchErrorCallback) => this, } +export type ErrorType = "text" | "json" | "blob" | "formData" | "arrayBuffer" | undefined | null + /** * Configuration object. */ export type Config = { options: object; - errorType: string; + errorType: ErrorType; polyfills: object; polyfill(p: "fetch", doThrow?: boolean): typeof fetch; polyfill(p: "FormData", doThrow: boolean, instance: true, ...args: ConstructorParameters): FormData; diff --git a/test/node/wretch.spec.ts b/test/node/wretch.spec.ts index b46b33c..f043b7b 100644 --- a/test/node/wretch.spec.ts +++ b/test/node/wretch.spec.ts @@ -575,6 +575,16 @@ describe("Wretch", function () { }) .res(_ => fail("I should never be called because an error was thrown")) .then(_ => expect(_).toBe(undefined)) + // Disabled + await wretch(`${_URL}/json500raw`) + .errorType(null) + .get() + .internalError(error => { + expect(error.json).toEqual(undefined) + expect(error.text).toEqual(undefined) + }) + .res(_ => fail("I should never be called because an error was thrown")) + .then(_ => expect(_).toBe(undefined)) // Global wretch.errorType("json") await wretch(`${_URL}/json500raw`)