1 | "use strict";
|
2 |
|
3 |
|
4 | module.exports = {
|
5 | findFilesByExtension,
|
6 | findFiles,
|
7 | addPrefix,
|
8 | mkdir,
|
9 | rmdir,
|
10 | file,
|
11 | isDirectory,
|
12 | isNewer,
|
13 | touch,
|
14 | size
|
15 | };
|
16 |
|
17 | const FS = require( "fs" ),
|
18 | Path = require( "path" );
|
19 |
|
20 | const BYTES_TO_KB = 0.001;
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | function findFiles( root, _filters, index = 0 ) {
|
34 | if ( !FS.existsSync( root ) ) return [];
|
35 | if ( !isDirectory( root ) ) return [];
|
36 |
|
37 | const filters = Array.isArray( _filters ) ? _filters : [_filters];
|
38 | if ( index >= filters.length ) return [];
|
39 |
|
40 | let files = [];
|
41 | if ( filters.length > index + 1 ) {
|
42 |
|
43 | const filter = filters[ index ];
|
44 | FS.readdirSync( root ).forEach(function ( filename ) {
|
45 | if ( isDirectory( Path.join( root, filename ) ) ) {
|
46 | if ( !filters || !filter || filter.test( filename ) ) {
|
47 | files = files.concat(findFiles( Path.join( root, filename ), filters, index + 1 ));
|
48 | }
|
49 | }
|
50 | });
|
51 | } else {
|
52 |
|
53 | const filter = filters[ index ];
|
54 | FS.readdirSync( root ).forEach(function ( filename ) {
|
55 | if ( isDirectory( Path.join( root, filename ) ) ) return;
|
56 | if ( !filters || !filter || filter.test( filename ) ) {
|
57 | files.push(Path.join( root, filename ));
|
58 | }
|
59 | });
|
60 | }
|
61 | return files;
|
62 | }
|
63 |
|
64 | function findFilesByExtension( root, ext ) {
|
65 | const files = [],
|
66 | fringe = [ root ];
|
67 |
|
68 | while ( fringe.length > 0 ) {
|
69 | const path = fringe.pop();
|
70 | if ( FS.existsSync( path ) ) {
|
71 | const subfiles = FS.readdirSync( path );
|
72 | for( const filename of subfiles ) {
|
73 | const f = Path.join( path, filename );
|
74 | const stat = FS.statSync( f );
|
75 | if ( !stat.isFile() ) {
|
76 | fringe.push( f );
|
77 | } else if ( filename.substr( -ext.length ) === ext ) {
|
78 | files.push( f );
|
79 | }
|
80 | }
|
81 | }
|
82 | }
|
83 | return files;
|
84 | }
|
85 |
|
86 |
|
87 | function addPrefix( path, prefix ) {
|
88 | return Path.join(
|
89 | Path.dirname( path ),
|
90 | prefix + Path.basename( path )
|
91 | ).split( Path.sep ).join( "/" );
|
92 | }
|
93 |
|
94 | function isDirectory( path ) {
|
95 | if ( !FS.existsSync( path ) ) return false;
|
96 | const stat = FS.statSync( path );
|
97 | return stat.isDirectory();
|
98 | }
|
99 |
|
100 | function mkdir( ...pathes ) {
|
101 | const path = Path.resolve( ...pathes );
|
102 | let curPath = "";
|
103 | const items = path.replace( /\\/gu, '/' ).split( "/" );
|
104 | for ( let i = 0; i < items.length; i++ ) {
|
105 | const item = items[ i ];
|
106 | curPath += `${item}/`;
|
107 | if ( FS.existsSync( curPath ) ) {
|
108 | const stat = FS.statSync( curPath );
|
109 | if ( !stat.isDirectory() ) {
|
110 | break;
|
111 | }
|
112 | } else {
|
113 | try {
|
114 | if ( curPath !== '.' ) {
|
115 | FS.mkdirSync( curPath );
|
116 | }
|
117 | } catch ( ex ) {
|
118 | throw Error(`Unable to create directory "${curPath}"!\n${ex}`);
|
119 | }
|
120 | }
|
121 | }
|
122 | return path;
|
123 | }
|
124 |
|
125 | function rmdir( path ) {
|
126 | if ( !FS.existsSync( path ) ) return false;
|
127 | const stat = FS.statSync( path );
|
128 | if ( stat.isDirectory() ) {
|
129 | FS.readdirSync( path ).forEach(function ( filename ) {
|
130 | const fullpath = Path.join( path, filename );
|
131 | try {
|
132 | rmdir( fullpath );
|
133 | } catch ( ex ) {
|
134 | console.error( `Unable to remove directory "${fullpath.redBG.white}"!` );
|
135 | console.error( String(ex).red );
|
136 | }
|
137 | });
|
138 | try {
|
139 | FS.rmdirSync( path );
|
140 | } catch ( err ) {
|
141 | console.error( `Unable to remove directory '${path}'!` );
|
142 | console.error( err );
|
143 | }
|
144 | } else {
|
145 | try {
|
146 | FS.unlinkSync( path );
|
147 | } catch ( err ) {
|
148 | console.error( `Unable to delete file '${path}'!` );
|
149 | console.error( err );
|
150 | }
|
151 | }
|
152 | return true;
|
153 | }
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | function file( path, content ) {
|
169 | try {
|
170 | if ( typeof content === 'undefined' ) {
|
171 | if ( !FS.existsSync( path ) ) return null;
|
172 | return FS.readFileSync( path );
|
173 | }
|
174 | const dir = Path.dirname( path );
|
175 | mkdir( dir );
|
176 | FS.writeFileSync( path, content );
|
177 | return content;
|
178 | } catch ( ex ) {
|
179 | console.warn( "content:", content );
|
180 | throw new Error( `${ex}\n...in pathutils/file("${path}", ${typeof content})` );
|
181 | }
|
182 | }
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | function isNewer( sourcePath, referencePath ) {
|
192 | if ( !FS.existsSync( referencePath ) ) return true;
|
193 | if ( !FS.existsSync( sourcePath ) ) return false;
|
194 | const statSrc = FS.statSync( sourcePath );
|
195 | const statRef = FS.statSync( referencePath );
|
196 | const timeSrc = statSrc.mtime.getTime();
|
197 | const timeRef = statRef.mtime.getTime();
|
198 | return timeSrc > timeRef;
|
199 | }
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 | function touch( path ) {
|
208 | if ( FS.existsSync( path ) ) {
|
209 | const content = FS.readFileSync( path );
|
210 | FS.writeFileSync( path, content );
|
211 | console.log( `File has been touched: ${path.yellow} (${(size(path) * BYTES_TO_KB).toFixed(1)} kb)` );
|
212 | return true;
|
213 | }
|
214 | return false;
|
215 | }
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 | function size( path ) {
|
223 | if( !FS.existsSync( path ) ) return 0;
|
224 |
|
225 | const stat = FS.statSync( path );
|
226 | return stat.size;
|
227 | }
|