| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 |
1
1
1
1
1
| /**
* 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'),
fs = require('fs'),
os = require('os'),
path = require('path'),
zlib = require('zlib');
/**
* read
*
* Read the contents from the compressed file.
*
* @async
* @params {String} filename
* @params {Function} callback
*/
var read = function (filename, callback) {
fs.readFile(filename, function (err, data) {
if (err) { return callback(err); }
zlib.gunzip(data, function (err, content) {
var result = {};
if (err) { return callback(err); }
try {
result = JSON.parse(content);
} catch (e) {
return callback(e);
}
return callback(null, content);
});
});
};
/**
* write
*
* Write contents into a compressed file.
*
* @async
* @params {String} filename
* @params {String} result
* @params {Function} callback
*/
var write = function (filename, result, callback) {
var content = JSON.stringify(result);
zlib.gzip(content, function (err, data) {
if (err) { return callback(err); }
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 (source, identifier, options) {
var hash = crypto.createHash('SHA1'),
contents = JSON.stringify({
source: source,
options: options,
identifier: identifier
});
hash.end(contents);
return hash.read().toString('hex') + '.json.gzip';
};
/**
* cache
*
* @async
* @param {Object} params
* @param {String} params.directory Directory where cached files will be stored
* @param {String} params.identifier Unique identifier to help with cache busting
* @param {String} params.source Original contents of the file to be cached
* @param {Object} params.options Options to be given to the transform function
* @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) {
*
* });
*/
var cache = module.exports = function (params, callback) {
// Spread params into named variables
// Forgive user whenever possible
var source = params.source,
options = params.options || {},
transform = params.transform,
identifier = params.identifier, // @TODO ensure that 'undefined' will not break
directory = (typeof params.directory === 'string') ?
params.directory :
os.tmpdir();
var file = path.join(directory, filename(source, identifier, options));
read(file, function (err, content) {
var result = {};
if (!err) { return callback(null, content); }
result = transform(source, options);
return write(file, result, function (err) {
callback(err, result);
});
});
};
|