import * as fs from 'fs' ; import * as path from 'path' ; import ConfigSet from '../types/ConfigSet' ; import getOptions from './getOptions' ; import loadConfig from './loadConfig' ; import { getConfigPathCandidatesForFile } from './getConfigPathCandidatesForFile' ; import NormalizedPath from '../types/NormalizedPath' ; class ConfigManager { private fullConfigSet : ConfigSet = null ; private partialDiscoveredConfigs : ConfigSet = { } ; private discoveredPaths : Set < string > = new Set ( ) ; public getAllConfigs ( ) { if ( this . fullConfigSet === null ) { this . _getAllConfigs ( ) ; } return this . fullConfigSet ; } public getPartialConfigSetForPath ( configSourcePath ) { const partialSet = { } ; const configCandidatesForFile = getConfigPathCandidatesForFile ( configSourcePath ) ; if ( this . fullConfigSet ) { for ( let configPathCandidate of configCandidatesForFile ) { if ( this . fullConfigSet [ configPathCandidate ] ) { partialSet [ configPathCandidate ] = this . fullConfigSet [ configPathCandidate ] ; } } } else { for ( let configPathCandidate of configCandidatesForFile ) { const configPathCandidateFull = path . join ( configPathCandidate , 'fence.json' ) ; if ( this . discoveredPaths . has ( configPathCandidateFull ) ) { const discoveredConfig = this . partialDiscoveredConfigs [ configPathCandidate ] ; if ( discoveredConfig ) { partialSet [ configPathCandidateFull ] = discoveredConfig ; } } else { try { const stat = fs . statSync ( configPathCandidateFull ) ; if ( stat ?. isFile ( ) ) { loadConfig ( configPathCandidateFull , partialSet ) ; } } catch { } this . discoveredPaths . add ( configPathCandidateFull ) ; } } Object . assign ( this . partialDiscoveredConfigs , partialSet ) ; } return partialSet ; } private _getAllConfigs ( ) { this . fullConfigSet = { } ; let files = [ ] ; for ( let rootDir of getOptions ( ) . rootDir ) { accumulateFences ( rootDir , files , getOptions ( ) . ignoreExternalFences ) ; } files . forEach ( file => { loadConfig ( file , this . fullConfigSet ) ; } ) ; } } let configManager = null ; export default function getConfigManager ( ) { if ( ! configManager ) { configManager = new ConfigManager ( ) ; } return configManager ; } function accumulateFences ( dir , files , ignoreExternalFences ) { const directoryEntries = fs . readdirSync ( dir , { withFileTypes : true } ) ; for ( const directoryEntry of directoryEntries ) { const fullPath = path . join ( dir , directoryEntry . name ) ; if ( directoryEntry . name == 'fence.json' ) { files . push ( fullPath ) ; } else if ( directoryEntry . isDirectory ( ) && ! ( ignoreExternalFences && directoryEntry . name == 'node_modules' ) ) { accumulateFences ( fullPath , files , ignoreExternalFences ) ; } } }