UNPKG

5.88 kBJavaScriptView Raw
1"use strict";
2
3function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
5function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
6
7/**
8 * Filesystem Cache
9 *
10 * Given a file and a transform function, cache the result into files
11 * or retrieve the previously cached files if the given file is already known.
12 *
13 * @see https://github.com/babel/babel-loader/issues/34
14 * @see https://github.com/babel/babel-loader/pull/41
15 */
16const fs = require("fs");
17
18const os = require("os");
19
20const path = require("path");
21
22const zlib = require("zlib");
23
24const crypto = require("crypto");
25
26const findCacheDir = require("find-cache-dir");
27
28const {
29 promisify
30} = require("util");
31
32const transform = require("./transform"); // Lazily instantiated when needed
33
34
35let defaultCacheDirectory = null;
36let hashType = "md4"; // use md5 hashing if md4 is not available
37
38try {
39 crypto.createHash(hashType);
40} catch (err) {
41 hashType = "md5";
42}
43
44const readFile = promisify(fs.readFile);
45const writeFile = promisify(fs.writeFile);
46const gunzip = promisify(zlib.gunzip);
47const gzip = promisify(zlib.gzip);
48
49const makeDir = require("make-dir");
50/**
51 * Read the contents from the compressed file.
52 *
53 * @async
54 * @params {String} filename
55 * @params {Boolean} compress
56 */
57
58
59const read = /*#__PURE__*/function () {
60 var _ref = _asyncToGenerator(function* (filename, compress) {
61 const data = yield readFile(filename + (compress ? ".gz" : ""));
62 const content = compress ? yield gunzip(data) : data;
63 return JSON.parse(content.toString());
64 });
65
66 return function read(_x, _x2) {
67 return _ref.apply(this, arguments);
68 };
69}();
70/**
71 * Write contents into a compressed file.
72 *
73 * @async
74 * @params {String} filename
75 * @params {Boolean} compress
76 * @params {String} result
77 */
78
79
80const write = /*#__PURE__*/function () {
81 var _ref2 = _asyncToGenerator(function* (filename, compress, result) {
82 const content = JSON.stringify(result);
83 const data = compress ? yield gzip(content) : content;
84 return yield writeFile(filename + (compress ? ".gz" : ""), data);
85 });
86
87 return function write(_x3, _x4, _x5) {
88 return _ref2.apply(this, arguments);
89 };
90}();
91/**
92 * Build the filename for the cached file
93 *
94 * @params {String} source File source code
95 * @params {Object} options Options used
96 *
97 * @return {String}
98 */
99
100
101const filename = function (source, identifier, options) {
102 const hash = crypto.createHash(hashType);
103 const contents = JSON.stringify({
104 source,
105 options,
106 identifier
107 });
108 hash.update(contents);
109 return hash.digest("hex") + ".json";
110};
111/**
112 * Handle the cache
113 *
114 * @params {String} directory
115 * @params {Object} params
116 */
117
118
119const handleCache = /*#__PURE__*/function () {
120 var _ref3 = _asyncToGenerator(function* (directory, params) {
121 const {
122 source,
123 options = {},
124 cacheIdentifier,
125 cacheDirectory,
126 cacheCompression
127 } = params;
128 const file = path.join(directory, filename(source, cacheIdentifier, options));
129
130 try {
131 // No errors mean that the file was previously cached
132 // we just need to return it
133 return yield read(file, cacheCompression);
134 } catch (err) {}
135
136 const fallback = typeof cacheDirectory !== "string" && directory !== os.tmpdir(); // Make sure the directory exists.
137
138 try {
139 yield makeDir(directory);
140 } catch (err) {
141 if (fallback) {
142 return handleCache(os.tmpdir(), params);
143 }
144
145 throw err;
146 } // Otherwise just transform the file
147 // return it to the user asap and write it in cache
148
149
150 const result = yield transform(source, options);
151
152 try {
153 yield write(file, cacheCompression, result);
154 } catch (err) {
155 if (fallback) {
156 // Fallback to tmpdir if node_modules folder not writable
157 return handleCache(os.tmpdir(), params);
158 }
159
160 throw err;
161 }
162
163 return result;
164 });
165
166 return function handleCache(_x6, _x7) {
167 return _ref3.apply(this, arguments);
168 };
169}();
170/**
171 * Retrieve file from cache, or create a new one for future reads
172 *
173 * @async
174 * @param {Object} params
175 * @param {String} params.cacheDirectory Directory to store cached files
176 * @param {String} params.cacheIdentifier Unique identifier to bust cache
177 * @param {Boolean} params.cacheCompression Whether compressing cached files
178 * @param {String} params.source Original contents of the file to be cached
179 * @param {Object} params.options Options to be given to the transform fn
180 *
181 * @example
182 *
183 * const result = await cache({
184 * cacheDirectory: '.tmp/cache',
185 * cacheIdentifier: 'babel-loader-cachefile',
186 * cacheCompression: false,
187 * source: *source code from file*,
188 * options: {
189 * experimental: true,
190 * runtime: true
191 * },
192 * });
193 */
194
195
196module.exports = /*#__PURE__*/function () {
197 var _ref4 = _asyncToGenerator(function* (params) {
198 let directory;
199
200 if (typeof params.cacheDirectory === "string") {
201 directory = params.cacheDirectory;
202 } else {
203 if (defaultCacheDirectory === null) {
204 defaultCacheDirectory = findCacheDir({
205 name: "babel-loader"
206 }) || os.tmpdir();
207 }
208
209 directory = defaultCacheDirectory;
210 }
211
212 return yield handleCache(directory, params);
213 });
214
215 return function (_x8) {
216 return _ref4.apply(this, arguments);
217 };
218}();
\No newline at end of file