UNPKG

persistent-cache

Version:

A simple module to persistently store/cache arbitrary data.

214 lines (160 loc) 5.07 kB
var path = require('path'); var fs = require('fs'); var mkdirp = require('mkdirp-no-bin'); var rmdir = require('rmdir'); function exists(dir) { try { fs.accessSync(dir); } catch(err) { return false; } return true; } function safeCb(cb) { if(typeof cb === 'function') return cb; return function(){}; } function cache(options) { var options = options || {}; var base = path.normalize( (options.base || (require.main ? path.dirname(require.main.filename) : undefined) || process.cwd()) + '/cache' ); var cacheDir = path.normalize(base + '/' + (options.name || 'cache')); var cacheInfinitely = !(typeof options.duration === "number"); var cacheDuration = options.duration; var ram = typeof options.memory == 'boolean' ? options.memory : true; var persist = typeof options.persist == 'boolean' ? options.persist : true; if(ram) var memoryCache = {}; if(persist && !exists(cacheDir)) mkdirp.sync(cacheDir); function buildFilePath(name) { return path.normalize(cacheDir + '/' + name + '.json'); } function buildCacheEntry(data) { return { cacheUntil: !cacheInfinitely ? new Date().getTime() + cacheDuration : undefined, data: data }; } function put(name, data, cb) { var entry = buildCacheEntry(data); if(persist) fs.writeFile(buildFilePath(name), JSON.stringify(entry), cb); if(ram) { entry.data = JSON.stringify(entry.data); memoryCache[name] = entry; if(!persist) return safeCb(cb)(null); } } function putSync(name, data) { var entry = buildCacheEntry(data); if(persist) fs.writeFileSync(buildFilePath(name), JSON.stringify(entry)); if(ram) { memoryCache[name] = entry; memoryCache[name].data = JSON.stringify(memoryCache[name].data); } } function get(name, cb) { if(ram && !!memoryCache[name]) { var entry = memoryCache[name]; if(!!entry.cacheUntil && new Date().getTime() > entry.cacheUntil) { return safeCb(cb)(null, undefined); } try{ entry = JSON.parse(entry.data); } catch(e){ return safeCb(cb)(e); } return safeCb(cb)(null, entry); } fs.readFile(buildFilePath(name), 'utf8' ,onFileRead); function onFileRead(err, content) { if(err != null) { return safeCb(cb)(null, undefined); } var entry; try{ entry = JSON.parse(content); } catch(e){ return safeCb(cb)(e); } if(!!entry.cacheUntil && new Date().getTime() > entry.cacheUntil) { return safeCb(cb)(null, undefined); } return safeCb(cb)(null, entry.data); } } function getSync(name) { if(ram && !!memoryCache[name]) { var entry = memoryCache[name]; if(entry.cacheUntil && new Date().getTime() > entry.cacheUntil) { return undefined; } return JSON.parse(entry.data); } try { var data = JSON.parse(fs.readFileSync(buildFilePath(name), 'utf8')); } catch(e) { return undefined; } if(data.cacheUntil && new Date().getTime() > data.cacheUntil) return undefined; return data.data; } function deleteEntry(name, cb) { if(ram) { delete memoryCache[name]; if(!persist) safeCb(cb)(null); } fs.unlink(buildFilePath(name), cb); } function deleteEntrySync(name) { if(ram) { delete memoryCache[name]; if(!persist) return; } fs.unlinkSync(buildFilePath(name)); } function unlink(cb) { if(persist) return rmdir(cacheDir, safeCb(cb)); safeCb(cb)(null); } function transformFileNameToKey(fileName) { return fileName.slice(0, -5); } function keys(cb) { cb = safeCb(cb); if(ram && !persist) return cb(null, Object.keys(memoryCache)); fs.readdir(cacheDir, onDirRead); function onDirRead(err, files) { return !!err ? cb(err) : cb(err, files.map(transformFileNameToKey)); } } function keysSync() { if(ram && !persist) return Object.keys(memoryCache); return fs.readdirSync(cacheDir).map(transformFileNameToKey); } return { put: put, get: get, delete: deleteEntry, putSync: putSync, getSync: getSync, deleteSync: deleteEntrySync, keys: keys, keysSync: keysSync, unlink: unlink }; } module.exports = cache;