@@ -65,21 +65,29 @@ class ConfigLoader extends EventEmitter {
6565 if ( ! fs . existsSync ( this . cacheDir ) ) {
6666 try {
6767 fs . mkdirSync ( this . cacheDir , { recursive : true } ) ;
68+ console . log ( `Created cache directory at ${ this . cacheDir } ` ) ;
6869 return true ;
6970 } catch ( err ) {
7071 console . error ( 'Failed to create cache directory:' , err ) ;
7172 return false ;
7273 }
7374 }
75+ console . log ( `Using cache directory at ${ this . cacheDir } ` ) ;
7476 return true ;
7577 }
7678
7779 async start ( ) {
7880 const { configurationSources } = this . config ;
7981 if ( ! configurationSources ?. enabled ) {
82+ console . log ( 'Configuration sources are disabled' ) ;
8083 return ;
8184 }
8285
86+ console . log ( 'Configuration sources are enabled' ) ;
87+ console . log (
88+ `Sources: ${ JSON . stringify ( configurationSources . sources . filter ( ( s ) => s . enabled ) . map ( ( s ) => s . type ) ) } ` ,
89+ ) ;
90+
8391 // Clear any existing interval before starting a new one
8492 if ( this . reloadTimer ) {
8593 clearInterval ( this . reloadTimer ) ;
@@ -88,6 +96,9 @@ class ConfigLoader extends EventEmitter {
8896
8997 // Start periodic reload if interval is set
9098 if ( configurationSources . reloadIntervalSeconds > 0 ) {
99+ console . log (
100+ `Setting reload interval to ${ configurationSources . reloadIntervalSeconds } seconds` ,
101+ ) ;
91102 this . reloadTimer = setInterval (
92103 ( ) => this . reloadConfiguration ( ) ,
93104 configurationSources . reloadIntervalSeconds * 1000 ,
@@ -106,34 +117,63 @@ class ConfigLoader extends EventEmitter {
106117 }
107118
108119 async reloadConfiguration ( ) {
109- if ( this . isReloading ) return ;
120+ if ( this . isReloading ) {
121+ console . log ( 'Configuration reload already in progress, skipping' ) ;
122+ return ;
123+ }
110124 this . isReloading = true ;
125+ console . log ( 'Starting configuration reload' ) ;
111126
112127 try {
113128 const { configurationSources } = this . config ;
114- if ( ! configurationSources ?. enabled ) return ;
129+ if ( ! configurationSources ?. enabled ) {
130+ console . log ( 'Configuration sources are disabled, skipping reload' ) ;
131+ return ;
132+ }
133+
134+ const enabledSources = configurationSources . sources . filter ( ( source ) => source . enabled ) ;
135+ console . log ( `Found ${ enabledSources . length } enabled configuration sources` ) ;
115136
116137 const configs = await Promise . all (
117- configurationSources . sources
118- . filter ( ( source ) => source . enabled )
119- . map ( ( source ) => this . loadFromSource ( source ) ) ,
138+ enabledSources . map ( async ( source ) => {
139+ try {
140+ console . log ( `Loading configuration from ${ source . type } source` ) ;
141+ return await this . loadFromSource ( source ) ;
142+ } catch ( error ) {
143+ console . error ( `Error loading from ${ source . type } source:` , error . message ) ;
144+ return null ;
145+ }
146+ } ) ,
120147 ) ;
121148
149+ // Filter out null results from failed loads
150+ const validConfigs = configs . filter ( ( config ) => config !== null ) ;
151+
152+ if ( validConfigs . length === 0 ) {
153+ console . log ( 'No valid configurations loaded from any source' ) ;
154+ return ;
155+ }
156+
122157 // Use merge strategy based on configuration
123158 const shouldMerge = configurationSources . merge ?? true ; // Default to true for backward compatibility
159+ console . log ( `Using ${ shouldMerge ? 'merge' : 'override' } strategy for configuration` ) ;
160+
124161 const newConfig = shouldMerge
125- ? configs . reduce (
162+ ? validConfigs . reduce (
126163 ( acc , curr ) => {
127164 return this . deepMerge ( acc , curr ) ;
128165 } ,
129166 { ...this . config } ,
130167 )
131- : { ...this . config , ...configs [ configs . length - 1 ] } ; // Use last config for override
168+ : { ...this . config , ...validConfigs [ validConfigs . length - 1 ] } ; // Use last config for override
132169
133170 // Emit change event if config changed
134171 if ( JSON . stringify ( newConfig ) !== JSON . stringify ( this . config ) ) {
172+ console . log ( 'Configuration has changed, updating and emitting change event' ) ;
135173 this . config = newConfig ;
136174 this . emit ( 'configurationChanged' , this . config ) ;
175+ } else {
176+ console . log ( 'Configuration has not changed, no update needed' ) ;
137177 }
138178 } catch ( error ) {
139179 console . error ( 'Error reloading configuration:' , error ) ;
@@ -161,11 +201,13 @@ class ConfigLoader extends EventEmitter {
161201 if ( ! isValidPath ( configPath ) ) {
162202 throw new Error ( 'Invalid configuration file path' ) ;
163203 }
204+ console . log ( `Loading configuration from file: ${ configPath } ` ) ;
164205 const content = await fs . promises . readFile ( configPath , 'utf8' ) ;
165206 return JSON . parse ( content ) ;
166207 }
167208
168209 async loadFromHttp ( source ) {
210+ console . log ( `Loading configuration from HTTP: ${ source . url } ` ) ;
169211 const headers = {
170212 ...source . headers ,
171213 ...( source . auth ?. type === 'bearer' ? { Authorization : `Bearer ${ source . auth . token } ` } : { } ) ,
@@ -176,6 +218,8 @@ class ConfigLoader extends EventEmitter {
176218 }
177219
178220 async loadFromGit ( source ) {
221+ console . log ( `Loading configuration from Git: ${ source . repository } ` ) ;
222+
179223 // Validate inputs
180224 if ( ! source . repository || ! isValidGitUrl ( source . repository ) ) {
181225 throw new Error ( 'Invalid repository URL format' ) ;
@@ -191,15 +235,25 @@ class ConfigLoader extends EventEmitter {
191235 if ( ! isValidPath ( tempDir ) ) {
192236 throw new Error ( 'Invalid temporary directory path' ) ;
193237 }
238+
239+ console . log ( `Creating git cache directory at ${ tempDir } ` ) ;
194240 await fs . promises . mkdir ( tempDir , { recursive : true } ) ;
195241
196- const repoDir = path . join ( tempDir , Buffer . from ( source . repository ) . toString ( 'base64' ) ) ;
242+ // Create a safe directory name from the repository URL
243+ const repoDirName = Buffer . from ( source . repository )
244+ . toString ( 'base64' )
245+ . replace ( / [ ^ a - z A - Z 0 - 9 ] / g, '_' ) ;
246+ const repoDir = path . join ( tempDir , repoDirName ) ;
247+
197248 if ( ! isValidPath ( repoDir ) ) {
198249 throw new Error ( 'Invalid repository directory path' ) ;
199250 }
200251
252+ console . log ( `Using repository directory: ${ repoDir } ` ) ;
253+
201254 // Clone or pull repository
202255 if ( ! fs . existsSync ( repoDir ) ) {
256+ console . log ( `Cloning repository ${ source . repository } to ${ repoDir } ` ) ;
203257 const execOptions = {
204258 cwd : process . cwd ( ) ,
205259 env : {
@@ -211,23 +265,57 @@ class ConfigLoader extends EventEmitter {
211265 : { } ) ,
212266 } ,
213267 } ;
214- await execFileAsync ( 'git' , [ 'clone' , source . repository , repoDir ] , execOptions ) ;
268+
269+ try {
270+ await execFileAsync ( 'git' , [ 'clone' , source . repository , repoDir ] , execOptions ) ;
271+ console . log ( 'Repository cloned successfully' ) ;
272+ } catch ( error ) {
273+ console . error ( 'Failed to clone repository:' , error . message ) ;
274+ throw new Error ( `Failed to clone repository: ${ error . message } ` ) ;
275+ }
215276 } else {
216- await execFileAsync ( 'git' , [ 'pull' ] , { cwd : repoDir } ) ;
277+ console . log ( `Pulling latest changes from ${ source . repository } ` ) ;
278+ try {
279+ await execFileAsync ( 'git' , [ 'pull' ] , { cwd : repoDir } ) ;
280+ console . log ( 'Repository pulled successfully' ) ;
281+ } catch ( error ) {
282+ console . error ( 'Failed to pull repository:' , error . message ) ;
283+ throw new Error ( `Failed to pull repository: ${ error . message } ` ) ;
284+ }
217285 }
218286
219287 // Checkout specific branch if specified
220288 if ( source . branch ) {
221- await execFileAsync ( 'git' , [ 'checkout' , source . branch ] , { cwd : repoDir } ) ;
289+ console . log ( `Checking out branch: ${ source . branch } ` ) ;
290+ try {
291+ await execFileAsync ( 'git' , [ 'checkout' , source . branch ] , { cwd : repoDir } ) ;
292+ console . log ( `Branch ${ source . branch } checked out successfully` ) ;
293+ } catch ( error ) {
294+ console . error ( `Failed to checkout branch ${ source . branch } :` , error . message ) ;
295+ throw new Error ( `Failed to checkout branch ${ source . branch } : ${ error . message } ` ) ;
296+ }
222297 }
223298
224299 // Read and parse config file
225300 const configPath = path . join ( repoDir , source . path ) ;
226301 if ( ! isValidPath ( configPath ) ) {
227302 throw new Error ( 'Invalid configuration file path in repository' ) ;
228303 }
229- const content = await fs . promises . readFile ( configPath , 'utf8' ) ;
230- return JSON . parse ( content ) ;
304+
305+ console . log ( `Reading configuration file: ${ configPath } ` ) ;
306+ if ( ! fs . existsSync ( configPath ) ) {
307+ throw new Error ( `Configuration file not found at ${ configPath } ` ) ;
308+ }
309+
310+ try {
311+ const content = await fs . promises . readFile ( configPath , 'utf8' ) ;
312+ const config = JSON . parse ( content ) ;
313+ console . log ( 'Configuration loaded successfully from Git' ) ;
314+ return config ;
315+ } catch ( error ) {
316+ console . error ( 'Failed to read or parse configuration file:' , error . message ) ;
317+ throw new Error ( `Failed to read or parse configuration file: ${ error . message } ` ) ;
318+ }
231319 }
232320
233321 deepMerge ( target , source ) {
@@ -249,6 +337,7 @@ class ConfigLoader extends EventEmitter {
249337 }
250338}
251339
340+ // Helper function to check if a value is an object
252341function isObject ( item ) {
253342 return item && typeof item === 'object' && ! Array . isArray ( item ) ;
254343}
0 commit comments