import * as yaml from 'js-yaml' ; import * as fs from 'fs' ; import { ConfigObject , CloudConfigOptions } from './models' ; import { mergeProperties , readYamlAsDocument , parsePropertiesToObjects , logger , getSpringApplicationJsonFromEnv , getPredefinedEnvProperties } from './utils' ; import { CloudConfigOptionsSchema , BootstrapConfigSchema } from './schemas' ; import { SpringCloudConfigServiceImpl } from './services' ; import { injectable } from 'inversify' ; @ injectable ( ) export class SpringCloudConfig { private bootstrapConfig : ConfigObject ; private Config : ConfigObject | undefined ; constructor ( private readonly springCloudConfigServiceImpl ) { } param { CloudConfigOptions } options returns { Promise < ConfigObject > } private async readBootstrapConfig ( options ) { const theBootstrapPath = options . bootstrapPath !== undefined ? options . bootstrapPath : options . configPath ; let thisBootstrapConfig = mergeProperties ( [ await readYamlAsDocument ( `${ theBootstrapPath }/bootstrap.yml` , options . activeProfiles ) , getSpringApplicationJsonFromEnv ( ) , getPredefinedEnvProperties ( ) ] ) ; const { error } = BootstrapConfigSchema . validate ( thisBootstrapConfig , { allowUnknown : true } ) ; if ( error ) { throw new Error ( error . details [ 0 ] . message ) ; } thisBootstrapConfig . spring . cloud . config . profiles = options . activeProfiles ; return thisBootstrapConfig ; } param { string } appConfigPath param { string [ ] } activeProfiles returns { Promise < ConfigObject > } private async readApplicationConfig ( appConfigPath , activeProfiles ) { const applicationConfig = await readYamlAsDocument ( appConfigPath + '/application.yml' , activeProfiles ) ; const appConfigs = [ applicationConfig ] ; activeProfiles . forEach ( function ( activeProfile ) { const profileSpecificYaml = 'application-' + activeProfile + '.yml' ; const profileSpecificYamlPath = appConfigPath + '/' + profileSpecificYaml ; if ( fs . existsSync ( profileSpecificYamlPath ) ) { const propDoc = yaml . safeLoad ( fs . readFileSync ( profileSpecificYamlPath , 'utf8' ) ) ; const thisDoc = parsePropertiesToObjects ( propDoc ) ; appConfigs . push ( thisDoc ) ; } else { logger . debug ( 'Profile-specific yaml not found: ' + profileSpecificYaml ) ; } } ) ; return mergeProperties ( appConfigs ) ; } param { ConfigObject } theBootstrapConfig returns { Promise < ConfigObject > } private async readCloudConfig ( theBootstrapConfig ) { return await this . springCloudConfigServiceImpl . getConfigFromServer ( theBootstrapConfig ) ; } param { CloudConfigOptions } options returns { ConfigObject } private async readConfig ( options ) { let propertiesObjects = [ ] ; this . bootstrapConfig = await this . readBootstrapConfig ( options ) ; logger . debug ( "Using Bootstrap Config: " + JSON . stringify ( this . bootstrapConfig ) ) ; const applicationConfig = await this . readApplicationConfig ( options . configPath , options . activeProfiles ) ; logger . debug ( "Using Application Config: " + JSON . stringify ( applicationConfig ) ) ; propertiesObjects . push ( applicationConfig ) ; if ( applicationConfig . spring && applicationConfig . spring . cloud && applicationConfig . spring . cloud . config && applicationConfig . spring . cloud . config . name ) { this . bootstrapConfig . spring . cloud . config . name = applicationConfig . spring . cloud . config . name ; } const cloudConfig = await this . readCloudConfig ( this . bootstrapConfig ) ; propertiesObjects . push ( cloudConfig ) ; propertiesObjects . push ( this . bootstrapConfig ) ; this . Config = mergeProperties ( propertiesObjects ) ; logger . debug ( 'Using Config: ' + JSON . stringify ( this . Config ) ) ; return this . Config ; } param { CloudConfigOptions } options returns { ConfigObject } public async load ( options ) { const { error } = CloudConfigOptionsSchema . validate ( options ) ; if ( error !== null ) { throw new Error ( "Invalid options supplied. Please consult the documentation." ) ; } logger . level = ( options . level !== undefined ? options . level : 'info' ) ; return this . readConfig ( options ) ; } public instance ( ) { if ( this . Config === undefined ) { throw new Error ( "SpringCloudConfig hasn't been loaded yet." ) ; } return this . Config ; } }