"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Explorer = void 0; const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const defaults_1 = require("./defaults"); const ExplorerBase_js_1 = require("./ExplorerBase.js"); const merge_1 = require("./merge"); const util_js_1 = require("./util.js"); /** * @internal */ class Explorer extends ExplorerBase_js_1.ExplorerBase { async load(filepath) { filepath = path_1.default.resolve(filepath); const load = async () => { return await this.config.transform(await this.#readConfiguration(filepath)); }; if (this.loadCache) { return await (0, util_js_1.emplace)(this.loadCache, filepath, load); } return await load(); } async search(from = '') { if (this.config.metaConfigFilePath) { this.loadingMetaConfig = true; const config = await this.load(this.config.metaConfigFilePath); this.loadingMetaConfig = false; if (config && !config.isEmpty) { return config; } } from = path_1.default.resolve(from); const dirs = this.#getDirs(from); const firstDirIter = await dirs.next(); /* istanbul ignore if -- @preserve */ if (firstDirIter.done) { // this should never happen throw new Error(`Could not find any folders to iterate through (start from ${from})`); } let currentDir = firstDirIter.value; const search = async () => { /* istanbul ignore if -- @preserve */ if (await (0, util_js_1.isDirectory)(currentDir.path)) { for (const filepath of this.getSearchPlacesForDir(currentDir, defaults_1.globalConfigSearchPlaces)) { try { const result = await this.#readConfiguration(filepath); if (result !== null && !(result.isEmpty && this.config.ignoreEmptySearchPlaces)) { return await this.config.transform(result); } } catch (error) { if (error.code === 'ENOENT' || error.code === 'EISDIR' || error.code === 'ENOTDIR' || error.code === 'EACCES') { continue; } throw error; } } } const nextDirIter = await dirs.next(); if (!nextDirIter.done) { currentDir = nextDirIter.value; if (this.searchCache) { return await (0, util_js_1.emplace)(this.searchCache, currentDir.path, search); } return await search(); } return await this.config.transform(null); }; if (this.searchCache) { return await (0, util_js_1.emplace)(this.searchCache, from, search); } return await search(); } async #readConfiguration(filepath, importStack = []) { const contents = await promises_1.default.readFile(filepath, { encoding: 'utf-8' }); return this.toCosmiconfigResult(filepath, await this.#loadConfigFileWithImports(filepath, contents, importStack)); } async #loadConfigFileWithImports(filepath, contents, importStack) { const loadedContent = await this.#loadConfiguration(filepath, contents); if (!loadedContent || !(0, merge_1.hasOwn)(loadedContent, '$import')) { return loadedContent; } const fileDirectory = path_1.default.dirname(filepath); const { $import: imports, ...ownContent } = loadedContent; const importPaths = Array.isArray(imports) ? imports : [imports]; const newImportStack = [...importStack, filepath]; this.validateImports(filepath, importPaths, newImportStack); const importedConfigs = await Promise.all(importPaths.map(async (importPath) => { const fullPath = path_1.default.resolve(fileDirectory, importPath); const result = await this.#readConfiguration(fullPath, newImportStack); return result?.config; })); return (0, merge_1.mergeAll)([...importedConfigs, ownContent], { mergeArrays: this.config.mergeImportArrays, }); } async #loadConfiguration(filepath, contents) { if (contents.trim() === '') { return; } const extension = path_1.default.extname(filepath); const loader = this.config.loaders[extension || 'noExt'] ?? this.config.loaders['default']; if (!loader) { throw new Error(`No loader specified for ${(0, ExplorerBase_js_1.getExtensionDescription)(extension)}`); } try { const loadedContents = await loader(filepath, contents); if (path_1.default.basename(filepath, extension) !== 'package') { return loadedContents; } return ((0, util_js_1.getPropertyByPath)(loadedContents, this.config.packageProp ?? this.config.moduleName) ?? null); } catch (error) { error.filepath = filepath; throw error; } } async #fileExists(path) { try { await promises_1.default.stat(path); return true; } catch (e) { return false; } } async *#getDirs(startDir) { switch (this.config.searchStrategy) { case 'none': { // only check in the passed directory (defaults to working directory) yield { path: startDir, isGlobalConfig: false }; return; } case 'project': { let currentDir = startDir; while (true) { yield { path: currentDir, isGlobalConfig: false }; for (const ext of ['json', 'yaml']) { const packageFile = path_1.default.join(currentDir, `package.${ext}`); if (await this.#fileExists(packageFile)) { break; } } const parentDir = path_1.default.dirname(currentDir); /* istanbul ignore if -- @preserve */ if (parentDir === currentDir) { // we're probably at the root of the directory structure break; } currentDir = parentDir; } return; } case 'global': { yield* this.getGlobalDirs(startDir); } } } } exports.Explorer = Explorer; //# sourceMappingURL=Explorer.js.map