Skip to content

Commit

Permalink
lib: add cache utility
Browse files Browse the repository at this point in the history
  • Loading branch information
joyeecheung committed May 14, 2018
1 parent 80ec407 commit 6b5223d
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ tmp
coverage.lcov
tmp-*
.eslintcache
.ncu
103 changes: 103 additions & 0 deletions lib/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use strict';

const path = require('path');
const fs = require('fs');
const { writeJson, readJson, writeFile, readFile } = require('./file');

function isAsync(fn) {
return fn[Symbol.toStringTag] === 'AsyncFunction';
}

class Cache {
constructor(dir) {
this.dir = dir || path.join(__dirname, '..', '.ncu', 'cache');
this.originals = {};
this.disabled = process.argv.includes('--enable-cache');
}

disable() {
this.disabled = true;
}

enable() {
this.disabled = false;
}

getFilename(key, ext) {
return path.join(this.dir, key) + ext;
}

has(key, ext) {
if (this.disabled) {
return false;
}

return fs.existsSync(this.getFilename(key, ext));
}

get(key, ext) {
if (!this.has(key, ext)) {
return undefined;
}
if (ext === '.json') {
return readJson(this.getFilename(key, ext));
} else {
return readFile(this.getFilename(key, ext));
}
}

write(key, ext, content) {
if (this.disabled) {
return;
}
const filename = this.getFilename(key, ext);
if (ext === '.json') {
return writeJson(filename, content);
} else {
return writeFile(filename, content);
}
}

wrapAsync(original, identity) {
const cache = this;
return async function(...args) {
const { key, ext } = identity.call(this, ...args);
const cached = cache.get(key, ext);
if (cached) {
return cached;
}
const result = await original.call(this, ...args);
cache.write(key, ext, result);
return result;
};
}

wrapNormal(original, identity) {
const cache = this;
return function(...args) {
const { key, ext } = identity.call(this, ...args);
const cached = cache.get(key, ext);
if (cached) {
return cached;
}
const result = original.call(this, ...args);
cache.write(key, ext, result);
return result;
};
}

wrap(Class, identities) {
for (let method of Object.keys(identities)) {
const original = Class.prototype[method];
const identity = identities[method];
this.originals[method] = original;
if (isAsync(original)) {
Class.prototype[method] = this.wrapAsync(original, identity);
} else {
Class.prototype[method] = this.wrapNormal(original, identity);
}
}
}
}

module.exports = Cache;

0 comments on commit 6b5223d

Please sign in to comment.