Interface Wretch<Self, Chain, Resolver>

The Wretch object used to perform easy fetch requests.

import wretch from "wretch"

// Reusable wretch instance
const w = wretch("https://domain.com", { mode: "cors" })

Immutability : almost every method of this class return a fresh Wretch object.

interface Wretch<Self, Chain, Resolver> {
    accept(this: Self & Wretch<Self, Chain, Resolver>, headerValue: string): this;
    addon<W, R>(addon: WretchAddon<W, R>): W & Self & Wretch<Self & W, Chain & R, Resolver>;
    auth(this: Self & Wretch<Self, Chain, Resolver>, headerValue: string): this;
    body(this: Self & Wretch<Self, Chain, Resolver>, contents: any): this;
    catcher(this: Self & Wretch<Self, Chain, Resolver>, errorId: string | number | symbol, catcher: ((error: WretchError, originalRequest: this) => any)): this;
    catcherFallback(this: Self & Wretch<Self, Chain, Resolver>, catcher: ((error: WretchError, originalRequest: this) => any)): this;
    content(this: Self & Wretch<Self, Chain, Resolver>, headerValue: string): this;
    defer<Clear>(this: Self & Wretch<Self, Chain, Resolver>, callback: WretchDeferredCallback<Self, Chain, Resolver>, clear?: Clear): this;
    delete(this: Self & Wretch<Self, Chain, Resolver>, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    errorType(this: Self & Wretch<Self, Chain, Resolver>, method: ErrorType): this;
    fetch(this: Self & Wretch<Self, Chain, Resolver>, method?: string, url?: string, body?: any): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    get(this: Self & Wretch<Self, Chain, Resolver>, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    head(this: Self & Wretch<Self, Chain, Resolver>, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    headers(this: Self & Wretch<Self, Chain, Resolver>, headerValues: HeadersInit): this;
    json(this: Self & Wretch<Self, Chain, Resolver>, jsObject: object, contentType?: string): this;
    middlewares(this: Self & Wretch<Self, Chain, Resolver>, middlewares: ConfiguredMiddleware[], clear?: boolean): this;
    options(this: Self & Wretch<Self, Chain, Resolver>, options: WretchOptions, replace?: boolean): this;
    opts(this: Self & Wretch<Self, Chain, Resolver>, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    patch(this: Self & Wretch<Self, Chain, Resolver>, body?: any, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    polyfills(this: Self & Wretch<Self, Chain, Resolver>, polyfills: object, replace?: boolean): this;
    post(this: Self & Wretch<Self, Chain, Resolver>, body?: any, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    put(this: Self & Wretch<Self, Chain, Resolver>, body?: any, url?: string): Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver;
    resolve<ResolverReturn, Clear>(this: Self & Wretch<Self, Chain, Resolver>, resolver: ((chain: Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, undefined>
        : Clear extends true
            ? Chain & WretchResponseChain<Self, Chain, undefined>
            : Resolver, originalRequest: Self & Wretch<Self, Chain, Clear extends true
        ? undefined
        : Resolver>) => ResolverReturn), clear?: Clear): Self & Wretch<Self, Chain, ResolverReturn>;
    url(this: Self & Wretch<Self, Chain, Resolver>, url: string, replace?: boolean): this;
}

Type Parameters

  • Self = unknown
  • Chain = unknown
  • Resolver = undefined

Body Types

  • Sets the request body with any content.

    wretch("...").body("hello").put();
    // Note that calling put/post methods with a non-object argument is equivalent:
    wretch("...").put("hello");

    Parameters

    Returns this

  • Sets the "Content-Type" header, stringifies an object and sets the request body.

    const jsonObject = { a: 1, b: 2, c: 3 };
    wretch("...").json(jsonObject).post();
    // Note that calling an 'http verb' method with an object argument is equivalent:
    wretch("...").post(jsonObject);

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • jsObject: object

      An object which will be serialized into a JSON

    • OptionalcontentType: string

      A custom content type.

    Returns this

HTTP

  • Sends the request using the accumulated fetch options.

    Can be used to replay requests.

    const reAuthOn401 = wretch()
    .catcher(401, async (error, request) => {
    // Renew credentials
    const token = await wretch("/renewtoken").get().text();
    storeToken(token);
    // Replay the original request with new credentials
    return request.auth(token).fetch().unauthorized((err) => {
    throw err;
    }).json();
    });

    reAuthOn401
    .get("/resource")
    .json() // <- Will only be called for the original promise
    .then(callback); // <- Will be called for the original OR the replayed promise result

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • Optionalmethod: string

      The HTTP method to use

    • Optionalurl: string

      Some url to append

    • Optionalbody: any

      Set the body. Behaviour varies depending on the argument type, an object is considered as json.

    Returns Resolver extends undefined
        ? Chain & WretchResponseChain<Self, Chain, Resolver<Resolver>>
        : Resolver

Helpers

  • Shortcut to set the "Accept" header.

    wretch("...").accept("application/json");
    

    Parameters

    Returns this

  • Register an Addon to enhance the wretch or response objects.

    import FormDataAddon from "wretch/addons/formData"
    import QueryStringAddon from "wretch/addons/queryString"

    // Add both addons
    const w = wretch().addon(FormDataAddon).addon(QueryStringAddon)

    // Additional features are now available
    w.formData({ hello: "world" }).query({ check: true })

    Type Parameters

    • W
    • R

    Parameters

    Returns W & Self & Wretch<Self & W, Chain & R, Resolver>

  • Shortcut to set the "Authorization" header.

    wretch("...").auth("Basic d3JldGNoOnJvY2tz");
    

    Parameters

    Returns this

  • Adds a catcher which will be called on every subsequent request error.

    Very useful when you need to perform a repetitive action on a specific error code.

    const w = wretch()
    .catcher(404, err => redirect("/routes/notfound", err.message))
    .catcher(500, err => flashMessage("internal.server.error"))

    // No need to catch the 404 or 500 codes, they are already taken care of.
    w.get("http://myapi.com/get/something").json()

    // Default catchers can be overridden if needed.
    w
    .get("http://myapi.com/get/something")
    .notFound(err =>
    // overrides the default 'redirect' catcher
    )
    .json()

    The original request is passed along the error and can be used in order to perform an additional request.

    const reAuthOn401 = wretch()
    .catcher(401, async (error, request) => {
    // Renew credentials
    const token = await wretch("/renewtoken").get().text();
    storeToken(token);
    // Replay the original request with new credentials
    return request.auth(token).fetch().unauthorized((err) => {
    throw err;
    }).json();
    });

    reAuthOn401
    .get("/resource")
    .json() // <- Will only be called for the original promise
    .then(callback); // <- Will be called for the original OR the replayed promise result

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • errorId: string | number | symbol

      Error code or name

    • catcher: ((error: WretchError, originalRequest: this) => any)

      The catcher method

        • (error, originalRequest): any
        • Parameters

          Returns any

    Returns this

  • A fallback catcher that will be called for any error thrown - if uncaught by other means.

    wretch(url)
    .catcher(404, err => redirect("/routes/notfound", err.message))
    .catcher(500, err => flashMessage("internal.server.error"))
    // this fallback will trigger for any error except the ones caught above (404 and 505)
    .catcherFallback(err => {
    log("Uncaught error:", err)
    throw err
    })

    Parameters

    Returns this

    Wretch.catcher for more details.

  • Shortcut to set the "Content-Type" header.

    wretch("...").content("application/json");
    

    Parameters

    Returns this

  • Defer one or multiple request chain methods that will get called just before the request is sent.

    // Small fictional example: deferred authentication

    // If you cannot retrieve the auth token while configuring the wretch object you can use .defer to postpone the call
    const api = wretch("http://some-domain.com").defer((w, url, options) => {
    // If we are hitting the route /user…
    if (//user/.test(url)) {
    const { token } = options.context;
    return w.auth(token);
    }
    return w;
    });

    // ... //

    const token = await getToken(request.session.user);

    // .auth gets called here automatically
    api.options({
    context: { token },
    }).get("/user/1").res();

    Type Parameters

    • Clear extends boolean = false

    Parameters

    Returns this

  • Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error is returned.

    Note: if the response Content-Type header is set to "application/json", the body will be parsed as json regardless of the errorType.

    wretch("http://server/which/returns/an/error/with/a/json/body")
    .errorType("json")
    .get()
    .res()
    .catch(error => {
    // error[errorType] (here, json) contains the parsed body
    console.log(error.json)
    })

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • method: ErrorType

      The method to call on the Fetch response to read the body and use it as the Error message

    Returns this

  • Sets the request headers.

    wretch("...")
    .headers({ "Content-Type": "text/plain", Accept: "application/json" })
    .post("my text")
    .json();

    Parameters

    Returns this

  • Add middlewares to intercept a request before being sent.

    // A simple delay middleware.
    const delayMiddleware = delay => next => (url, opts) => {
    return new Promise(res => setTimeout(() => res(next(url, opts)), delay))
    }

    // The request will be delayed by 1 second.
    wretch("...").middlewares([
    delayMiddleware(1000)
    ]).get().res()

    Parameters

    Returns this

  • Sets the fetch options.

    wretch("...").options({ credentials: "same-origin" });
    

    Wretch being immutable, you can store the object for later use.

    const corsWretch = wretch().options({ credentials: "include", mode: "cors" });

    corsWretch.get("http://endpoint1");
    corsWretch.get("http://endpoint2");

    You can override instead of mixing in the existing options by passing a boolean flag.

    // By default options are mixed in :
    let w = wretch()
    .options({ headers: { "Accept": "application/json" } })
    .options({ encoding: "same-origin", headers: { "X-Custom": "Header" } });
    console.log(JSON.stringify(w._options))
    // => {"encoding":"same-origin", "headers":{"Accept":"application/json","X-Custom":"Header"}}

    // With the flag, options are overridden :
    w = wretch()
    .options({ headers: { "Accept": "application/json" } })
    .options(
    { encoding: "same-origin", headers: { "X-Custom": "Header" } },
    true,
    );
    console.log(JSON.stringify(w._options))
    // => {"encoding":"same-origin","headers":{"X-Custom":"Header"}}

    Parameters

    Returns this

  • Sets non-global polyfills - for instance in browserless environments.

    Needed for libraries like fetch-ponyfill.

    const fetch = require("node-fetch");
    const FormData = require("form-data");

    wretch("http://domain.com")
    .polyfills({
    fetch: fetch,
    FormData: FormData,
    URLSearchParams: require("url").URLSearchParams,
    })
    .get()

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • polyfills: object

      An object containing the polyfills

    • Optionalreplace: boolean

      If true, replaces the current polyfills instead of mixing in

    Returns this

  • Appends or replaces the url.

    wretch("/root").url("/sub").get().json();

    // Can be used to set a base url

    // Subsequent requests made using the 'blogs' object will be prefixed with "http://domain.com/api/blogs"
    const blogs = wretch("http://domain.com/api/blogs");

    // Perfect for CRUD apis
    const id = await blogs.post({ name: "my blog" }).json(blog => blog.id);
    const blog = await blogs.get(`/${id}`).json();
    console.log(blog.name);

    await blogs.url(`/${id}`).delete().res();

    // And to replace the base url if needed :
    const noMoreBlogs = blogs.url("http://domain2.com/", true);

    Parameters

    • this: Self & Wretch<Self, Chain, Resolver>
    • url: string

      Url segment

    • Optionalreplace: boolean

      If true, replaces the current url instead of appending

    Returns this