ExplorerSync.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.ExplorerSync = void 0;
  7. const fs_1 = __importDefault(require("fs"));
  8. const path_1 = __importDefault(require("path"));
  9. const defaults_1 = require("./defaults");
  10. const ExplorerBase_js_1 = require("./ExplorerBase.js");
  11. const merge_1 = require("./merge");
  12. const util_js_1 = require("./util.js");
  13. /**
  14. * @internal
  15. */
  16. class ExplorerSync extends ExplorerBase_js_1.ExplorerBase {
  17. load(filepath) {
  18. filepath = path_1.default.resolve(filepath);
  19. const load = () => {
  20. return this.config.transform(this.#readConfiguration(filepath));
  21. };
  22. if (this.loadCache) {
  23. return (0, util_js_1.emplace)(this.loadCache, filepath, load);
  24. }
  25. return load();
  26. }
  27. search(from = '') {
  28. if (this.config.metaConfigFilePath) {
  29. this.loadingMetaConfig = true;
  30. const config = this.load(this.config.metaConfigFilePath);
  31. this.loadingMetaConfig = false;
  32. if (config && !config.isEmpty) {
  33. return config;
  34. }
  35. }
  36. from = path_1.default.resolve(from);
  37. const dirs = this.#getDirs(from);
  38. const firstDirIter = dirs.next();
  39. /* istanbul ignore if -- @preserve */
  40. if (firstDirIter.done) {
  41. // this should never happen
  42. throw new Error(`Could not find any folders to iterate through (start from ${from})`);
  43. }
  44. let currentDir = firstDirIter.value;
  45. const search = () => {
  46. /* istanbul ignore if -- @preserve */
  47. if ((0, util_js_1.isDirectorySync)(currentDir.path)) {
  48. for (const filepath of this.getSearchPlacesForDir(currentDir, defaults_1.globalConfigSearchPlacesSync)) {
  49. try {
  50. const result = this.#readConfiguration(filepath);
  51. if (result !== null &&
  52. !(result.isEmpty && this.config.ignoreEmptySearchPlaces)) {
  53. return this.config.transform(result);
  54. }
  55. }
  56. catch (error) {
  57. if (error.code === 'ENOENT' ||
  58. error.code === 'EISDIR' ||
  59. error.code === 'ENOTDIR' ||
  60. error.code === 'EACCES') {
  61. continue;
  62. }
  63. throw error;
  64. }
  65. }
  66. }
  67. const nextDirIter = dirs.next();
  68. if (!nextDirIter.done) {
  69. currentDir = nextDirIter.value;
  70. if (this.searchCache) {
  71. return (0, util_js_1.emplace)(this.searchCache, currentDir.path, search);
  72. }
  73. return search();
  74. }
  75. return this.config.transform(null);
  76. };
  77. if (this.searchCache) {
  78. return (0, util_js_1.emplace)(this.searchCache, from, search);
  79. }
  80. return search();
  81. }
  82. #readConfiguration(filepath, importStack = []) {
  83. const contents = fs_1.default.readFileSync(filepath, 'utf8');
  84. return this.toCosmiconfigResult(filepath, this.#loadConfigFileWithImports(filepath, contents, importStack));
  85. }
  86. #loadConfigFileWithImports(filepath, contents, importStack) {
  87. const loadedContent = this.#loadConfiguration(filepath, contents);
  88. if (!loadedContent || !(0, merge_1.hasOwn)(loadedContent, '$import')) {
  89. return loadedContent;
  90. }
  91. const fileDirectory = path_1.default.dirname(filepath);
  92. const { $import: imports, ...ownContent } = loadedContent;
  93. const importPaths = Array.isArray(imports) ? imports : [imports];
  94. const newImportStack = [...importStack, filepath];
  95. this.validateImports(filepath, importPaths, newImportStack);
  96. const importedConfigs = importPaths.map((importPath) => {
  97. const fullPath = path_1.default.resolve(fileDirectory, importPath);
  98. const result = this.#readConfiguration(fullPath, newImportStack);
  99. return result?.config;
  100. });
  101. return (0, merge_1.mergeAll)([...importedConfigs, ownContent], {
  102. mergeArrays: this.config.mergeImportArrays,
  103. });
  104. }
  105. #loadConfiguration(filepath, contents) {
  106. if (contents.trim() === '') {
  107. return;
  108. }
  109. const extension = path_1.default.extname(filepath);
  110. const loader = this.config.loaders[extension || 'noExt'] ??
  111. this.config.loaders['default'];
  112. if (!loader) {
  113. throw new Error(`No loader specified for ${(0, ExplorerBase_js_1.getExtensionDescription)(extension)}`);
  114. }
  115. try {
  116. const loadedContents = loader(filepath, contents);
  117. if (path_1.default.basename(filepath, extension) !== 'package') {
  118. return loadedContents;
  119. }
  120. return ((0, util_js_1.getPropertyByPath)(loadedContents, this.config.packageProp ?? this.config.moduleName) ?? null);
  121. }
  122. catch (error) {
  123. error.filepath = filepath;
  124. throw error;
  125. }
  126. }
  127. #fileExists(path) {
  128. try {
  129. fs_1.default.statSync(path);
  130. return true;
  131. }
  132. catch (e) {
  133. return false;
  134. }
  135. }
  136. *#getDirs(startDir) {
  137. switch (this.config.searchStrategy) {
  138. case 'none': {
  139. // there is no next dir
  140. yield { path: startDir, isGlobalConfig: false };
  141. return;
  142. }
  143. case 'project': {
  144. let currentDir = startDir;
  145. while (true) {
  146. yield { path: currentDir, isGlobalConfig: false };
  147. for (const ext of ['json', 'yaml']) {
  148. const packageFile = path_1.default.join(currentDir, `package.${ext}`);
  149. if (this.#fileExists(packageFile)) {
  150. break;
  151. }
  152. }
  153. const parentDir = path_1.default.dirname(currentDir);
  154. /* istanbul ignore if -- @preserve */
  155. if (parentDir === currentDir) {
  156. // we're probably at the root of the directory structure
  157. break;
  158. }
  159. currentDir = parentDir;
  160. }
  161. return;
  162. }
  163. case 'global': {
  164. yield* this.getGlobalDirs(startDir);
  165. }
  166. }
  167. }
  168. /**
  169. * @deprecated Use {@link ExplorerSync.prototype.load}.
  170. */
  171. /* istanbul ignore next */
  172. loadSync(filepath) {
  173. return this.load(filepath);
  174. }
  175. /**
  176. * @deprecated Use {@link ExplorerSync.prototype.search}.
  177. */
  178. /* istanbul ignore next */
  179. searchSync(from = '') {
  180. return this.search(from);
  181. }
  182. }
  183. exports.ExplorerSync = ExplorerSync;
  184. //# sourceMappingURL=ExplorerSync.js.map