UNPKG

28.6 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __generator = (this && this.__generator) || function (thisArg, body) {
12 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14 function verb(n) { return function (v) { return step([n, v]); }; }
15 function step(op) {
16 if (f) throw new TypeError("Generator is already executing.");
17 while (_) try {
18 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19 if (y = 0, t) op = [op[0] & 2, t.value];
20 switch (op[0]) {
21 case 0: case 1: t = op; break;
22 case 4: _.label++; return { value: op[1], done: false };
23 case 5: _.label++; y = op[1]; op = [0]; continue;
24 case 7: op = _.ops.pop(); _.trys.pop(); continue;
25 default:
26 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30 if (t[2]) _.ops.pop();
31 _.trys.pop(); continue;
32 }
33 op = body.call(thisArg, _);
34 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36 }
37};
38var __values = (this && this.__values) || function(o) {
39 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
40 if (m) return m.call(o);
41 if (o && typeof o.length === "number") return {
42 next: function () {
43 if (o && i >= o.length) o = void 0;
44 return { value: o && o[i++], done: !o };
45 }
46 };
47 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
48};
49var __read = (this && this.__read) || function (o, n) {
50 var m = typeof Symbol === "function" && o[Symbol.iterator];
51 if (!m) return o;
52 var i = m.call(o), r, ar = [], e;
53 try {
54 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
55 }
56 catch (error) { e = { error: error }; }
57 finally {
58 try {
59 if (r && !r.done && (m = i["return"])) m.call(i);
60 }
61 finally { if (e) throw e.error; }
62 }
63 return ar;
64};
65Object.defineProperty(exports, "__esModule", { value: true });
66var stream_1 = require("stream");
67var _a = require('fs-monkey/lib/util/lists'), fsAsyncMethods = _a.fsAsyncMethods, fsSyncMethods = _a.fsSyncMethods;
68var SPECIAL_METHODS = new Set([
69 "existsSync",
70 "readdir",
71 "readdirSync",
72 "createReadStream",
73 "createWriteStream",
74 "watch",
75 "watchFile",
76 "unwatchFile"
77]);
78var createFSProxy = function (watchers) { return new Proxy({}, {
79 get: function (_obj, property) {
80 var e_1, _a;
81 var funcCallers = [];
82 var prop;
83 try {
84 for (var watchers_1 = __values(watchers), watchers_1_1 = watchers_1.next(); !watchers_1_1.done; watchers_1_1 = watchers_1.next()) {
85 var watcher = watchers_1_1.value;
86 prop = watcher[property];
87 // if we're a function we wrap it in a bigger caller;
88 if (typeof prop === "function") {
89 funcCallers.push([watcher, prop]);
90 }
91 }
92 }
93 catch (e_1_1) { e_1 = { error: e_1_1 }; }
94 finally {
95 try {
96 if (watchers_1_1 && !watchers_1_1.done && (_a = watchers_1.return)) _a.call(watchers_1);
97 }
98 finally { if (e_1) throw e_1.error; }
99 }
100 if (funcCallers.length) {
101 return function () {
102 var e_2, _a;
103 var args = [];
104 for (var _i = 0; _i < arguments.length; _i++) {
105 args[_i] = arguments[_i];
106 }
107 try {
108 for (var funcCallers_1 = __values(funcCallers), funcCallers_1_1 = funcCallers_1.next(); !funcCallers_1_1.done; funcCallers_1_1 = funcCallers_1.next()) {
109 var _b = __read(funcCallers_1_1.value, 2), watcher = _b[0], func = _b[1];
110 func.apply(watcher, args);
111 }
112 }
113 catch (e_2_1) { e_2 = { error: e_2_1 }; }
114 finally {
115 try {
116 if (funcCallers_1_1 && !funcCallers_1_1.done && (_a = funcCallers_1.return)) _a.call(funcCallers_1);
117 }
118 finally { if (e_2) throw e_2.error; }
119 }
120 };
121 }
122 else {
123 return prop;
124 }
125 }
126}); };
127var fsPromisesMethods = [
128 'access',
129 'copyFile',
130 'open',
131 'opendir',
132 'rename',
133 'truncate',
134 'rmdir',
135 'mkdir',
136 'readdir',
137 'readlink',
138 'symlink',
139 'lstat',
140 'stat',
141 'link',
142 'unlink',
143 'chmod',
144 'lchmod',
145 'lchown',
146 'chown',
147 'utimes',
148 'realpath',
149 'mkdtemp',
150 'writeFile',
151 'appendFile',
152 'readFile'
153];
154/**
155 * Union object represents a stack of filesystems
156 */
157var Union = /** @class */ (function () {
158 function Union() {
159 var e_3, _a, e_4, _b, e_5, _c, e_6, _d;
160 var _this = this;
161 this.fss = [];
162 this.ReadStream = stream_1.Readable;
163 this.WriteStream = stream_1.Writable;
164 this.promises = {};
165 this.unwatchFile = function () {
166 var args = [];
167 for (var _i = 0; _i < arguments.length; _i++) {
168 args[_i] = arguments[_i];
169 }
170 throw new Error("unwatchFile is not supported, please use watchFile");
171 };
172 this.watch = function () {
173 var e_7, _a;
174 var args = [];
175 for (var _i = 0; _i < arguments.length; _i++) {
176 args[_i] = arguments[_i];
177 }
178 var watchers = [];
179 try {
180 for (var _b = __values(_this.fss), _c = _b.next(); !_c.done; _c = _b.next()) {
181 var fs = _c.value;
182 try {
183 var watcher = fs.watch.apply(fs, args);
184 watchers.push(watcher);
185 }
186 catch (e) {
187 // dunno what to do here...
188 }
189 }
190 }
191 catch (e_7_1) { e_7 = { error: e_7_1 }; }
192 finally {
193 try {
194 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
195 }
196 finally { if (e_7) throw e_7.error; }
197 }
198 // return a proxy to call functions on these props
199 return createFSProxy(watchers);
200 };
201 this.watchFile = function () {
202 var e_8, _a;
203 var args = [];
204 for (var _i = 0; _i < arguments.length; _i++) {
205 args[_i] = arguments[_i];
206 }
207 var watchers = [];
208 try {
209 for (var _b = __values(_this.fss), _c = _b.next(); !_c.done; _c = _b.next()) {
210 var fs = _c.value;
211 try {
212 var watcher = fs.watchFile.apply(fs, args);
213 watchers.push(watcher);
214 }
215 catch (e) {
216 // dunno what to do here...
217 }
218 }
219 }
220 catch (e_8_1) { e_8 = { error: e_8_1 }; }
221 finally {
222 try {
223 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
224 }
225 finally { if (e_8) throw e_8.error; }
226 }
227 // return a proxy to call functions on these props
228 return createFSProxy(watchers);
229 };
230 this.existsSync = function (path) {
231 var e_9, _a;
232 try {
233 for (var _b = __values(_this.fss), _c = _b.next(); !_c.done; _c = _b.next()) {
234 var fs = _c.value;
235 try {
236 if (fs.existsSync(path)) {
237 return true;
238 }
239 }
240 catch (e) {
241 // ignore
242 }
243 }
244 }
245 catch (e_9_1) { e_9 = { error: e_9_1 }; }
246 finally {
247 try {
248 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
249 }
250 finally { if (e_9) throw e_9.error; }
251 }
252 return false;
253 };
254 this.readdir = function () {
255 var args = [];
256 for (var _i = 0; _i < arguments.length; _i++) {
257 args[_i] = arguments[_i];
258 }
259 var lastarg = args.length - 1;
260 var cb = args[lastarg];
261 if (typeof cb !== 'function') {
262 cb = null;
263 lastarg++;
264 }
265 var lastError = null;
266 var result = new Set();
267 var iterate = function (i, error) {
268 if (i === void 0) { i = 0; }
269 if (error) {
270 error.prev = lastError;
271 lastError = error;
272 }
273 // Already tried all file systems, return the last error.
274 if (i >= _this.fss.length) { // last one
275 if (cb) {
276 cb(error || Error('No file systems attached.'));
277 }
278 ;
279 return;
280 }
281 // Replace `callback` with our intermediate function.
282 args[lastarg] = function (err, resArg) {
283 var e_10, _a;
284 if (result.size === 0 && err) {
285 return iterate(i + 1, err);
286 }
287 if (resArg) {
288 try {
289 // Convert all results to Strings to make sure that they're deduped
290 for (var resArg_1 = __values(resArg), resArg_1_1 = resArg_1.next(); !resArg_1_1.done; resArg_1_1 = resArg_1.next()) {
291 var res = resArg_1_1.value;
292 result.add(String(res));
293 }
294 }
295 catch (e_10_1) { e_10 = { error: e_10_1 }; }
296 finally {
297 try {
298 if (resArg_1_1 && !resArg_1_1.done && (_a = resArg_1.return)) _a.call(resArg_1);
299 }
300 finally { if (e_10) throw e_10.error; }
301 }
302 }
303 if (i === _this.fss.length - 1) {
304 return cb(null, Array.from(result).sort());
305 }
306 else {
307 return iterate(i + 1, error);
308 }
309 };
310 var j = _this.fss.length - i - 1;
311 var fs = _this.fss[j];
312 var func = fs.readdir;
313 if (!func)
314 iterate(i + 1, Error('Method not supported: readdir'));
315 else
316 func.apply(fs, args);
317 };
318 iterate();
319 };
320 this.readdirSync = function () {
321 var e_11, _a;
322 var args = [];
323 for (var _i = 0; _i < arguments.length; _i++) {
324 args[_i] = arguments[_i];
325 }
326 var lastError = null;
327 var result = new Set();
328 for (var i = _this.fss.length - 1; i >= 0; i--) {
329 var fs = _this.fss[i];
330 try {
331 if (!fs.readdirSync)
332 throw Error("Method not supported: \"readdirSync\" with args \"" + args + "\"");
333 try {
334 for (var _b = (e_11 = void 0, __values(fs.readdirSync.apply(fs, args))), _c = _b.next(); !_c.done; _c = _b.next()) {
335 var res = _c.value;
336 // Convert all results to Strings to make sure that they're deduped
337 result.add(String(res));
338 }
339 }
340 catch (e_11_1) { e_11 = { error: e_11_1 }; }
341 finally {
342 try {
343 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
344 }
345 finally { if (e_11) throw e_11.error; }
346 }
347 }
348 catch (err) {
349 err.prev = lastError;
350 lastError = err;
351 if (result.size === 0 && !i) { // last one
352 throw err;
353 }
354 else {
355 // Ignore error...
356 // continue;
357 }
358 }
359 }
360 return Array.from(result).sort();
361 };
362 this.readdirPromise = function () {
363 var args = [];
364 for (var _i = 0; _i < arguments.length; _i++) {
365 args[_i] = arguments[_i];
366 }
367 return __awaiter(_this, void 0, void 0, function () {
368 var lastError, result, i, fs, _a, _b, res, e_12_1, err_1;
369 var e_12, _c;
370 return __generator(this, function (_d) {
371 switch (_d.label) {
372 case 0:
373 lastError = null;
374 result = new Set();
375 i = this.fss.length - 1;
376 _d.label = 1;
377 case 1:
378 if (!(i >= 0)) return [3 /*break*/, 13];
379 fs = this.fss[i];
380 _d.label = 2;
381 case 2:
382 _d.trys.push([2, 11, , 12]);
383 if (!fs.promises || !fs.promises.readdir)
384 throw Error("Method not supported: \"readdirSync\" with args \"" + args + "\"");
385 _d.label = 3;
386 case 3:
387 _d.trys.push([3, 8, 9, 10]);
388 e_12 = void 0;
389 return [4 /*yield*/, fs.promises.readdir.apply(fs, args)];
390 case 4:
391 _a = (__values.apply(void 0, [_d.sent()])), _b = _a.next();
392 _d.label = 5;
393 case 5:
394 if (!!_b.done) return [3 /*break*/, 7];
395 res = _b.value;
396 // Convert all results to Strings to make sure that they're deduped
397 result.add(String(res));
398 _d.label = 6;
399 case 6:
400 _b = _a.next();
401 return [3 /*break*/, 5];
402 case 7: return [3 /*break*/, 10];
403 case 8:
404 e_12_1 = _d.sent();
405 e_12 = { error: e_12_1 };
406 return [3 /*break*/, 10];
407 case 9:
408 try {
409 if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
410 }
411 finally { if (e_12) throw e_12.error; }
412 return [7 /*endfinally*/];
413 case 10: return [3 /*break*/, 12];
414 case 11:
415 err_1 = _d.sent();
416 err_1.prev = lastError;
417 lastError = err_1;
418 if (result.size === 0 && !i) { // last one
419 throw err_1;
420 }
421 else {
422 // Ignore error...
423 // continue;
424 }
425 return [3 /*break*/, 12];
426 case 12:
427 i--;
428 return [3 /*break*/, 1];
429 case 13: return [2 /*return*/, Array.from(result).sort()];
430 }
431 });
432 });
433 };
434 this.createReadStream = function (path) {
435 var e_13, _a;
436 var lastError = null;
437 try {
438 for (var _b = __values(_this.fss), _c = _b.next(); !_c.done; _c = _b.next()) {
439 var fs = _c.value;
440 try {
441 if (!fs.createReadStream)
442 throw Error("Method not supported: \"createReadStream\"");
443 if (fs.existsSync && !fs.existsSync(path)) {
444 throw new Error("file \"" + path + "\" does not exists");
445 }
446 var stream = fs.createReadStream(path);
447 if (!stream) {
448 throw new Error("no valid stream");
449 }
450 _this.ReadStream = fs.ReadStream;
451 return stream;
452 }
453 catch (err) {
454 lastError = err;
455 }
456 }
457 }
458 catch (e_13_1) { e_13 = { error: e_13_1 }; }
459 finally {
460 try {
461 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
462 }
463 finally { if (e_13) throw e_13.error; }
464 }
465 throw lastError;
466 };
467 this.createWriteStream = function (path) {
468 var e_14, _a;
469 var lastError = null;
470 try {
471 for (var _b = __values(_this.fss), _c = _b.next(); !_c.done; _c = _b.next()) {
472 var fs = _c.value;
473 try {
474 if (!fs.createWriteStream)
475 throw Error("Method not supported: \"createWriteStream\"");
476 fs.statSync(path); //we simply stat first to exit early for mocked fs'es
477 //TODO which filesystem to write to?
478 var stream = fs.createWriteStream(path);
479 if (!stream) {
480 throw new Error("no valid stream");
481 }
482 _this.WriteStream = fs.WriteStream;
483 return stream;
484 }
485 catch (err) {
486 lastError = err;
487 }
488 }
489 }
490 catch (e_14_1) { e_14 = { error: e_14_1 }; }
491 finally {
492 try {
493 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
494 }
495 finally { if (e_14) throw e_14.error; }
496 }
497 throw lastError;
498 };
499 var _loop_1 = function (method) {
500 if (!SPECIAL_METHODS.has(method)) { // check we don't already have a property for this method
501 this_1[method] = function () {
502 var args = [];
503 for (var _i = 0; _i < arguments.length; _i++) {
504 args[_i] = arguments[_i];
505 }
506 return _this.syncMethod(method, args);
507 };
508 }
509 };
510 var this_1 = this;
511 try {
512 for (var fsSyncMethods_1 = __values(fsSyncMethods), fsSyncMethods_1_1 = fsSyncMethods_1.next(); !fsSyncMethods_1_1.done; fsSyncMethods_1_1 = fsSyncMethods_1.next()) {
513 var method = fsSyncMethods_1_1.value;
514 _loop_1(method);
515 }
516 }
517 catch (e_3_1) { e_3 = { error: e_3_1 }; }
518 finally {
519 try {
520 if (fsSyncMethods_1_1 && !fsSyncMethods_1_1.done && (_a = fsSyncMethods_1.return)) _a.call(fsSyncMethods_1);
521 }
522 finally { if (e_3) throw e_3.error; }
523 }
524 var _loop_2 = function (method) {
525 if (!SPECIAL_METHODS.has(method)) { // check we don't already have a property for this method
526 this_2[method] = function () {
527 var args = [];
528 for (var _i = 0; _i < arguments.length; _i++) {
529 args[_i] = arguments[_i];
530 }
531 return _this.asyncMethod(method, args);
532 };
533 }
534 };
535 var this_2 = this;
536 try {
537 for (var fsAsyncMethods_1 = __values(fsAsyncMethods), fsAsyncMethods_1_1 = fsAsyncMethods_1.next(); !fsAsyncMethods_1_1.done; fsAsyncMethods_1_1 = fsAsyncMethods_1.next()) {
538 var method = fsAsyncMethods_1_1.value;
539 _loop_2(method);
540 }
541 }
542 catch (e_4_1) { e_4 = { error: e_4_1 }; }
543 finally {
544 try {
545 if (fsAsyncMethods_1_1 && !fsAsyncMethods_1_1.done && (_b = fsAsyncMethods_1.return)) _b.call(fsAsyncMethods_1);
546 }
547 finally { if (e_4) throw e_4.error; }
548 }
549 var _loop_3 = function (method) {
550 if (method === 'readdir') {
551 this_3.promises[method] = this_3.readdirPromise;
552 return "continue";
553 }
554 this_3.promises[method] = function () {
555 var args = [];
556 for (var _i = 0; _i < arguments.length; _i++) {
557 args[_i] = arguments[_i];
558 }
559 return _this.promiseMethod(method, args);
560 };
561 };
562 var this_3 = this;
563 try {
564 for (var fsPromisesMethods_1 = __values(fsPromisesMethods), fsPromisesMethods_1_1 = fsPromisesMethods_1.next(); !fsPromisesMethods_1_1.done; fsPromisesMethods_1_1 = fsPromisesMethods_1.next()) {
565 var method = fsPromisesMethods_1_1.value;
566 _loop_3(method);
567 }
568 }
569 catch (e_5_1) { e_5 = { error: e_5_1 }; }
570 finally {
571 try {
572 if (fsPromisesMethods_1_1 && !fsPromisesMethods_1_1.done && (_c = fsPromisesMethods_1.return)) _c.call(fsPromisesMethods_1);
573 }
574 finally { if (e_5) throw e_5.error; }
575 }
576 try {
577 for (var _e = __values(SPECIAL_METHODS.values()), _f = _e.next(); !_f.done; _f = _e.next()) {
578 var method = _f.value;
579 // bind special methods to support
580 // const { method } = ufs;
581 this[method] = this[method].bind(this);
582 }
583 }
584 catch (e_6_1) { e_6 = { error: e_6_1 }; }
585 finally {
586 try {
587 if (_f && !_f.done && (_d = _e.return)) _d.call(_e);
588 }
589 finally { if (e_6) throw e_6.error; }
590 }
591 }
592 /**
593 * Adds a filesystem to the list of filesystems in the union
594 * The new filesystem object is added as the last filesystem used
595 * when searching for a file.
596 *
597 * @param fs the filesystem interface to be added to the queue of FS's
598 * @returns this instance of a unionFS
599 */
600 Union.prototype.use = function (fs) {
601 this.fss.push(fs);
602 return this;
603 };
604 Union.prototype.syncMethod = function (method, args) {
605 var lastError = null;
606 for (var i = this.fss.length - 1; i >= 0; i--) {
607 var fs = this.fss[i];
608 try {
609 if (!fs[method])
610 throw Error("Method not supported: \"" + method + "\" with args \"" + args + "\"");
611 return fs[method].apply(fs, args);
612 }
613 catch (err) {
614 err.prev = lastError;
615 lastError = err;
616 if (!i) { // last one
617 throw err;
618 }
619 else {
620 // Ignore error...
621 // continue;
622 }
623 }
624 }
625 };
626 Union.prototype.asyncMethod = function (method, args) {
627 var _this = this;
628 var lastarg = args.length - 1;
629 var cb = args[lastarg];
630 if (typeof cb !== 'function') {
631 cb = null;
632 lastarg++;
633 }
634 var lastError = null;
635 var iterate = function (i, err) {
636 if (i === void 0) { i = 0; }
637 if (err) {
638 err.prev = lastError;
639 lastError = err;
640 }
641 // Already tried all file systems, return the last error.
642 if (i >= _this.fss.length) { // last one
643 if (cb)
644 cb(err || Error('No file systems attached.'));
645 return;
646 }
647 // Replace `callback` with our intermediate function.
648 args[lastarg] = function (err) {
649 if (err)
650 return iterate(i + 1, err);
651 if (cb)
652 cb.apply(cb, arguments);
653 };
654 var j = _this.fss.length - i - 1;
655 var fs = _this.fss[j];
656 var func = fs[method];
657 if (!func)
658 iterate(i + 1, Error('Method not supported: ' + method));
659 else
660 func.apply(fs, args);
661 };
662 iterate();
663 };
664 Union.prototype.promiseMethod = function (method, args) {
665 return __awaiter(this, void 0, void 0, function () {
666 var lastError, i, theFs, promises, err_2;
667 return __generator(this, function (_a) {
668 switch (_a.label) {
669 case 0:
670 lastError = null;
671 i = this.fss.length - 1;
672 _a.label = 1;
673 case 1:
674 if (!(i >= 0)) return [3 /*break*/, 6];
675 theFs = this.fss[i];
676 promises = theFs.promises;
677 _a.label = 2;
678 case 2:
679 _a.trys.push([2, 4, , 5]);
680 if (!promises || !promises[method]) {
681 throw Error("Promise of method not supported: \"" + String(method) + "\" with args \"" + args + "\"");
682 }
683 return [4 /*yield*/, promises[method].apply(promises, args)];
684 case 3:
685 // return promises[method](...args);
686 return [2 /*return*/, _a.sent()];
687 case 4:
688 err_2 = _a.sent();
689 err_2.prev = lastError;
690 lastError = err_2;
691 if (!i) {
692 // last one
693 throw err_2;
694 }
695 else {
696 // Ignore error...
697 // continue;
698 }
699 return [3 /*break*/, 5];
700 case 5:
701 i--;
702 return [3 /*break*/, 1];
703 case 6: return [2 /*return*/];
704 }
705 });
706 });
707 };
708 return Union;
709}());
710exports.Union = Union;