UNPKG

4.89 kBJavaScriptView Raw
1var _classes = {
2 fs : require("fs"),
3 path : require("path")
4};
5
6/**
7 * @typedef {Object} fsizeOptions
8 * @property {Boolean} [symbolicLinks=true] detect symbolic links or treat them as files. Default value is `true`
9 * @property {Boolean} [skipErrors=false] skip errors and return them as an array in callback or interrupt execution on first error. Default value is `false`
10 * @property {Boolean} [logErrors=false] log detected errors in console. Default value is `false`
11 * @property {Boolean} [countFolders=true] count size of folders inodes. Default value is `true`
12 * @property {Boolean} [countSymbolicLinks=true] count size of symbolic link inodes. Default value is `true`
13 * @property {import('fs')} [fs] user specific file system
14 */
15
16/**
17 * calculate size of a file or directory
18 * @param {String} path path of the file or folder
19 * @param {fsizeOptions} opts additional options
20 * @param {function(Error|Error[], Number):void} callback function that is called when size is calculated
21 */
22var fsize = function(path, opts, callback) {
23 var fs;
24 var separator = _classes.path.sep;
25
26 if (typeof(opts) === "function") {
27 callback = opts;
28 opts = {};
29 }
30
31 if (typeof(opts) !== "object") {
32 opts = {};
33 }
34
35 if (typeof(opts.symbolicLinks) === "undefined") {
36 opts.symbolicLinks = true;
37 }
38
39 if (typeof(opts.skipErrors) === "undefined") {
40 opts.skipErrors = false;
41 }
42
43 if (typeof(opts.logErrors) === "undefined") {
44 opts.logErrors = false;
45 }
46
47 if (typeof(opts.countFolders) === "undefined") {
48 opts.countFolders = true;
49 }
50 if (typeof(opts.countSymbolicLinks) === "undefined") {
51 opts.countSymbolicLinks = true;
52 }
53
54 if (!fs)
55 fs = opts.fs || _classes.fs;
56
57 var count = 0;
58 var wait = 0;
59 var size = 0;
60 var errors = [];
61 var errorsSend = false;
62 var _next = function (path) {
63 if (errors.length && !opts.skipErrors) {
64 if (!errorsSend) {
65 errorsSend = true;
66 callback((opts.logErrors ? errors : errors[0]), size);
67 }
68 return;
69 }
70 if (path) {
71 wait++;
72 fs[opts.symbolicLinks ? 'lstat' : 'stat'](path, function(err, stats) {
73 if (err) {
74 if (opts.logErrors || !errors.length) {
75 errors.push(err);
76 }
77 count++;
78 _next();
79 } else if (!stats.isDirectory() || stats.isSymbolicLink()) {
80 if (opts.countSymbolicLinks || !stats.isSymbolicLink()) {
81 size += stats.size;
82 }
83 count++;
84 _next();
85 } else {
86 if (opts.countFolders) {
87 size += stats.size;
88 }
89 fs.readdir(path, function(err, files) {
90 if(err) {
91 if (opts.logErrors || !errors.length) {
92 errors.push(err);
93 }
94 } else {
95 files.forEach(function (file) {
96 _next(path + separator + file);
97 });
98 }
99 count++;
100 _next();
101 });
102 }
103 });
104 }
105 if (count === wait) {
106 callback((opts.logErrors ? errors : errors[0]), size);
107 }
108 };
109 _next(path);
110};
111
112
113/**
114 * calculate size of a file or directory synchronously
115 * @param {String} path path of the file or folder
116 * @param {fsizeOptions} opts additional options
117 * @returns {Number}
118 */
119var fsizeSync = function(path, opts) {
120 var fs;
121 var separator = _classes.path.sep;
122
123 if (typeof(opts) === "function") {
124 callback = opts;
125 opts = {};
126 }
127
128 if (typeof(opts) !== "object") {
129 opts = {};
130 }
131
132 if (typeof(opts.symbolicLinks) === "undefined") {
133 opts.symbolicLinks = true;
134 }
135
136 if (typeof(opts.skipErrors) === "undefined") {
137 opts.skipErrors = false;
138 }
139
140 if (typeof(opts.logErrors) === "undefined") {
141 opts.logErrors = false;
142 }
143
144 if (typeof(opts.countFolders) === "undefined") {
145 opts.countFolders = true;
146 }
147 if (typeof(opts.countSymbolicLinks) === "undefined") {
148 opts.countSymbolicLinks = true;
149 }
150
151 if (!fs)
152 fs = opts.fs || _classes.fs;
153
154 var size = 0;
155 var errors = [];
156 var errorsSend = false;
157 var _next = function (path) {
158 if (errors.length && !opts.skipErrors) {
159 throw(errors[0]);
160 }
161 if (path) {
162 var er, err;
163 var stats;
164 try {
165 stats = fs[opts.symbolicLinks ? 'lstatSync' : 'statSync'](path);
166 } catch (er) {
167 err = er;
168 };
169
170 if (err) {
171 if (opts.logErrors || !errors.length) {
172 errors.push(err);
173 _next();
174 }
175 } else if (!stats.isDirectory() || stats.isSymbolicLink()) {
176 if (opts.countSymbolicLinks || !stats.isSymbolicLink()) {
177 size += stats.size;
178 }
179 } else {
180 if (opts.countFolders) {
181 size += stats.size;
182 }
183 err = undefined;
184 er = undefined;
185 var files;
186 try {
187 files = fs.readdirSync(path);
188 } catch (er) {
189 err = er;
190 };
191 if(err) {
192 if (opts.logErrors || !errors.length) {
193 errors.push(err);
194 _next();
195 }
196 } else {
197 if (Array.isArray(files)) {
198 files.forEach(function (file) {
199 _next(path + separator + file);
200 });
201 }
202 }
203 }
204 }
205 };
206 _next(path);
207
208 opts.errors = errors;
209
210 return size;
211};
212
213
214fsize.fsize = fsize;
215fsize.sync = fsizeSync;
216
217module.exports = fsize;
\No newline at end of file