UNPKG

4.48 kBJavaScriptView Raw
1//
2'use strict';
3
4const path = require('path');
5const loadPackageProp = require('./loadPackageProp');
6const loadRc = require('./loadRc');
7const loadJs = require('./loadJs');
8const loadDefinedFile = require('./loadDefinedFile');
9const funcRunner = require('./funcRunner');
10const getDirectory = require('./getDirectory');
11
12module.exports = function createExplorer(options
13
14
15
16
17
18
19
20
21
22
23
24 ) {
25 // When `options.sync` is `false` (default),
26 // these cache Promises that resolve with results, not the results themselves.
27 const fileCache = options.cache ? new Map() : null;
28 const directoryCache = options.cache ? new Map() : null;
29 const transform = options.transform || identity;
30 const packageProp = options.packageProp;
31
32 function clearFileCache() {
33 if (fileCache) fileCache.clear();
34 }
35
36 function clearDirectoryCache() {
37 if (directoryCache) directoryCache.clear();
38 }
39
40 function clearCaches() {
41 clearFileCache();
42 clearDirectoryCache();
43 }
44
45 function throwError(error) {
46 if (options.sync) {
47 throw error;
48 } else {
49 return Promise.reject(error);
50 }
51 }
52
53 function load(
54 searchPath ,
55 configPath
56 ) {
57 if (!configPath && options.configPath) {
58 configPath = options.configPath;
59 }
60
61 if (configPath) {
62 const absoluteConfigPath = path.resolve(process.cwd(), configPath);
63 if (fileCache && fileCache.has(absoluteConfigPath)) {
64 return fileCache.get(absoluteConfigPath);
65 }
66
67 let load;
68 if (path.basename(absoluteConfigPath) === 'package.json') {
69 if (!packageProp) {
70 return throwError(
71 new Error(
72 'Please specify the packageProp option. The configPath argument cannot point to a package.json file if packageProp is false.'
73 )
74 );
75 }
76 load = () =>
77 loadPackageProp(path.dirname(absoluteConfigPath), {
78 packageProp,
79 sync: options.sync,
80 });
81 } else {
82 load = () =>
83 loadDefinedFile(absoluteConfigPath, {
84 sync: options.sync,
85 format: options.format,
86 });
87 }
88
89 const loadResult = load();
90 const result =
91 loadResult instanceof Promise
92 ? loadResult.then(transform)
93 : transform(loadResult);
94 if (fileCache) fileCache.set(absoluteConfigPath, result);
95 return result;
96 }
97
98 if (!searchPath) return !options.sync ? Promise.resolve(null) : null;
99
100 const absoluteSearchPath = path.resolve(process.cwd(), searchPath);
101 const searchPathDir = getDirectory(absoluteSearchPath, options.sync);
102
103 return searchPathDir instanceof Promise
104 ? searchPathDir.then(searchDirectory)
105 : searchDirectory(searchPathDir);
106 }
107
108 function searchDirectory(
109 directory
110 ) {
111 if (directoryCache && directoryCache.has(directory)) {
112 return directoryCache.get(directory);
113 }
114
115 const result = funcRunner(!options.sync ? Promise.resolve() : undefined, [
116 () => {
117 if (!packageProp) return;
118 return loadPackageProp(directory, {
119 packageProp,
120 sync: options.sync,
121 });
122 },
123 result => {
124 if (result || !options.rc) return result;
125 return loadRc(path.join(directory, options.rc), {
126 sync: options.sync,
127 rcStrictJson: options.rcStrictJson,
128 rcExtensions: options.rcExtensions,
129 });
130 },
131 result => {
132 if (result || !options.js) return result;
133 return loadJs(path.join(directory, options.js), { sync: options.sync });
134 },
135 result => {
136 if (result) return result;
137
138 const nextDirectory = path.dirname(directory);
139
140 if (nextDirectory === directory || directory === options.stopDir)
141 return null;
142
143 return searchDirectory(nextDirectory);
144 },
145 transform,
146 ]);
147
148 if (directoryCache) directoryCache.set(directory, result);
149 return result;
150 }
151
152 return {
153 load,
154 clearFileCache,
155 clearDirectoryCache,
156 clearCaches,
157 };
158};
159
160function identity(x) {
161 return x;
162}