# Augment configuration factories

# Caching configuration

If you want to reload the configuration for each request coming you will slow your application. To solve that issue you can use a ComposedConfigurationFactory implementation:

import {fromLoadable, loaders, parsers, validators, createEncapsulationBuilder, TimeInterval, cacheConfigurationFactory} from '@configuration-parsing/core'

const factory = 
    fromLoadable(loaders.file())
        .parsingWith(parsers.json())
        .validatingWith(validators.empty())

const cachedFactory = createEncapsulationBuilder(factory)
    .encapsulate(cacheConfigurationFactory({
        reloadEvery: TimeInterval.minutes(2).and(TimeInterval.seconds(30))
    }))
    .build()

const configuration = await cachedFactory.create({ 
    location: 'my-config.json' 
})

# Adapt loader options

Sometimes you want to simplify your factory loader options. To do so, you can use mapLoaderOptions with a mapping function. For example, you can transform a value representing your current env (prod, dev) into a file path.

import {fromLoadable, loaders, parsers, validators, createEncapsulationBuilder, TimeInterval, mapLoaderOptions, FileLoaderOptions} from '@configuration-parsing/core'
import {joiConfigurationValidator} from '@configuration-parsing/validator-joi'

type Configuration = { foo: string }

export const customerConfigurationFactory =
    createEncapsulationBuilder(
        fromLoadable<Configuration, FileLoaderOptions>(loaders.file())
            .parsingWith(parsers.json())
            .validatingWith(validators.empty()
        )
    )
        .encapsulate(mapLoaderOptions(options => ({ fileLocation: `config/${options}.json` })))
        .build()

// will load `config/dev.json`
const configuration = await customerConfigurationFactory.create('dev')

# Adapt configuration factories results

As you can map the loader options, you can also map the factory result. By using mapConfigurationFactoryResult for example transform a config object into an uri.

import {fromLoadable, loaders, parsers, validators, createEncapsulationBuilder, TimeInterval, mapConfigurationFactoryResult, FileLoaderOptions} from '@configuration-parsing/core'

type DatabaseConfiguration = {
    host: string,
    user: string,
    password: string,
    port: string
}

export const databaseUriFactory =
    createEncapsulationBuilder(
        fromLoadable<DatabaseConfiguration, FileLoaderOptions>(loaders.file())
            .parsingWith(parsers.json())
            .validatingWith(validators.empty())
    )
        .encapsulate(mapConfigurationFactoryResult(configuration => `my-db://${configuration.user}:${configuration.password}@${configuration.host}:${configuration.port}`))
        .build()

const uri = await databaseUriFactory.create({ fileLocation: 'config/my-db.json' })

# Merge multiples configuration factories

You can merge configuration coming from multiples sources. You can use a MergeBuilder implementation to do so.

import {fromLoadable, loaders, parsers, validators, FileLoaderOptions, createMergeBuilder} from '@configuration-parsing/core'

type CacheConfiguration = {
    expiresAfter: number,
    fileLocation: string
}

type AuthConfiguration = {
    login: string
    password: string
    serviceUrl: string
}

const cacheConfigurationFactory = fromLoadable(loaders.file())
    .parsingWith(parsers.json())
    .validatingWith(validators.empty())

const authConfigurationFactory = fromLoadable(loaders.file())
    .parsingWith(parsers.json())
    .validatingWith(validators.empty())

const mergedConfigurationFactory = createMergeBuilder()
    .merge(authConfigurationFactory, {
        mapConfiguration: config => ({ auth: config }),
        mapLoader: (options: { auth: FileLoaderOptions }) => options.auth
    })
    .merge(cacheConfigurationFactory, {
        mapConfiguration: config => ({ cache: config }),
        mapLoader: (options: { cache: FileLoaderOptions }) => options.cache
    })
    .build()

const mergedConfiguration = await mergedConfigurationFactory.create({
    auth: { fileLocation: 'config/auth.json' },
    cache: { fileLocation: 'config/cache.json' }
})