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