1 | import crypto from 'crypto'
|
2 | import * as fs from 'fs-extra'
|
3 | import * as path from 'path'
|
4 | import * as xxh from 'xxhashjs'
|
5 |
|
6 | const HEXBASE = 16
|
7 |
|
8 | const defaultHashOptions = {
|
9 | method: 'xxhash32',
|
10 | shrink: 8,
|
11 | append: false
|
12 | }
|
13 |
|
14 | const getxxhash = (content, options) => {
|
15 | const hashFunc = options.method === 'xxhash32' ? xxh.h32 : xxh.h64
|
16 | const seed = 0
|
17 |
|
18 | return hashFunc(seed)
|
19 | .update(content)
|
20 | .digest()
|
21 | .toString(HEXBASE)
|
22 | }
|
23 |
|
24 | const getHash = (content, options) => {
|
25 | if (options.method && typeof options.method === 'function') {
|
26 | return options.method(content)
|
27 | }
|
28 |
|
29 | if (options.method && options.method.indexOf('xxhash') === 0) {
|
30 | return getxxhash(content, options)
|
31 | }
|
32 |
|
33 | try {
|
34 | const hashFunc = crypto.createHash(options.method)
|
35 |
|
36 | return hashFunc.update(content).digest('hex')
|
37 | } catch (e) {
|
38 | return null
|
39 | }
|
40 | }
|
41 |
|
42 | function hash (content, options) {
|
43 | options = options || defaultHashOptions
|
44 |
|
45 | let hash = getHash(content, options)
|
46 |
|
47 | if (hash == null) {
|
48 |
|
49 |
|
50 | hash = getHash(content, defaultHashOptions)
|
51 | }
|
52 |
|
53 | return options.shrink ? hash.substr(0, options.shrink) : hash
|
54 | }
|
55 |
|
56 | export default (file, options?: any) => {
|
57 | const content = fs.readFileSync(file)
|
58 | const ext = path.extname(file)
|
59 | return hash(content, options) + ext
|
60 | }
|