wretch
Version:
A tiny wrapper built around fetch with an intuitive syntax.
777 lines (776 loc) • 31.2 kB
TypeScript
/**
* The Wretch object used to perform easy fetch requests.
*
* ```ts
* 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.
*/
export interface Wretch<Self = unknown, Chain = unknown, Resolver = undefined, ErrorType = undefined> {
/**
* @private @internal
*/
_url: string;
/**
* @private @internal
*/
_options: WretchOptions;
/**
* @private @internal
*/
_fetch?: FetchLike | ((url: string, opts: WretchOptions) => Promise<Response>);
/**
* @private @internal
*/
_errorTransformer?: <T>(error: WretchError, response: WretchResponse, request: Wretch<any, any, any, any>) => Promise<T> | T;
/**
* @private @internal
*/
_catchers: Map<number | string | symbol, (error: ErrorType extends undefined ? WretchError : ErrorType, originalRequest: Wretch<Self, Chain, Resolver, ErrorType>) => void>;
/**
* @private @internal
*/
_resolvers: ((resolver: Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain> : Resolver, originalRequest: Wretch<Self, Chain, Resolver, ErrorType>) => any)[];
/**
* @private @internal
*/
_deferred: WretchDeferredCallback<Self, Chain, Resolver, ErrorType>[];
/**
* @private @internal
*/
_middlewares: ConfiguredMiddleware[];
/**
* @private @internal
*/
_addons: WretchAddon<unknown, Chain>[];
/**
* Register an Addon to enhance the wretch or response objects.
*
* ```js
* 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 })
* ```
*
* @category Helpers
* @param addon - A Wretch addon or an array of addons to register
*/
addon<W, R>(addon: WretchAddon<W, R>): W & Self & Wretch<Self & W, Chain & R, Resolver, ErrorType>;
addon<W1, R1, W2, R2>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>]): W1 & W2 & Self & Wretch<Self & W1 & W2, Chain & R1 & R2, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>]): W1 & W2 & W3 & Self & Wretch<Self & W1 & W2 & W3, Chain & R1 & R2 & R3, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>]): W1 & W2 & W3 & W4 & Self & Wretch<Self & W1 & W2 & W3 & W4, Chain & R1 & R2 & R3 & R4, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4, W5, R5>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>, WretchAddon<W5, R5>]): W1 & W2 & W3 & W4 & W5 & Self & Wretch<Self & W1 & W2 & W3 & W4 & W5, Chain & R1 & R2 & R3 & R4 & R5, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4, W5, R5, W6, R6>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>, WretchAddon<W5, R5>, WretchAddon<W6, R6>]): W1 & W2 & W3 & W4 & W5 & W6 & Self & Wretch<Self & W1 & W2 & W3 & W4 & W5 & W6, Chain & R1 & R2 & R3 & R4 & R5 & R6, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4, W5, R5, W6, R6, W7, R7>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>, WretchAddon<W5, R5>, WretchAddon<W6, R6>, WretchAddon<W7, R7>]): W1 & W2 & W3 & W4 & W5 & W6 & W7 & Self & Wretch<Self & W1 & W2 & W3 & W4 & W5 & W6 & W7, Chain & R1 & R2 & R3 & R4 & R5 & R6 & R7, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4, W5, R5, W6, R6, W7, R7, W8, R8>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>, WretchAddon<W5, R5>, WretchAddon<W6, R6>, WretchAddon<W7, R7>, WretchAddon<W8, R8>]): W1 & W2 & W3 & W4 & W5 & W6 & W7 & W8 & Self & Wretch<Self & W1 & W2 & W3 & W4 & W5 & W6 & W7 & W8, Chain & R1 & R2 & R3 & R4 & R5 & R6 & R7 & R8, Resolver, ErrorType>;
addon<W1, R1, W2, R2, W3, R3, W4, R4, W5, R5, W6, R6, W7, R7, W8, R8, W9, R9>(addon: [WretchAddon<W1, R1>, WretchAddon<W2, R2>, WretchAddon<W3, R3>, WretchAddon<W4, R4>, WretchAddon<W5, R5>, WretchAddon<W6, R6>, WretchAddon<W7, R7>, WretchAddon<W8, R8>, WretchAddon<W9, R9>]): W1 & W2 & W3 & W4 & W5 & W6 & W7 & W8 & W9 & Self & Wretch<Self & W1 & W2 & W3 & W4 & W5 & W6 & W7 & W8 & W9, Chain & R1 & R2 & R3 & R4 & R5 & R6 & R7 & R8 & R9, Resolver, ErrorType>;
/**
* Sets a custom fetch implementation to use for requests.
*
* This is useful for:
* - Adding custom middleware to fetch
* - Using alternative fetch implementations
* - Mocking fetch in tests
* - Adding performance monitoring
*
* ```js
* // 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()
* ```
*
* @category Helpers
* @param fetch - A custom fetch implementation
*/
fetchPolyfill(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, fetch: (url: string, opts: WretchOptions) => Promise<Response>): this;
/**
* Appends or replaces the url.
*
* ```js
* 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);
* ```
*
* @category Helpers
* @param url - Url segment
* @param replace - If true, replaces the current url instead of appending
*/
url(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, url: string, replace?: boolean): this;
/**
* Sets the fetch options.
*
* ```js
* wretch("...").options({ credentials: "same-origin" });
* ```
*
* Wretch being immutable, you can store the object for later use.
*
* ```js
* 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.
*
* ```js
* // 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"}}
* ```
*
* @category Helpers
* @param options - New options
* @param replace - If true, replaces the existing options
*/
options(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, options: WretchOptions, replace?: boolean): this;
/**
* Sets the request headers.
*
* ```js
* wretch("...")
* .headers({ "Content-Type": "text/plain", Accept: "application/json" })
* .post("my text")
* .json();
* ```
*
* @category Helpers
* @param headerValues - An object containing header keys and values
*/
headers(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, headerValues: HeadersInit): this;
/**
* Shortcut to set the "Accept" header.
*
* ```js
* wretch("...").accept("application/json");
* ```
*
* @category Helpers
* @param headerValue - Header value
*/
accept(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, headerValue: string): this;
/**
* Shortcut to set the "Content-Type" header.
*
* ```js
* wretch("...").content("application/json");
* ```
*
* @category Helpers
* @param headerValue - Header value
*/
content(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, headerValue: string): this;
/**
* Shortcut to set the "Authorization" header.
*
* ```js
* wretch("...").auth("Basic d3JldGNoOnJvY2tz");
* ```
*
* @category Helpers
* @param headerValue - Header value
*/
auth(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, headerValue: string): this;
/**
* Adds a [catcher](https://github.com/elbywan/wretch#catchers) which will be
* called on every subsequent request error.
*
* Very useful when you need to perform a repetitive action on a specific error
* code or multiple error codes.
*
* ```js
* const w = wretch()
* .catcher(404, err => redirect("/routes/notfound", err.message))
* .catcher(500, err => flashMessage("internal.server.error"))
*
* // Catch multiple error codes with the same handler
* const w2 = wretch()
* .catcher([401, 403], err => redirect("/login"))
*
* // No need to catch the 404, 500, 401, or 403 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.
*
* ```js
* 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
* ```
*
* @category Helpers
* @param errorId - Error code or name, or an array of error codes/names
* @param catcher - The catcher method
*/
catcher(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, errorId: ErrorId | ErrorId[], catcher: (error: ErrorType extends undefined ? WretchError : ErrorType, originalRequest: this) => any): Self & Wretch<Self, Chain, Resolver, ErrorType extends undefined ? WretchError : ErrorType>;
/**
* A fallback catcher that will be called for any error thrown - if uncaught by other means.
*
* ```js
* 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
* })
* ```
*
* @category Helpers
* @see {@link Wretch.catcher} for more details.
* @param catcher - The catcher method
*/
catcherFallback(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, catcher: (error: unknown, originalRequest: this) => any): Self & Wretch<Self, Chain, Resolver, ErrorType extends undefined ? WretchError : ErrorType>;
/**
* 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.).
*
* ```js
* 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();
* ```
*
* @category Helpers
* @param transformer - A function that receives the error, response, and request, and returns the transformed error with custom properties
*/
customError<T extends (ErrorType extends undefined ? any : ErrorType)>(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, transformer: (error: WretchError, response: WretchResponse, request: Self & Wretch<Self, Chain, Resolver, ErrorType>) => Promise<T> | T): Self & Wretch<Self, Chain, Resolver, T>;
/**
* Defer one or multiple request chain methods that will get called just before the request is sent.
*
* ```js
* // 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();
* ```
*
* @category Helpers
* @param callback - Exposes the wretch instance, url and options to program deferred methods.
* @param clear - Replace the existing deferred methods if true instead of pushing to the existing list.
*/
defer<Clear extends boolean = false>(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, callback: WretchDeferredCallback<Self, Chain, Resolver, ErrorType>, clear?: Clear): this;
/**
* 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._
*
* ```js
* // 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()
* ```
*
* @category Helpers
* @param resolver - Resolver callback
*/
resolve<ResolverReturn, Clear extends boolean = false>(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, resolver: (chain: Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, undefined, ErrorType> : Clear extends true ? Chain & WretchResponseChain<Self, Chain, undefined, ErrorType> : Resolver, originalRequest: Self & Wretch<Self, Chain, Clear extends true ? undefined : Resolver, ErrorType>) => ResolverReturn, clear?: Clear): Self & Wretch<Self, Chain, ResolverReturn, ErrorType>;
/**
* Add middlewares to intercept a request before being sent.
*
* ```javascript
* // 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()
* ```
*
* @category Helpers
*/
middlewares(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, middlewares: ConfiguredMiddleware[], clear?: boolean): this;
/**
* Sets the request body with any content.
*
* ```js
* wretch("...").body("hello").put();
* // Note that calling put/post methods with a non-object argument is equivalent:
* wretch("...").put("hello");
* ```
*
* @category Body Types
* @param contents - The body contents
*/
body(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, contents: any): this;
/**
* Sets the "Content-Type" header, stringifies an object and sets the request body.
*
* ```js
* 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);
* ```
*
* @category Body Types
* @param jsObject - An object which will be serialized into a JSON
* @param contentType - A custom content type.
*/
json(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, jsObject: object, contentType?: string): this;
/**
* Sends the request using the accumulated fetch options.
*
* Can be used to replay requests.
*
* ```js
* 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
* ```
*
* @category HTTP
* @param method - The HTTP method to use
* @param url - Some url to append
* @param body - Set the body. Behaviour varies depending on the argument type, an object is considered as json.
*/
fetch(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, method?: string, url?: string, body?: any): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) request.
*
* ```js
* wretch("...").get();
* ```
*
* @category HTTP
*/
get(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [DELETE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) request.
*
* ```js
* wretch("...").delete();
* ```
*
* @category HTTP
*/
delete(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [PUT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) request.
*
* ```js
* wretch("...").json({...}).put()
* ```
*
* @category HTTP
*/
put(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, body?: any, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) request.
*
* ```js
* wretch("...").json({...}).post()
* ```
*
* @category HTTP
*/
post(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, body?: any, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [PATCH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) request.
*
* ```js
* wretch("...").json({...}).patch()
* ```
*
* @category HTTP
*/
patch(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, body?: any, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs a [HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) request.
*
* ```js
* wretch("...").head();
* ```
*
* @category HTTP
*/
head(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Performs an [OPTIONS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) request.
*
* ```js
* wretch("...").opts();
* ```
*
* @category HTTP
*/
opts(this: Self & Wretch<Self, Chain, Resolver, ErrorType>, url?: string): Resolver extends undefined ? Chain & WretchResponseChain<Self, Chain, Resolver, ErrorType> : Resolver;
/**
* Converts 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.
*
* ```js
* 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" })
* ```
*
* @category Helpers
*/
toFetch(this: Self & Wretch<Self, Chain, Resolver, ErrorType>): (url: string, options?: WretchOptions) => Promise<Response>;
}
/**
* The resolver interface to chaining catchers and extra methods after the request has been sent.
* Ultimately returns a Promise.
*
*/
export interface WretchResponseChain<T, Self = unknown, R = undefined, ErrorType = undefined> {
/**
* @private @internal
*/
_wretchReq: Wretch<T, Self, R, ErrorType>;
/**
* @private @internal
*/
_fetchReq: Promise<WretchResponse>;
/**
* @private @internal
*/
_sharedState: Record<any, any>;
/**
*
* The handler for the raw fetch Response.
* Check the [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Response) documentation for more details on the Response class.
*
* ```js
* wretch("...").get().res((response) => console.log(response.url));
* ```
*
* @category Response Type
*/
res: <Result = WretchResponse>(cb?: (type: WretchResponse) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Read the payload and deserialize it as JSON.
*
* ```js
* wretch("...").get().json((json) => console.log(Object.keys(json)));
* ```
*
* @category Response Type
*/
json: <Result = unknown>(cb?: (type: any) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Read the payload and deserialize it as a Blob.
*
* ```js
* wretch("...").get().blob(blob => …)
* ```
*
* @category Response Type
*/
blob: <Result = Blob>(cb?: (type: Blob) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Read the payload and deserialize it as a FormData object.
*
* ```js
* wretch("...").get().formData(formData => …)
* ```
*
* @category Response Type
*/
formData: <Result = FormData>(cb?: (type: FormData) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Read the payload and deserialize it as an ArrayBuffer object.
*
* ```js
* wretch("...").get().arrayBuffer(arrayBuffer => …)
* ```
*
* @category Response Type
*/
arrayBuffer: <Result = ArrayBuffer>(cb?: (type: ArrayBuffer) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Retrieves the payload as a string.
*
* ```js
* wretch("...").get().text((txt) => console.log(txt));
* ```
*
* @category Response Type
*/
text: <Result = string>(cb?: (type: string) => Promise<Result> | Result) => Promise<Awaited<Result>>;
/**
* Catches an http response with a specific error code or name and performs a callback.
*
* The original request is passed along the error and can be used in order to
* perform an additional request.
*
* ```js
* wretch("/resource")
* .get()
* .unauthorized(async (error, req) => {
* // Renew credentials
* const token = await wretch("/renewtoken").get().text();
* storeToken(token);
* // Replay the original request with new credentials
* return req.auth(token).get().unauthorized((err) => {
* throw err;
* }).json();
* })
* .json()
* // The promise chain is preserved as expected
* // ".then" will be performed on the result of the original request
* // or the replayed one (if a 401 error was thrown)
* .then(callback);
* ```
*
* @category Catchers
*/
error: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, code: (number | string | symbol), cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches a bad request (http code 400) and performs a callback.
*
* _Syntactic sugar for `error(400, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
badRequest: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches an unauthorized request (http code 401) and performs a callback.
*
* _Syntactic sugar for `error(401, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
unauthorized: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches a forbidden request (http code 403) and performs a callback.
*
* _Syntactic sugar for `error(403, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
forbidden: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches a "not found" request (http code 404) and performs a callback.
*
* _Syntactic sugar for `error(404, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
notFound: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches a timeout (http code 408) and performs a callback.
*
*
* _Syntactic sugar for `error(408, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
timeout: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches an internal server error (http code 500) and performs a callback.
*
*
* _Syntactic sugar for `error(500, cb)`._
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
internalError: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
/**
* Catches any error thrown by the fetch function and perform the callback.
*
* @see {@link WretchResponseChain.error}
* @category Catchers
*/
fetchError: (this: Self & WretchResponseChain<T, Self, R, ErrorType>, cb: WretchErrorCallback<T, Self, R, ErrorType>) => this;
}
/**
* Fetch Request options with additional properties.
*/
export type WretchOptions = Record<string, any> & RequestInit;
/**
* An Error enhanced with status, text and body.
*/
export type WretchError = Error & {
status: number;
response: WretchResponse;
url: string;
};
/**
* Callback provided to catchers on error. Contains the original wretch instance used to perform the request.
*/
export type WretchErrorCallback<T, C, R, E> = (error: E extends undefined ? WretchError : E, originalRequest: T & Wretch<T, C, R, E>) => any;
/**
* Fetch Response object with additional properties.
*/
export type WretchResponse = Response & {
[key: string]: any;
};
/**
* Any function having the same shape as fetch().
*/
export type FetchLike = (url: string, opts: WretchOptions) => Promise<WretchResponse>;
/**
* Callback provided to the defer function allowing to chain deferred actions that will be stored and applied just before the request is sent.
*/
export type WretchDeferredCallback<T, C, R, E> = (wretch: T & Wretch<T, C, R, E>, url: string, options: WretchOptions) => Wretch<T, C, any, E>;
/**
* Shape of a typical middleware.
* Expects options and returns a ConfiguredMiddleware that can then be registered using the .middlewares function.
*/
export type Middleware = (options?: {
[key: string]: any;
}) => ConfiguredMiddleware;
/**
* A ready to use middleware which is called before the request is sent.
* Input is the next middleware in the chain, then url and options.
* Output is a promise.
*/
export type ConfiguredMiddleware = (next: FetchLike) => FetchLike;
/**
* An addon enhancing either the request or response chain (or both).
*/
export type WretchAddon<W, R = unknown> = {
beforeRequest?<T, C, R, E = unknown>(wretch: T & Wretch<T, C, R, E>, options: WretchOptions, state: Record<any, any>): T & Wretch<T, C, R, E>;
wretch?: W;
resolver?: R | (<T, C, E = unknown>(_: C & WretchResponseChain<T, C, R, E>) => R);
};
export type ErrorId = number | string | symbol;