GT2/GT2-iOS/node_modules/xdl/build/tools/FsCache.js

147 lines
5.3 KiB
JavaScript
Raw Normal View History

2018-02-12 17:26:06 +00:00
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCacheDir = exports.Cacher = undefined;
var _fs;
function _load_fs() {
return _fs = _interopRequireDefault(require('mz/fs'));
}
var _mkdirpPromise;
function _load_mkdirpPromise() {
return _mkdirpPromise = _interopRequireDefault(require('mkdirp-promise'));
}
var _os = _interopRequireDefault(require('os'));
var _path = _interopRequireDefault(require('path'));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
/*
A Cacher is used to wrap a fallible or expensive function and to memoize its results on disk
in case it either fails or we don't need fresh results very often. It stores objects in JSON, and
parses JSON from disk when returning an object.
It's constructed with a "refresher" callback which will be called for the results, a filename to use
for the cache, and an optional TTL and boostrap file. The TTL (in milliseconds) can be used to speed
up slow calls from the cache (for example checking npm published versions can be very slow). The
bootstrap file can be used to "seed" the cache with a particular value stored in a file.
If there is a problem calling the refresher function or in performing the cache's disk I/O, errors
will be stored in variables on the class. The only times Cacher will throw an exception are if it's
not possible to create the cache directory (usually weird home directory permissions), or if getAsync()
is called but no value can be provided. The latter will only occur if the refresher fails, no cache
is available on disk (i.e. this is the first call or it has been recently cleared), and bootstrapping
was not available (either a bootstrap file wasn't provided or reading/writing failed).
See src/__tests__/tools/FsCache-test.js for usage examples.
*/
class Cacher {
constructor(refresher, filename, ttlMilliseconds, bootstrapFile) {
this.refresher = refresher;
this.filename = _path.default.join(getCacheDir(), filename);
this.ttlMilliseconds = ttlMilliseconds || 0;
this.bootstrapFile = bootstrapFile;
}
getAsync() {
var _this = this;
return _asyncToGenerator(function* () {
yield (0, (_mkdirpPromise || _load_mkdirpPromise()).default)(getCacheDir());
let mtime;
try {
const stats = yield (_fs || _load_fs()).default.stat(_this.filename);
mtime = stats.mtime;
} catch (e) {
if (_this.bootstrapFile) {
try {
const bootstrapContents = (yield (_fs || _load_fs()).default.readFile(_this.bootstrapFile)).toString();
yield (_fs || _load_fs()).default.writeFile(_this.filename, bootstrapContents, 'utf8');
} catch (e) {
// intentional no-op
}
}
mtime = new Date(1989, 10, 19);
}
let fromCache;
let failedRefresh = null;
// if mtime + ttl >= now, attempt to fetch the value, otherwise read from disk
if (new Date() - mtime > _this.ttlMilliseconds) {
try {
fromCache = yield _this.refresher();
try {
yield (_fs || _load_fs()).default.writeFile(_this.filename, JSON.stringify(fromCache), 'utf8');
} catch (e) {
_this.writeError = e;
// do nothing, if the refresh succeeded it'll be returned, if the persist failed we don't care
}
} catch (e) {
failedRefresh = e;
}
}
if (!fromCache) {
try {
fromCache = JSON.parse((yield (_fs || _load_fs()).default.readFile(_this.filename)));
} catch (e) {
_this.readError = e;
// if this fails then we've exhausted our options and it should remain null
}
}
if (fromCache) {
return fromCache;
} else {
if (failedRefresh) {
throw new Error(`Unable to perform cache refresh for ${_this.filename}: ${failedRefresh}`);
} else {
throw new Error(`Unable to read ${_this.filename}. ${_this.readError || ''}`);
}
}
})();
}
clearAsync() {
var _this2 = this;
return _asyncToGenerator(function* () {
try {
yield (_fs || _load_fs()).default.unlink(_this2.filename);
} catch (e) {
_this2.writeError = e;
}
})();
}
}
function getCacheDir() {
const homeDir = _os.default.homedir();
if (process.env.XDG_CACHE_HOME) {
return process.env.XDG_CACHE_HOME;
} else if (process.platform === 'win32') {
return _path.default.join(homeDir, 'AppData', 'Local', 'Expo');
} else if (process.platform === 'darwin') {
// too many mac users have broken permissions on their ~/.cache directory
return _path.default.join(homeDir, '.expo', 'cache');
} else {
return _path.default.join(homeDir, '.cache', 'expo');
}
}
exports.Cacher = Cacher;
exports.getCacheDir = getCacheDir;
//# sourceMappingURL=../__sourcemaps__/tools/FsCache.js.map