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);
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
Register an Addon to enhance the wretch or response objects.
import FormDataAddon from "wretch/addons/formData"
import QueryStringAddon from "wretch/addons/queryString"
// Add a single addon
const w = wretch().addon(FormDataAddon)
// Or add multiple addons at once
const w2 = wretch().addon([FormDataAddon, QueryStringAddon])
// Additional features are now available
w.formData({ hello: "world" }).query({ check: true })
A Wretch addon or an array of addons to register
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
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
})
Wretch.catcher for more details.
Configures custom error parsing for all error responses.
Allows you to transform errors and add custom properties that will be fully typed across all error handlers (.error(), .badRequest(), .unauthorized(), etc.).
interface ApiError {
code: number;
message: string;
}
const api = wretch("https://api.example.com")
.customError<ApiError>(async (error, response, request) => {
const json = await response.json();
return { ...error, ...json };
});
// All error handlers now have typed access to ApiError properties
api.get("/resource")
.badRequest(error => {
// error.code and error.message are fully typed as ApiError
console.log(error.code, error.message);
})
.json();
A function that receives the error, response, and request, and returns the transformed error with custom properties
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();
Sets a custom fetch implementation to use for requests.
This is useful for:
// Add performance monitoring to fetch
const customFetch = (url, opts) => {
console.time(url)
return fetch(url, opts).finally(() => console.timeEnd(url))
}
wretch("http://domain.com")
.fetchPolyfill(customFetch)
.get()
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()
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"}}
Programs a resolver to perform response chain tasks automatically.
Very useful when you need to perform repetitive actions on the wretch response.
The clear argument, if set to true, removes previously defined resolvers.
// Program "response" chain actions early on
const w = wretch()
.addon(PerfsAddon())
.resolve(resolver => resolver
// monitor every request…
.perfs(console.log)
// automatically parse and return json…
.json()
)
const myJson = await w.url("http://a.com").get()
// Equivalent to:
// w.url("http://a.com")
// .get()
// <- the resolver chain is automatically injected here !
// .perfs(console.log)
// .json()
Resolver callback
Optionalclear: ClearConverts the wretch instance into a fetch-like function that preserves all accumulated configuration (middlewares, catchers, options, headers, etc.).
Useful for integrating with libraries that expect a fetch function signature.
const myFetch = wretch("https://api.example.com")
.auth("Bearer token")
.catcher(401, handleAuth)
.middlewares([retry()])
.toFetch()
// Use like regular fetch but with all the wretch configuration
const response = await myFetch("/users", { method: "GET" })
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);
The Wretch object used to perform easy fetch requests.
Immutability : almost every method of this class return a fresh Wretch object.