/cachios

Simple axios cache wrapper using node-cache

Primary LanguageJavaScriptMIT LicenseMIT

Cachios

Dependency Status npm version Build Status: Node.js CI Coverage Status

NPM

A simple axios cache wrapper using node-cache.


Cachios is meant to be a replacement for the following pattern:

const axios = require('axios');

const resources = {};

function getResource(id) {
  if (!resources[id]) {
    // actually retrieve the resource
    return axios.get(`/api/thing/${id}`).then((resp) => {
      // store the resource
      resources[id] = resp.data;
      return resp.data;
    });
  } else {
    // return the resource we already have
    return Promise.resolve(resources[id]);
  }
}

With Cachios, this is replaced with:

const cachios = require('cachios');

function getResource(id) {
  return cachios.get(`/api/thing/${id}`).then((resp) => {
    return resp.data;
  });
}

The following axios methods are supported:

  • request
  • get
  • delete
  • head
  • options
  • post
  • put
  • patch

The entire response is not cached, and is instead trimmed down (by default) to status and data. To configure this, see "Custom Response Copier".

Installation

npm install --save cachios

Examples

Basic:

const cachios = require('cachios');

cachios.get('https://jsonplaceholder.typicode.com/posts/1', {
  ttl: 300 /* seconds */,
}).then(console.log);

Custom axios client:

// your normal, non-cached axios instance that is already setup.
import axios from './configured-axios';

const cachios = require('cachios');
const cachiosInstance = cachios.create(axios);

const postData = {/* your postdata here */};

cachiosInstance.post('/posts/1', postData, {
  ttl: 30, // persist 30 seconds
}).then((resp) => {
  console.log(resp.status);

  const data = resp.data;
  console.log(data.title);
  console.log(data.body);
});

Multiple cached GET requests: Runkit

Multiple cached GET requests with different query parameters: Runkit

Configuration

TTL

To set the cache TTL, pass it in with your request config:

const cachios = require('cachios');

cachios.get('url', {
  ttl: /* time to live in seconds */,
});

const postData = {};
cachios.post('url', postData, {
  headers: /* your custom headers */
  ...
  ttl: 60, // persist this result for 60 seconds
});

Force Ignore Cache

To ignore existing cache items and force a fresh request to go through, use force: true:

const cachios = require('cachios');

cachios.get('url'); // cache 'url'

// ignore and update cache for 'url' by using `force: true`
cachios.get('url', {
  force: true,
});

Custom Axios Instance

Cachios also supports using a pre-configured axios instance:

const cachios = require('cachios');
const axios = require('axios');

const axiosInstance = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
});

// all requests will now use this axios instance
const cachiosInstance = cachios.create(axiosInstance);

Custom Cache Configuration

Internally, Cachios uses node-cache with sane defaults. To configure it yourself, pass it during cachios.create:

const cachios = require('cachios');
const axios = require('axios');

// configure `node-cache` to keep cache forever!
const cachiosInstance = cachios.create(axios, {
  stdTTL: 0,
  checkperiod: 0,
});

Alternative Cache Implementation

Don't want to use node-cache? The .cache property can be overridden.

cachios expects the cache implementation to work as follows:

cachios.cache = {
  /**
  cacheKey: string

  if a value has been set for this `cacheKey`, return it.
  otherwise, return a falsey value (undefined, false, null).

  synchronous, asynchronous, and promise-returning functions are supported.
  */
  get(cacheKey),

  /**
  cacheKey: string
  cacheValue: mixed
  ttl: number|undefined

  store the value `cacheValue` under `cacheKey` for `ttl` seconds.
  if `ttl` is not set, it is assumed the value is stored forever.

  synchronous, asynchronous, and promise-returning functions are supported.
  */
  set(cacheKey, cacheValue, ttl),
}

Example using lru-cache:

const cachios = require('cachios');
const LRU  = require('lru-cache');

cachios.cache = LRU(500);

cachios.get('http://example.com/') // not cached
.then(() => cachios.get('http://example.com/')); // cached
.then(() => {
  console.log(cachios.cache.itemCount); // 1 item in cache - the first request
});

Example of persistent cache with keyv and @keyv/sqlite:

const cachios = require('cachios');
const Keyv = require('keyv');

cachios.cache = new Keyv('sqlite://cache.sqlite');

cachios.get('http://example.com/') // not cached
.then(() => cachios.get('http://example.com/')); // cached
.then(() => cachios.cache.opts.store.query('SELECT COUNT(*) as count FROM keyv'))
.then((cacheSize) => {
  console.log(cacheSize[0].count); // 1 item in cache - the first request
});

Custom Response Copier

By default, Cachios uses the following function to trim responses:

function defaultResponseCopier(response) {
  return {
    status: response.status,
    data: response.data,
  };
}

This was originally implemented because of errors during response storage.

To change what is saved, set the getResponseCopy property of your Cachios instance:

const cachios = require('cachios');

cachios.getResponseCopy = function (response) {
  return {
    status: response.status,
    statusText: response.statusText,
    data: response.data,
  };
};

Custom Cache Identifier

By default, Cachios uses the following function to create a unique cache identifier:

function defaultCacheIdentifer(config) {
  return {
    method: config.method,
    url: config.url,
    params: config.params,
    data: config.data,
  };
}

To override this, set the getCacheIdentifier property of your Cachios instance:

const cachios = require('cachios');

cachios.getCacheIdentifier = function (config) {
  return {
    method: config.method,
    url: config.url,
    params: config.params,
    data: config.data,
    headers: config.headers,
  };
};

Custom object-hash Replacer

By default, Cachios uses an internal defaultReplacer function to add FormData support to object-hash.

To override this, set the getReplaced property of your Cachios instance:

const cachios = require('cachios');

cachios.getReplaced = function (thing) {
  if (thing === 'foo') {
    return 'bar';
  }

  return thing;
};

License

MIT