1 | const FileSystem = require('fs');
|
2 | const Path = require('path');
|
3 | const Util = require('util');
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | function promisify(nodeFunction) {
|
13 | return function(...args) {
|
14 | return new Promise((resolve, reject) => {
|
15 | nodeFunction(...args, function(err, data) {
|
16 | if(err) {
|
17 | reject(err);
|
18 | } else {
|
19 | resolve(data);
|
20 | }
|
21 | })
|
22 | });
|
23 | };
|
24 | }
|
25 |
|
26 | const readDirAsync = promisify(FileSystem.readdir);
|
27 | const readDir = path => readDirAsync(path).then(entries => entries.map(e => Path.join(path, e)));
|
28 | const fileStat = promisify(FileSystem.stat);
|
29 | const fileAccess = promisify(FileSystem.access);
|
30 | const fileExists = file => fileAccess(file, FileSystem.F_OK);
|
31 | const readFile = promisify(FileSystem.readFile);
|
32 | const readText = file => readFile(file, {encoding: 'utf8'});
|
33 |
|
34 | async function filterAsync(array, callback) {
|
35 | let results = await Promise.all(array.map(callback));
|
36 | return array.filter((_,i) => results[i]);
|
37 | }
|
38 |
|
39 | function getFiles(dir) {
|
40 | return readDir(dir).then(entries => filterAsync(entries, e => fileStat(e).then(s => s.isFile())));
|
41 | }
|
42 |
|
43 |
|
44 | function readDirR(dir) {
|
45 | return FileSystem.statSync(dir).isDirectory()
|
46 | ? Array.prototype.concat(...FileSystem.readdirSync(dir).map(f => readDirR(Path.join(dir, f))))
|
47 | : dir;
|
48 | }
|
49 |
|
50 |
|
51 | function copyFile(source, target) {
|
52 | return new Promise((resolve,reject) => {
|
53 | const rd = FileSystem.createReadStream(source);
|
54 | rd.on('error', err => reject(err));
|
55 | const wr = FileSystem.createWriteStream(target);
|
56 | wr.on('error', err => reject(err));
|
57 | wr.on('close', () => resolve());
|
58 | rd.pipe(wr);
|
59 | });
|
60 | }
|
61 |
|
62 |
|
63 | function format(...args) {
|
64 | if(args.length === 1 && Object.prototype.toString.call(args[0]) === '[object String]') {
|
65 | return args[0];
|
66 | }
|
67 | return args.map(o => Util.inspect(o, {colors: true, depth: 3, showHidden: false})).join(' ');
|
68 | }
|
69 |
|
70 | function log(...args) {
|
71 | return console.log(format(...args));
|
72 | }
|
73 |
|
74 | function splice(str, index, count, add) {
|
75 |
|
76 | if (index < 0) {
|
77 | index = str.length + index;
|
78 | if (index < 0) {
|
79 | index = 0;
|
80 | }
|
81 | }
|
82 |
|
83 | return str.slice(0, index) + (add || "") + str.slice(index + count);
|
84 | }
|
85 |
|
86 | function mapToObject(array, callback) {
|
87 | let result = Object.create(null);
|
88 | for(let i = 0; i<array.length; ++i) {
|
89 | let pair = callback(array[i], i);
|
90 | result[pair[0]] = pair[1];
|
91 | }
|
92 | return result;
|
93 | }
|
94 |
|
95 | function isObject(obj) {
|
96 | return obj !== null && typeof obj === 'object';
|
97 | }
|
98 |
|
99 |
|
100 | function isPlainObject(obj) {
|
101 | return isObject(obj) && (
|
102 | obj.constructor === Object
|
103 | || obj.constructor === undefined
|
104 | );
|
105 | }
|
106 |
|
107 | function mergeDeep(target, ...sources) {
|
108 | if (!sources.length) return target;
|
109 | const source = sources.shift();
|
110 |
|
111 | if(Array.isArray(target)) {
|
112 | if(Array.isArray(source)) {
|
113 | target.push(...source);
|
114 | } else {
|
115 | target.push(source);
|
116 | }
|
117 | } else if(isPlainObject(target)) {
|
118 | if(isPlainObject(source)) {
|
119 | for(let key of Object.keys(source)) {
|
120 | if(!target[key]) {
|
121 | target[key] = source[key];
|
122 | } else {
|
123 | mergeDeep(target[key], source[key]);
|
124 | }
|
125 | }
|
126 | } else {
|
127 | throw new Error(`Cannot merge object with non-object`);
|
128 | }
|
129 | } else {
|
130 | target = source;
|
131 | }
|
132 |
|
133 | return mergeDeep(target, ...sources);
|
134 | }
|
135 |
|
136 | function forAll(array, callback) {
|
137 | return Promise.all(array.map(callback));
|
138 | }
|
139 |
|
140 | Object.assign(exports, {readDir, fileStat, fileAccess, fileExists, promisify, mergeDeep, mapToObject, splice, log, copyFile, getFiles, readDirR, readText, forAll}); |
\ | No newline at end of file |