UNPKG

7.82 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _fs = _interopRequireDefault(require("fs"));
9
10var _path = _interopRequireDefault(require("path"));
11
12function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; }
15
16const readFile = fp => new Promise((resolve, reject) => {
17 _fs.default.readFile(fp, 'utf8', (err, data) => {
18 if (err) return reject(err);
19 resolve(data);
20 });
21});
22
23const readFileSync = fp => {
24 return _fs.default.readFileSync(fp, 'utf8');
25};
26
27const pathExists = fp => new Promise(resolve => {
28 _fs.default.access(fp, err => {
29 resolve(!err);
30 });
31});
32
33const pathExistsSync = _fs.default.existsSync;
34
35class JoyCon {
36 constructor({
37 files,
38 cwd = process.cwd(),
39 stopDir,
40 packageKey,
41 parseJSON = JSON.parse
42 } = {}) {
43 this.options = {
44 files,
45 cwd,
46 stopDir,
47 packageKey,
48 parseJSON
49 };
50 this.existsCache = new Map();
51 this.loaders = new Set();
52 this.packageJsonCache = new Map();
53 }
54
55 addLoader(loader) {
56 this.loaders.add(loader);
57 return this;
58 }
59
60 recusivelyResolve(options) {
61 var _this = this;
62
63 return _asyncToGenerator(function* () {
64 if (options.cwd === options.stopDir || _path.default.basename(options.cwd) === 'node_modules') {
65 return null;
66 }
67
68 for (const filename of options.files) {
69 const file = _path.default.resolve(options.cwd, filename);
70
71 let exists = process.env.NODE_ENV !== 'test' && _this.existsCache.has(file) ? _this.existsCache.get(file) : yield pathExists(file);
72
73 if (exists && options.packageKey && _path.default.basename(file) === 'package.json') {
74 const data = require(file);
75
76 delete require.cache[file];
77 exists = Object.prototype.hasOwnProperty.call(data, options.packageKey);
78
79 if (exists) {
80 _this.packageJsonCache.set(file, data[options.packageKey]);
81 }
82 } else {
83 _this.packageJsonCache.delete(file);
84 }
85
86 _this.existsCache.set(file, exists);
87
88 if (exists) {
89 return file;
90 }
91 }
92
93 return _this.recusivelyResolve(Object.assign({}, options, {
94 cwd: _path.default.dirname(options.cwd)
95 }));
96 })();
97 }
98
99 recusivelyResolveSync(options) {
100 if (options.cwd === options.stopDir || _path.default.basename(options.cwd) === 'node_modules') {
101 return null;
102 }
103
104 for (const filename of options.files) {
105 const file = _path.default.resolve(options.cwd, filename);
106
107 let exists = process.env.NODE_ENV !== 'test' && this.existsCache.has(file) ? this.existsCache.get(file) : pathExistsSync(file);
108
109 if (exists && options.packageKey && _path.default.basename(file) === 'package.json') {
110 const data = require(file);
111
112 delete require.cache[file];
113 exists = Object.prototype.hasOwnProperty.call(data, options.packageKey);
114
115 if (exists) {
116 this.packageJsonCache.set(file, data[options.packageKey]);
117 }
118 } else {
119 this.packageJsonCache.delete(file);
120 }
121
122 this.existsCache.set(file, exists);
123
124 if (exists) {
125 return file;
126 }
127 }
128
129 return this.recusivelyResolveSync(Object.assign({}, options, {
130 cwd: _path.default.dirname(options.cwd)
131 }));
132 }
133
134 resolve(...args) {
135 var _this2 = this;
136
137 return _asyncToGenerator(function* () {
138 const options = Object.assign({}, _this2.options);
139
140 if (Object.prototype.toString.call(args[0]) === '[object Object]') {
141 Object.assign(options, args[0]);
142 } else {
143 if (args[0]) {
144 options.files = args[0];
145 }
146
147 if (args[1]) {
148 options.cwd = args[1];
149 }
150
151 if (args[2]) {
152 options.stopDir = args[2];
153 }
154 }
155
156 options.cwd = _path.default.resolve(options.cwd);
157 options.stopDir = options.stopDir ? _path.default.resolve(options.stopDir) : _path.default.parse(options.cwd).root;
158
159 if (!options.files || options.files.length === 0) {
160 throw new Error('files must be an non-empty array!');
161 }
162
163 return _this2.recusivelyResolve(options);
164 })();
165 }
166
167 resolveSync(...args) {
168 const options = Object.assign({}, this.options);
169
170 if (Object.prototype.toString.call(args[0]) === '[object Object]') {
171 Object.assign(options, args[0]);
172 } else {
173 if (args[0]) {
174 options.files = args[0];
175 }
176
177 if (args[1]) {
178 options.cwd = args[1];
179 }
180
181 if (args[2]) {
182 options.stopDir = args[2];
183 }
184 }
185
186 options.cwd = _path.default.resolve(options.cwd);
187 options.stopDir = options.stopDir ? _path.default.resolve(options.stopDir) : _path.default.parse(options.cwd).root;
188
189 if (!options.files || options.files.length === 0) {
190 throw new Error('files must be an non-empty array!');
191 }
192
193 return this.recusivelyResolveSync(options);
194 }
195
196 load(...args) {
197 var _this3 = this;
198
199 return _asyncToGenerator(function* () {
200 const filepath = yield _this3.resolve(...args);
201
202 if (filepath) {
203 const loader = _this3.findLoader(filepath);
204
205 if (loader) {
206 return {
207 path: filepath,
208 data: yield loader.load(filepath)
209 };
210 }
211
212 const extname = _path.default.extname(filepath).slice(1);
213
214 if (extname === 'js') {
215 return {
216 path: filepath,
217 data: require(filepath)
218 };
219 }
220
221 if (extname === 'json') {
222 if (_this3.packageJsonCache.has(filepath)) {
223 return {
224 path: filepath,
225 data: _this3.packageJsonCache.get(filepath)
226 };
227 }
228
229 const data = _this3.options.parseJSON((yield readFile(filepath)));
230
231 return {
232 path: filepath,
233 data
234 };
235 }
236
237 return {
238 path: filepath,
239 data: yield readFile(filepath)
240 };
241 }
242
243 return {};
244 })();
245 }
246
247 loadSync(...args) {
248 const filepath = this.resolveSync(...args);
249
250 if (filepath) {
251 const loader = this.findLoader(filepath);
252
253 if (loader) {
254 return {
255 path: filepath,
256 data: loader.loadSync(filepath)
257 };
258 }
259
260 const extname = _path.default.extname(filepath).slice(1);
261
262 if (extname === 'js') {
263 return {
264 path: filepath,
265 data: require(filepath)
266 };
267 }
268
269 if (extname === 'json') {
270 if (this.packageJsonCache.has(filepath)) {
271 return {
272 path: filepath,
273 data: this.packageJsonCache.get(filepath)
274 };
275 }
276
277 const data = this.options.parseJSON(readFileSync(filepath));
278 return {
279 path: filepath,
280 data
281 };
282 }
283
284 return {
285 path: filepath,
286 data: readFileSync(filepath)
287 };
288 }
289
290 return {};
291 }
292
293 findLoader(filepath) {
294 for (const loader of this.loaders) {
295 if (loader.test && loader.test.test(filepath)) {
296 return loader;
297 }
298 }
299
300 return null;
301 }
302
303 clearCache() {
304 this.existsCache.clear();
305 return this;
306 }
307
308}
309
310exports.default = JoyCon;
311module.exports = JoyCon;
312module.exports.default = JoyCon;
\No newline at end of file