diff options
Diffstat (limited to 'node_modules/babel-loader/lib/fs-cache.js')
-rw-r--r-- | node_modules/babel-loader/lib/fs-cache.js | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/node_modules/babel-loader/lib/fs-cache.js b/node_modules/babel-loader/lib/fs-cache.js new file mode 100644 index 0000000..83cf61d --- /dev/null +++ b/node_modules/babel-loader/lib/fs-cache.js @@ -0,0 +1,180 @@ +"use strict"; + +/** + * Filesystem cache + * + * Given a file and a transform function, cache the result into files + * or retrieve the previously cached files if the given file is already known. + * + * @see https://github.com/babel/babel-loader/issues/34 + * @see https://github.com/babel/babel-loader/pull/41 + */ +var crypto = require("crypto"); +var mkdirp = require("mkdirp"); +var findCacheDir = require("find-cache-dir"); +var fs = require("fs"); +var os = require("os"); +var path = require("path"); +var zlib = require("zlib"); + +var defaultCacheDirectory = null; // Lazily instantiated when needed + +/** + * Read the contents from the compressed file. + * + * @async + * @params {String} filename + * @params {Function} callback + */ +var read = function read(filename, callback) { + return fs.readFile(filename, function (err, data) { + if (err) return callback(err); + + return zlib.gunzip(data, function (err, content) { + if (err) return callback(err); + + var result = {}; + + try { + result = JSON.parse(content); + } catch (e) { + return callback(e); + } + + return callback(null, result); + }); + }); +}; + +/** + * Write contents into a compressed file. + * + * @async + * @params {String} filename + * @params {String} result + * @params {Function} callback + */ +var write = function write(filename, result, callback) { + var content = JSON.stringify(result); + + return zlib.gzip(content, function (err, data) { + if (err) return callback(err); + + return fs.writeFile(filename, data, callback); + }); +}; + +/** + * Build the filename for the cached file + * + * @params {String} source File source code + * @params {Object} options Options used + * + * @return {String} + */ +var filename = function filename(source, identifier, options) { + var hash = crypto.createHash("md4"); + var contents = JSON.stringify({ + source: source, + options: options, + identifier: identifier + }); + + hash.update(contents); + + return hash.digest("hex") + ".json.gz"; +}; + +/** + * Handle the cache + * + * @params {String} directory + * @params {Object} params + * @params {Function} callback + */ +var handleCache = function handleCache(directory, params, callback) { + var source = params.source; + var options = params.options || {}; + var transform = params.transform; + var identifier = params.identifier; + var shouldFallback = typeof params.directory !== "string" && directory !== os.tmpdir(); + + // Make sure the directory exists. + mkdirp(directory, function (err) { + // Fallback to tmpdir if node_modules folder not writable + if (err) return shouldFallback ? handleCache(os.tmpdir(), params, callback) : callback(err); + + var file = path.join(directory, filename(source, identifier, options)); + + return read(file, function (err, content) { + var result = {}; + // No errors mean that the file was previously cached + // we just need to return it + if (!err) return callback(null, content); + + // Otherwise just transform the file + // return it to the user asap and write it in cache + try { + result = transform(source, options); + } catch (error) { + return callback(error); + } + + return write(file, result, function (err) { + // Fallback to tmpdir if node_modules folder not writable + if (err) return shouldFallback ? handleCache(os.tmpdir(), params, callback) : callback(err); + + callback(null, result); + }); + }); + }); +}; + +/** + * Retrieve file from cache, or create a new one for future reads + * + * @async + * @param {Object} params + * @param {String} params.directory Directory to store cached files + * @param {String} params.identifier Unique identifier to bust cache + * @param {String} params.source Original contents of the file to be cached + * @param {Object} params.options Options to be given to the transform fn + * @param {Function} params.transform Function that will transform the + * original file and whose result will be + * cached + * + * @param {Function<err, result>} callback + * + * @example + * + * cache({ + * directory: '.tmp/cache', + * identifier: 'babel-loader-cachefile', + * source: *source code from file*, + * options: { + * experimental: true, + * runtime: true + * }, + * transform: function(source, options) { + * var content = *do what you need with the source* + * return content; + * } + * }, function(err, result) { + * + * }); + */ + +module.exports = function (params, callback) { + var directory = void 0; + + if (typeof params.directory === "string") { + directory = params.directory; + } else { + if (defaultCacheDirectory === null) { + defaultCacheDirectory = findCacheDir({ name: "babel-loader" }) || os.tmpdir(); + } + directory = defaultCacheDirectory; + } + + handleCache(directory, params, callback); +};
\ No newline at end of file |