react-relay-network-modern
Version:
Network Layer for React Relay and Express (Batch Queries, AuthToken, Logging, Retry)
90 lines (75 loc) • 2 kB
Flow
/* @flow */
import { QueryResponseCache } from 'relay-runtime';
import type { Middleware } from '../definition';
import { isFunction } from '../utils';
type CacheMiddlewareOpts = {|
size?: number,
ttl?: number,
onInit?: (cache: QueryResponseCache) => any,
allowMutations?: boolean,
allowFormData?: boolean,
clearOnMutation?: boolean,
cacheErrors?: boolean,
updateTTLOnGet?: boolean,
|};
export default function cacheMiddleware(opts?: CacheMiddlewareOpts): Middleware {
const {
size,
ttl,
onInit,
allowMutations,
allowFormData,
clearOnMutation,
cacheErrors,
updateTTLOnGet,
} = opts || {};
const cache = new QueryResponseCache({
size: size || 100, // 100 requests
ttl: ttl || 15 * 60 * 1000, // 15 minutes
});
if (isFunction(onInit)) {
onInit(cache);
}
return (next) => async (req) => {
if (req.isMutation()) {
if (clearOnMutation) {
cache.clear();
}
if (!allowMutations) {
return next(req);
}
}
if (req.isFormData() && !allowFormData) {
return next(req);
}
if (req.cacheConfig && req.cacheConfig.force) {
const queryId = req.getID();
const variables = req.getVariables();
const res = await next(req);
if (!res.errors || (res.errors && cacheErrors)) {
cache.set(queryId, variables, res);
}
return res;
}
try {
const queryId = req.getID();
const variables = req.getVariables();
const cachedRes = cache.get(queryId, variables);
if (cachedRes) {
if (updateTTLOnGet) {
cache.set(queryId, variables, cachedRes);
}
return cachedRes;
}
const res = await next(req);
if (!res.errors || (res.errors && cacheErrors)) {
cache.set(queryId, variables, res);
}
return res;
} catch (e) {
// if error, just log it to console
console.log(e); // eslint-disable-line
}
return next(req);
};
}