'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