createExplorer.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. 'use strict';
  2. var path = require('path');
  3. var isDir = require('is-directory');
  4. var loadPackageProp = require('./loadPackageProp');
  5. var loadRc = require('./loadRc');
  6. var loadJs = require('./loadJs');
  7. var loadDefinedFile = require('./loadDefinedFile');
  8. module.exports = function (options) {
  9. // These cache Promises that resolve with results, not the results themselves
  10. var fileCache = (options.cache) ? new Map() : null;
  11. var directoryCache = (options.cache) ? new Map() : null;
  12. var transform = options.transform || identityPromise;
  13. function clearFileCache() {
  14. if (fileCache) fileCache.clear();
  15. }
  16. function clearDirectoryCache() {
  17. if (directoryCache) directoryCache.clear();
  18. }
  19. function clearCaches() {
  20. clearFileCache();
  21. clearDirectoryCache();
  22. }
  23. function load(searchPath, configPath) {
  24. if (!configPath && options.configPath) {
  25. configPath = options.configPath;
  26. }
  27. if (configPath) {
  28. var absoluteConfigPath = path.resolve(process.cwd(), configPath);
  29. if (fileCache && fileCache.has(absoluteConfigPath)) {
  30. return fileCache.get(absoluteConfigPath);
  31. }
  32. var result = loadDefinedFile(absoluteConfigPath, options)
  33. .then(transform);
  34. if (fileCache) fileCache.set(absoluteConfigPath, result);
  35. return result;
  36. }
  37. if (!searchPath) return Promise.resolve(null);
  38. var absoluteSearchPath = path.resolve(process.cwd(), searchPath);
  39. return isDirectory(absoluteSearchPath)
  40. .then(function (searchPathIsDirectory) {
  41. var directory = (searchPathIsDirectory)
  42. ? absoluteSearchPath
  43. : path.dirname(absoluteSearchPath);
  44. return searchDirectory(directory);
  45. });
  46. }
  47. function searchDirectory(directory) {
  48. if (directoryCache && directoryCache.has(directory)) {
  49. return directoryCache.get(directory);
  50. }
  51. var result = Promise.resolve()
  52. .then(function () {
  53. if (!options.packageProp) return;
  54. return loadPackageProp(directory, options);
  55. })
  56. .then(function (result) {
  57. if (result || !options.rc) return result;
  58. return loadRc(path.join(directory, options.rc), options);
  59. })
  60. .then(function (result) {
  61. if (result || !options.js) return result;
  62. return loadJs(path.join(directory, options.js));
  63. })
  64. .then(function (result) {
  65. if (result) return result;
  66. var splitPath = directory.split(path.sep);
  67. var nextDirectory = (splitPath.length > 1)
  68. ? splitPath.slice(0, -1).join(path.sep)
  69. : null;
  70. if (!nextDirectory || directory === options.stopDir) return null;
  71. return searchDirectory(nextDirectory);
  72. })
  73. .then(transform);
  74. if (directoryCache) directoryCache.set(directory, result);
  75. return result;
  76. }
  77. return {
  78. load: load,
  79. clearFileCache: clearFileCache,
  80. clearDirectoryCache: clearDirectoryCache,
  81. clearCaches: clearCaches,
  82. };
  83. };
  84. function isDirectory(filepath) {
  85. return new Promise(function (resolve, reject) {
  86. return isDir(filepath, function (err, dir) {
  87. if (err) return reject(err);
  88. return resolve(dir);
  89. });
  90. });
  91. }
  92. function identityPromise(x) {
  93. return Promise.resolve(x);
  94. }