@windyroad/wrap-fetch v3.1.0
@windyroad/wrap-fetch
@windyroad/wrap-fetch is a small library that provides a simple way to wrap the global
fetch function with a custom wrapper function. This can be useful for adding custom headers
to requests, caching responses, logging requests and responses, transforming responses, mocking
responses for testing, adding authentication tokens to requests, handling errors, and more.
Installation
To install @windyroad/wrap-fetch, you can use npm or yarn:
npm install @windyroad/wrap-fetchUsage
To use @windyroad/wrap-fetch, you can import the wrapFetch function and use it to wrap the
global fetch function with a custom wrapper function. The wrapper function should take the
fetch function and its arguments and return a promise that resolves to the response.
Here's an example of how to use wrapFetch to add custom headers to requests:
import { wrapFetch } from '@windyroad/wrap-fetch';
const wrapper = (fetchImpl, ...args) => {
const headers = new Headers(args[1].headers);
headers.set('Authorization', 'Bearer token');
args[1].headers = headers;
return fetchImpl(...args);
};
const wrappedFetch = wrapFetch(wrapper);
/**
* Or
* ```
* const wrappedFetch = wrapFetch(wrapper, customFetch);
* ```
* if you want to wrap a different implementation of fetch.
**/
const url = 'https://example.com';
const options = { headers: { 'Content-Type': 'application/json' } };
const response = await wrappedFetch(url, options);In this code, we've imported the wrapFetch function from @windyroad/wrap-fetch and used it
to wrap the global fetch function with a function that adds an Authorization header to
requests. We've then used the wrapped fetch function to make a request to
https://example.com with a custom Content-Type header.
Examples
Here's a list of some useful examples of using @windyroad/wrap-fetch:
- Adding custom headers to requests: You can use
wrapFetchto add custom headers to requests by wrapping thefetchfunction with a function that adds the headers to the request.
const wrapper = (fetch, ...args) => {
const headers = new Headers(args[1].headers);
headers.set('Authorization', 'Bearer token');
args[1].headers = headers;
return fetch(...args);
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const options = { headers: { 'Content-Type': 'application/json' } };
const response = await wrappedFetch(url, options);- Caching responses: You can use
wrapFetchto cache responses by wrapping thefetchfunction with a function that checks if the response is already cached and returns the cached response if it is.
const cache = new Map();
const wrapper = async (fetch, ...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const response = await fetch(...args);
cache.set(key, response);
return response;
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response1 = await wrappedFetch(url);
const response2 = await wrappedFetch(url);- Logging requests and responses: You can use
wrapFetchto log requests and responses by wrapping thefetchfunction with a function that logs the request and response data.
const log = console.log.bind(console);
const wrapper = async (fetch, ...args) => {
log('Request:', args);
const response = await fetch(...args);
log('Response:', response);
return response;
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response = await wrappedFetch(url);- Transforming responses: You can use
wrapFetchto transform responses by wrapping thefetchfunction with a function that transforms the response data before returning it.
const wrapper = async (fetch, ...args) => {
const response = await fetch(...args);
const data = await response.json();
return { ...response, data };
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response = await wrappedFetch(url);- Mocking responses for testing: You can use
wrapFetchto mock responses for testing by wrapping thefetchfunction with a function that returns a predefined response instead of making a real request.
const wrapper = async () => {
return new Response('{"foo": "bar"}', { status: 200 });
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response = await wrappedFetch(url);- Adding authentication tokens to requests: You can use
wrapFetchto add authentication tokens to requests by wrapping thefetchfunction with a function that adds the token to the request headers.
const token = 'secret';
const wrapper = (fetch, ...args) => {
const headers = new Headers(args[1].headers);
headers.set('Authorization', `Bearer ${token}`);
args[1].headers = headers;
return fetch(...args);
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response = await wrappedFetch(url);- Handling errors: You can use
wrapFetchto handle errors by wrapping thefetchfunction with a function that checks for errors in the response and throws an error if one is found.
const wrapper = async (fetch, ...args) => {
const response = await fetch(...args);
if (!response.ok) {
const data = await response.json();
throw new Error(data.error);
}
return response;
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
await expect(wrappedFetch(url)).rejects.toThrow('Not found');- Adding query parameters to requests: You can use
wrapFetchto add query parameters to requests by wrapping thefetchfunction with a function that adds the parameters to the request URL.
const wrapper = (fetch, ...args) => {
const url = new URL(args[0]);
url.searchParams.set('foo', 'bar');
args[0] = url.toString();
return fetch(...args);
};
const wrappedFetch = wrapFetch(wrapper);
const url = 'https://example.com';
const response = await wrappedFetch(url);These examples should provide a good starting point for using @windyroad/wrap-fetch in your own projects.
API
wrapFetch
function wrapFetch<
WrapInputs extends any[] = Parameters<typeof fetch>,
WrapReturns = Awaited<ReturnType<typeof fetch>>,
FetchFunction<Arguments, ResponseType> extends (...args: any) => Promise<any> = typeof fetch,
>(
wrapper: (
fetchImplInner: (
...args: FetchInputs<typeof fetchImpl>
) => Promise<FetchReturns<typeof fetchImpl>>,
...args: WrapInputs
) => Promise<WrapReturns>,
fetchImpl?: FetchFunction<Arguments, ResponseType>,
): (...args: WrapInputs) => Promise<WrapReturns>Wraps a fetch implementation with a wrapper function.
Parameters
wrapper: The wrapper function to apply to thefetchimplementation.fetchImpl: Thefetchimplementation to wrap. Defaults to the globalfetchfunction.
Type Parameters
WrapInputs: The type of the input arguments for the wrapper function. Defaults toParameters<typeof fetch>.WrapReturns: The return type of the wrapper function. Defaults toAwaited<ReturnType<typeof fetch>>.FetchFunction<Arguments, ResponseType>: The type of thefetchimplementation. Defaults totypeof fetch.
Returns
A wrapped version of the fetch implementation.
Contributing
Contributions are welcome! Please read the contributing guidelines for more information.
License
@windyroad/wrap-fetch is lovingly licensed under the MIT License. ❤️