Files: 3f257b5c381aa9abc81ea117537a756a2b877e84 / utils.js
3992 bytesRaw
1 | const { PassThrough } = require('stream'); |
2 | const { stat, exists } = require('fs'); |
3 | const fs = require('fs-extra'); |
4 | const { createReadStream, createWriteStream, utimes } = require('fs'); |
5 | const { createCipher, createDecipher } = require('crypto'); |
6 | const { join } = require('path'); |
7 | const { createGzip, createGunzip } = require('zlib'); |
8 | |
9 | /** |
10 | * @function getStats |
11 | * @description Returns the directory/file stat |
12 | * @param {String} path Path to verify |
13 | * @return {Promies<Object>} Null if an error happens or the object of stat |
14 | */ |
15 | const getStats = path => |
16 | new Promise(resolve => { |
17 | return stat(path, (err, stat) => { |
18 | if (err) { |
19 | // File does not exist |
20 | return resolve(null); |
21 | } |
22 | |
23 | // Return stat |
24 | return resolve(stat); |
25 | }); |
26 | }); |
27 | |
28 | module.exports.getStats = getStats; |
29 | |
30 | /** |
31 | * @function exists |
32 | * @description Returns if a path exists |
33 | * @param {String} path Path to verify |
34 | * @return {Promise<Boolean>} Returns a boolean to indicate if path exists |
35 | */ |
36 | module.exports.exists = path => |
37 | new Promise(resolve => { |
38 | return exists(path, exists => resolve(exists)); |
39 | }); |
40 | |
41 | /** |
42 | * @function delete |
43 | * @description Deletes the path |
44 | * @param {String} path Path to delete |
45 | * @return {Promise} Resolves after deleted |
46 | */ |
47 | module.exports.delete = path => |
48 | new Promise(resolve => { |
49 | return fs.remove(path, () => resolve()); |
50 | }); |
51 | |
52 | /** |
53 | * @function copy |
54 | * @description Copies the file from the source to the target path |
55 | * @param {String} source File path to copy |
56 | * @param {String} target Path to put the file |
57 | * @param {String} crypt The cipher algorithm and key |
58 | * @param {String} decrypt The decipher algorithm and key |
59 | * @return {Promise<Object>} Resolves if was OK or rejects with the error object |
60 | */ |
61 | module.exports.copy = (source, target, crypt, decrypt) => |
62 | new Promise(async (resolve, reject) => { |
63 | const [ statSource, statTarget ] = await Promise.all([ getStats(source), getStats(target) ]); |
64 | |
65 | if (!statSource) { |
66 | return reject(new Error('Source does not exists.')); |
67 | } |
68 | |
69 | if (!statSource.isFile() || (statTarget && !statTarget.isFile())) { |
70 | return reject(new Error(`It's possible just to copy files.`)); |
71 | } |
72 | |
73 | let cryptOrDecryptFn = null; |
74 | let zipFn = null; |
75 | let unzipFn = null; |
76 | |
77 | if (crypt) { |
78 | |
79 | // Set function to crypt |
80 | cryptOrDecryptFn = createCipher(crypt.algorithm, crypt.password); |
81 | zipFn = createGzip(); |
82 | unzipFn = new PassThrough(); |
83 | } else if (decrypt) { |
84 | |
85 | // Set function to decrypt |
86 | cryptOrDecryptFn = createDecipher(decrypt.algorithm, decrypt.password); |
87 | zipFn = new PassThrough(); |
88 | unzipFn = createGunzip(); |
89 | } else { |
90 | |
91 | // Set empty stream just to pipe |
92 | cryptOrDecryptFn = new PassThrough(); |
93 | zipFn = new PassThrough(); |
94 | unzipFn = new PassThrough(); |
95 | } |
96 | |
97 | const destStream = createWriteStream(target); |
98 | destStream.on('finish', () => { |
99 | |
100 | // Change target modificate time |
101 | return utimes(target, statSource.atime, statSource.mtime, () => { |
102 | return resolve(); |
103 | }); |
104 | }); |
105 | destStream.on('error', err => reject(err)); |
106 | |
107 | // Read the file > crypt/decrypt > write to the target > resolve the promise |
108 | return createReadStream(source) |
109 | .pipe(zipFn) |
110 | .pipe(cryptOrDecryptFn) |
111 | .pipe(unzipFn) |
112 | .pipe(destStream); |
113 | }); |
114 | |
115 | /** |
116 | * @function readRecursive |
117 | * @description Reads recursivelly a path |
118 | * @param {String} source Path to copy |
119 | * @param {String} target Target path |
120 | * @return {Promise<Array<Array<String>>>} Resolves with the paths if was OK or rejects with the error object |
121 | */ |
122 | module.exports.readRecursive = (source, target) => |
123 | new Promise((resolve, reject) => { |
124 | |
125 | // Read things inside dir |
126 | return fs.readdir(source, (err, files) => { |
127 | if (err) { |
128 | return reject(err); |
129 | } |
130 | |
131 | // Return an array with new source and target |
132 | const pathsParsed = files.map(f => [ |
133 | join(source, f), |
134 | join(target, f) |
135 | ]); |
136 | }); |
137 | }); |
Built with git-ssb-web