UNPKG

3.18 kBJavaScriptView Raw
1const {fixWin32Permissions} = require('./item');
2const path = require('path');
3const FileSystem = require('./filesystem');
4const fs = require('fs');
5const bypass = require('./bypass');
6
7const createContext = ({output, options = {}, target}, newContext) =>
8 Object.assign(
9 {
10 // Assign options and set defaults if needed
11 options: {
12 recursive: options.recursive !== false,
13 lazy: options.lazy !== false
14 },
15 output,
16 target
17 },
18 newContext
19 );
20
21function addFile(context, stats, isRoot) {
22 const {output, target} = context;
23 const {lazy} = context.options;
24
25 if (!stats.isFile()) {
26 throw new Error(`${target} is not a valid file!`);
27 }
28
29 const outputPropKey = isRoot ? target : path.basename(target);
30
31 output[outputPropKey] = () => {
32 const content = !lazy ? fs.readFileSync(target) : '';
33 const file = FileSystem.file(Object.assign({}, stats, {content}))();
34
35 if (lazy) {
36 Object.defineProperty(file, '_content', {
37 get() {
38 const res = bypass(() => fs.readFileSync(target));
39 Object.defineProperty(file, '_content', {
40 value: res,
41 writable: true
42 });
43 return res;
44 },
45 set(data) {
46 Object.defineProperty(file, '_content', {
47 value: data,
48 writable: true
49 });
50 },
51 configurable: true
52 });
53 }
54
55 return file;
56 };
57
58 return output[outputPropKey];
59}
60
61function addDir(context, stats, isRoot) {
62 const {target, output} = context;
63 const {recursive} = context.options;
64
65 if (!stats.isDirectory()) {
66 throw new Error(`${target} is not a valid directory!`);
67 }
68
69 stats = Object.assign({}, stats);
70 const outputPropKey = isRoot ? target : path.basename(target);
71
72 // On windows platforms, directories do not have the executable flag, which causes FileSystem.prototype.getItem
73 // to think that the directory cannot be traversed. This is a workaround, however, a better solution may be to
74 // re-think the logic in FileSystem.prototype.getItem
75 // This workaround adds executable privileges if read privileges are found
76 stats.mode = fixWin32Permissions(stats.mode);
77
78 // Create directory factory
79 const directoryItems = {};
80 output[outputPropKey] = FileSystem.directory(
81 Object.assign(stats, {items: directoryItems})
82 );
83
84 fs.readdirSync(target).forEach(p => {
85 const absPath = path.join(target, p);
86 const stats = fs.statSync(absPath);
87 const newContext = createContext(context, {
88 target: absPath,
89 output: directoryItems
90 });
91
92 if (recursive && stats.isDirectory()) {
93 addDir(newContext, stats);
94 } else if (stats.isFile()) {
95 addFile(newContext, stats);
96 }
97 });
98
99 return output[outputPropKey];
100}
101
102/**
103 * Load directory or file from real FS
104 */
105exports.load = function(p, options) {
106 return bypass(() => {
107 p = path.resolve(p);
108
109 const stats = fs.statSync(p);
110 const context = createContext({output: {}, options, target: p});
111
112 if (stats.isDirectory()) {
113 return addDir(context, stats, true);
114 } else if (stats.isFile()) {
115 return addFile(context, stats, true);
116 }
117 });
118};