UNPKG

5.73 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;
36const readFile = promisify(fs.readFile);
37const writeFile = promisify(fs.writeFile);
38const gunzip = promisify(zlib.gunzip);
39const gzip = promisify(zlib.gzip);
40
41const makeDir = require("make-dir");
42/**
43 * Read the contents from the compressed file.
44 *
45 * @async
46 * @params {String} filename
47 * @params {Boolean} compress
48 */
49
50
51const read = /*#__PURE__*/function () {
52 var _ref = _asyncToGenerator(function* (filename, compress) {
53 const data = yield readFile(filename + (compress ? ".gz" : ""));
54 const content = compress ? yield gunzip(data) : data;
55 return JSON.parse(content.toString());
56 });
57
58 return function read(_x, _x2) {
59 return _ref.apply(this, arguments);
60 };
61}();
62/**
63 * Write contents into a compressed file.
64 *
65 * @async
66 * @params {String} filename
67 * @params {Boolean} compress
68 * @params {String} result
69 */
70
71
72const write = /*#__PURE__*/function () {
73 var _ref2 = _asyncToGenerator(function* (filename, compress, result) {
74 const content = JSON.stringify(result);
75 const data = compress ? yield gzip(content) : content;
76 return yield writeFile(filename + (compress ? ".gz" : ""), data);
77 });
78
79 return function write(_x3, _x4, _x5) {
80 return _ref2.apply(this, arguments);
81 };
82}();
83/**
84 * Build the filename for the cached file
85 *
86 * @params {String} source File source code
87 * @params {Object} options Options used
88 *
89 * @return {String}
90 */
91
92
93const filename = function (source, identifier, options) {
94 const hash = crypto.createHash("md4");
95 const contents = JSON.stringify({
96 source,
97 options,
98 identifier
99 });
100 hash.update(contents);
101 return hash.digest("hex") + ".json";
102};
103/**
104 * Handle the cache
105 *
106 * @params {String} directory
107 * @params {Object} params
108 */
109
110
111const handleCache = /*#__PURE__*/function () {
112 var _ref3 = _asyncToGenerator(function* (directory, params) {
113 const {
114 source,
115 options = {},
116 cacheIdentifier,
117 cacheDirectory,
118 cacheCompression
119 } = params;
120 const file = path.join(directory, filename(source, cacheIdentifier, options));
121
122 try {
123 // No errors mean that the file was previously cached
124 // we just need to return it
125 return yield read(file, cacheCompression);
126 } catch (err) {}
127
128 const fallback = typeof cacheDirectory !== "string" && directory !== os.tmpdir(); // Make sure the directory exists.
129
130 try {
131 yield makeDir(directory);
132 } catch (err) {
133 if (fallback) {
134 return handleCache(os.tmpdir(), params);
135 }
136
137 throw err;
138 } // Otherwise just transform the file
139 // return it to the user asap and write it in cache
140
141
142 const result = yield transform(source, options);
143
144 try {
145 yield write(file, cacheCompression, result);
146 } catch (err) {
147 if (fallback) {
148 // Fallback to tmpdir if node_modules folder not writable
149 return handleCache(os.tmpdir(), params);
150 }
151
152 throw err;
153 }
154
155 return result;
156 });
157
158 return function handleCache(_x6, _x7) {
159 return _ref3.apply(this, arguments);
160 };
161}();
162/**
163 * Retrieve file from cache, or create a new one for future reads
164 *
165 * @async
166 * @param {Object} params
167 * @param {String} params.cacheDirectory Directory to store cached files
168 * @param {String} params.cacheIdentifier Unique identifier to bust cache
169 * @param {Boolean} params.cacheCompression Whether compressing cached files
170 * @param {String} params.source Original contents of the file to be cached
171 * @param {Object} params.options Options to be given to the transform fn
172 *
173 * @example
174 *
175 * const result = await cache({
176 * cacheDirectory: '.tmp/cache',
177 * cacheIdentifier: 'babel-loader-cachefile',
178 * cacheCompression: false,
179 * source: *source code from file*,
180 * options: {
181 * experimental: true,
182 * runtime: true
183 * },
184 * });
185 */
186
187
188module.exports = /*#__PURE__*/function () {
189 var _ref4 = _asyncToGenerator(function* (params) {
190 let directory;
191
192 if (typeof params.cacheDirectory === "string") {
193 directory = params.cacheDirectory;
194 } else {
195 if (defaultCacheDirectory === null) {
196 defaultCacheDirectory = findCacheDir({
197 name: "babel-loader"
198 }) || os.tmpdir();
199 }
200
201 directory = defaultCacheDirectory;
202 }
203
204 return yield handleCache(directory, params);
205 });
206
207 return function (_x8) {
208 return _ref4.apply(this, arguments);
209 };
210}();
\No newline at end of file