Fetcher
A simple and small (typed) library on top of fetch that is more user friendly.
Sections:
Please head to the API Docs for detailed information.
Installation
npm install @paquitosoft/fetcher
How to use it
The module exports four API functions tailored for the main HTTP Methods (GET, POST, PUT, DELETE) and also another one to tailor your request (and use other HTTP methods).
Sending a GET request
import { get } from '@paquitosoft/fetcher';
async function loadProducts() {
const products = await get('https://fakestoreapi.com/products');
console.log({ products });
}
async function loadAndCacheProducts() {
const products = await get('https://fakestoreapi.com/products', {
ttl: 10 * 60
});
console.log({ products });
}
Sending a POST request
import { post } from '@paquitosoft/fetcher';
async function saveProduct() {
const newProduct = {
title: 'test product',
price: 13.5,
description: 'lorem ipsum set',
image: 'https://i.pravatar.cc',
category: 'electronic'
};
const persistedProduct = await post('https://fakestoreapi.com/products', newProduct);
console.log({ persistedProduct });
}
Caching
By default fetcher
uses an in-memory cache so you can avoid hitting the server for long-lived resources.
This is controlled by the ttl
(seconds) parameter for GET requests.
You can also provide your own custom cache manager to store values in other locations such local-storage
or IndexedDB
.
For such situations, you would create
a class/object which implements the CacheManager interface.
import { setCacheManager, get } from '@paquitosoft/fetcher';
const localStorageCacheManager = {
set(key, value, options = { ttl: 0 }) {
const cacheEntry = {
expires: Date.now() + ((options?.ttl || 0) * 1000),
value
};
localStorage.setItem(key, JSON.stringify(cacheEntry));
},
get(key) {
const cacheEntryRaw = localStorage.getItem(key);
if (!cacheEntry) return undefined;
const now = Date.now();
const cacheEntry = JSON.parse(cacheEntryRaw);
if (cacheEntry && now < cacheEntry.expires) {
return cacheEntry.value;
} else {
localStorage.removeItem(key);
return undefined;
}
}
};
setCacheManager(localStorageCacheManager);
async function loadAndCacheProducts() {
const products = await get('https://fakestoreapi.com/products', {
ttl: 10 * 60
});
console.log({ products });
}
Middlewares
There might be scenarios where you would like to apply some logic before or after every request. You can achieve this by using middlewares
.
You would create middleware functions and register them in the fetcher
module by calling the addMiddleware
function.
Before request middlewares
These are just functions that receive the request meta-data and must return that meta-data with your needed modifications.
Here is an example of a middleware to add some sort of auth token to every request.
import { addMiddleware, removeMiddleware, get } from '@paquitosoft/fetcher';
function authMiddleware({ method, url, fetchOptions, ttl, body, cache }) {
const authToken = localStorage.getItem('auth-token');
const headers = {
...fetchOptions.headers,
'Authorization': `Bearer ${authToken}`
};
return {
fetchOptions: {
...fetchOptions,
headers
}
};
}
addMiddleware('before', authMiddleware);
const shopCart = await get('https://fakestoreapi.com/carts/5');
removeMiddleware(authMiddleware);
After request middlewares
In you ever need to modify the response from the server before it gets to your consumer, you can use an after middleware which receives the data fetched from the server (processed) and can return whatever it wants.
Here is an example where we modify the response if user is in a certain A/B experiment:
import { addMiddleware, get } from '@paquitosoft/fetcher';
function updateProductsMetaData(serverData: products) {
const isProductsListingUrl = /\/products$/.test(url);
if (isProductsListingUrl) {
const isUserInExperiment = (localStorage.getItem('user-ab-engaged-experiments') || '')
.split(',').includes('exp_001');
if (isUserInExperiment) {
return products.map(product => ({
...product,
labels: ['NEW']
}));
}
}
}
addMiddleware('before', updateProductsMetaData);
const products = await get('https://fakestoreapi.com/products');