3 var path = require('path');
4 var fs = require('fs');
5 var loadPackageProp = require('./loadPackageProp');
6 var loadRc = require('./loadRc');
7 var loadJs = require('./loadJs');
8 var loadDefinedFile = require('./loadDefinedFile');
10 module.exports = function (options) {
11 // These cache Promises that resolve with results, not the results themselves
12 var fileCache = (options.cache) ? new Map() : null;
13 var directoryCache = (options.cache) ? new Map() : null;
14 var transform = options.transform || identityPromise;
16 function clearFileCache() {
17 if (fileCache) fileCache.clear();
20 function clearDirectoryCache() {
21 if (directoryCache) directoryCache.clear();
24 function clearCaches() {
26 clearDirectoryCache();
29 function load(searchPath, configPath) {
31 var absoluteConfigPath = path.resolve(process.cwd(), configPath);
32 if (fileCache && fileCache.has(absoluteConfigPath)) {
33 return fileCache.get(absoluteConfigPath);
35 var result = loadDefinedFile(absoluteConfigPath, options)
37 if (fileCache) fileCache.set(absoluteConfigPath, result);
41 if (!searchPath) return Promise.resolve(null);
43 var absoluteSearchPath = path.resolve(process.cwd(), searchPath);
45 return isDirectory(absoluteSearchPath)
46 .then(function (searchPathIsDirectory) {
47 var directory = (searchPathIsDirectory)
49 : path.dirname(absoluteSearchPath);
50 return searchDirectory(directory);
54 function searchDirectory(directory) {
55 if (directoryCache && directoryCache.has(directory)) {
56 return directoryCache.get(directory);
59 var result = Promise.resolve()
61 if (!options.packageProp) return;
62 return loadPackageProp(directory, options);
64 .then(function (result) {
65 if (result || !options.rc) return result;
66 return loadRc(path.join(directory, options.rc), options);
68 .then(function (result) {
69 if (result || !options.js) return result;
70 return loadJs(path.join(directory, options.js));
72 .then(function (result) {
73 if (result) return result;
75 var splitPath = directory.split(path.sep);
76 var nextDirectory = (splitPath.length > 1)
77 ? splitPath.slice(0, -1).join(path.sep)
80 if (!nextDirectory || directory === options.stopDir) return null;
82 return searchDirectory(nextDirectory);
86 if (directoryCache) directoryCache.set(directory, result);
92 clearFileCache: clearFileCache,
93 clearDirectoryCache: clearDirectoryCache,
94 clearCaches: clearCaches,
98 function isDirectory(filepath) {
99 return new Promise(function (resolve, reject) {
100 fs.stat(filepath, function (err, stats) {
101 if (err) return reject(err);
102 return resolve(stats.isDirectory());
107 function identityPromise(x) {
108 return Promise.resolve(x);