UNPKG

4.44 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 (!searchPath) searchPath = process.cwd();
58 if (!configPath && options.configPath) configPath = options.configPath;
59
60 if (configPath) {
61 const absoluteConfigPath = path.resolve(process.cwd(), configPath);
62 if (fileCache && fileCache.has(absoluteConfigPath)) {
63 return fileCache.get(absoluteConfigPath);
64 }
65
66 let load;
67 if (path.basename(absoluteConfigPath) === 'package.json') {
68 if (!packageProp) {
69 return throwError(
70 new Error(
71 'Please specify the packageProp option. The configPath argument cannot point to a package.json file if packageProp is false.'
72 )
73 );
74 }
75 load = () =>
76 loadPackageProp(path.dirname(absoluteConfigPath), {
77 packageProp,
78 sync: options.sync,
79 });
80 } else {
81 load = () =>
82 loadDefinedFile(absoluteConfigPath, {
83 sync: options.sync,
84 format: options.format,
85 });
86 }
87
88 const loadResult = load();
89 const result =
90 loadResult instanceof Promise
91 ? loadResult.then(transform)
92 : transform(loadResult);
93 if (fileCache) fileCache.set(absoluteConfigPath, result);
94 return result;
95 }
96
97 const absoluteSearchPath = path.resolve(process.cwd(), searchPath);
98 const searchPathDir = getDirectory(absoluteSearchPath, options.sync);
99
100 return searchPathDir instanceof Promise
101 ? searchPathDir.then(searchDirectory)
102 : searchDirectory(searchPathDir);
103 }
104
105 function searchDirectory(
106 directory
107 ) {
108 if (directoryCache && directoryCache.has(directory)) {
109 return directoryCache.get(directory);
110 }
111
112 const result = funcRunner(!options.sync ? Promise.resolve() : undefined, [
113 () => {
114 if (!packageProp) return;
115 return loadPackageProp(directory, {
116 packageProp,
117 sync: options.sync,
118 });
119 },
120 result => {
121 if (result || !options.rc) return result;
122 return loadRc(path.join(directory, options.rc), {
123 sync: options.sync,
124 rcStrictJson: options.rcStrictJson,
125 rcExtensions: options.rcExtensions,
126 });
127 },
128 result => {
129 if (result || !options.js) return result;
130 return loadJs(path.join(directory, options.js), { sync: options.sync });
131 },
132 result => {
133 if (result) return result;
134
135 const nextDirectory = path.dirname(directory);
136
137 if (nextDirectory === directory || directory === options.stopDir)
138 return null;
139
140 return searchDirectory(nextDirectory);
141 },
142 transform,
143 ]);
144
145 if (directoryCache) directoryCache.set(directory, result);
146 return result;
147 }
148
149 return {
150 load,
151 clearFileCache,
152 clearDirectoryCache,
153 clearCaches,
154 };
155};
156
157function identity(x) {
158 return x;
159}