liudong
2023-05-29 340f156319b863525e50e900c58e59b86ecb3d5e
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
'use strict';
const fs = require('fs');
const path = require('path');
const hasha = require('hasha');
const makeDir = require('make-dir');
const writeFileAtomic = require('write-file-atomic');
const packageHash = require('package-hash');
 
let ownHash = '';
function getOwnHash() {
    ownHash = packageHash.sync(path.join(__dirname, 'package.json'));
    return ownHash;
}
 
function wrap(opts) {
    if (!(opts.factory || opts.transform) || (opts.factory && opts.transform)) {
        throw new Error('Specify factory or transform but not both');
    }
 
    if (typeof opts.cacheDir !== 'string' && !opts.disableCache) {
        throw new Error('cacheDir must be a string');
    }
 
    let transformFn = opts.transform;
    const {factory, cacheDir, shouldTransform, disableCache, hashData, onHash} = opts;
    const cacheDirCreated = opts.createCacheDir === false;
    let created = transformFn && cacheDirCreated;
    const ext = opts.ext || '';
    const salt = opts.salt || '';
    const encoding = opts.encoding === 'buffer' ? undefined : opts.encoding || 'utf8';
 
    function transform(input, metadata, hash) {
        if (!created) {
            if (!cacheDirCreated && !disableCache) {
                makeDir.sync(cacheDir);
            }
 
            if (!transformFn) {
                transformFn = factory(cacheDir);
            }
 
            created = true;
        }
 
        return transformFn(input, metadata, hash);
    }
 
    return function (input, metadata) {
        if (shouldTransform && !shouldTransform(input, metadata)) {
            return input;
        }
 
        if (disableCache) {
            return transform(input, metadata);
        }
 
        let data = [ownHash || getOwnHash(), input];
 
        if (salt) {
            data.push(salt);
        }
 
        if (hashData) {
            data = data.concat(hashData(input, metadata));
        }
 
        const hash = hasha(data, {algorithm: 'sha256'});
        const cachedPath = path.join(cacheDir, hash + ext);
 
        if (onHash) {
            onHash(input, metadata, hash);
        }
 
        try {
            return fs.readFileSync(cachedPath, encoding);
        } catch (error) {
            const result = transform(input, metadata, hash);
            writeFileAtomic.sync(cachedPath, result, {encoding});
            return result;
        }
    };
}
 
module.exports = wrap;