Dynamic configuration values with variable support.
Works with yml
, json
, toml
config formats and anything that parsed down to a plain ol' javascript object
Configorama extends your configuration with a powerful variable system. It resolves configuration variables from:
- CLI options
- ENV variables
- File references
- Other Key/values in config
- Async/sync JS functions
- Any source you'd like...
See tests for more examples.
Click to expand
Async API:
const path = require('path')
const configorama = require('configorama')
const cliFlags = require('minimist')(process.argv.slice(2))
// Path to yaml/json/toml config
const myConfigFilePath = path.join(__dirname, 'config.yml')
const config = await configorama(myConfigFilePath, {
options: args
})
Sync API:
const path = require('path')
const configorama = require('configorama')
const cliFlags = require('minimist')(process.argv.slice(2))
// Path to yaml/json/toml config
const myConfigFilePath = path.join(__dirname, 'config.yml')
const config = configorama.sync(myConfigFilePath, {
options: cliFlags
})
apiKey: ${env:SECRET_KEY}
# CLI option. Example `cmd --stage dev` makes `bar: dev`
bar: ${opt:stage}
# Composed example makes `foo: dev-hello`
foo: ${opt:stage}-hello
foo: bar
# Self file reference. Resolves to `bar`
one: ${self:foo}
# Shorthand self reference. Resolves to `bar`
two: ${foo}
# import full yml/json/toml file via relative path
yamlFileRef: ${file(./subFile.yml)}
# import sub values from files. This imports other-config.yml `topLevel:` value
yamlFileValue: ${file(./other-config.yml):topLevel}
# import sub values from files. This imports other-config.json `nested.value` value
yamlFileValueSubKey: ${file(./other-config.json):nested.value}
# fallback to default value if file not found
fallbackValueExample: ${file(./not-found.yml), 'fall back value'}
asyncJSValue: ${file(./async-value.js)}
# resolves to 'asyncval'
${file(./asyncValue.js)}
will call into async-value
and run/resolve the async function with values. These values can be strings, objects, arrays, whatever.
/* async-value.js */
module.exports = (config) => {
return fetchSecretsFromRemoteStore()
}
function fetchSecretsFromRemoteStore() {
return delay(1000).then(() => {
return Promise.resolve('asyncval')
})
}
function delay(t, v) {
return new Promise((resolve) => setTimeout(resolve.bind(null, v), t))
}
Resolve values from cwd
git data.
repository: ${git:repository}
describe: ${git:describe}
branch: ${git:branch}
commit: ${git:commit}
sha1: ${git:sha1}
message: ${git:message}
remote: ${git:remote}
remoteDefined: ${git:remote('origin')}
remoteDefinedNoQuotes: ${git:remote(origin)}
repoUrl: ${git:repoUrl}
Filters will transform the resolved variables
toUpperCaseString: ${'value' | toUpperCase }
toKebabCaseString: ${'valueHere' | toKebabCase }
key: lol_hi
keyTwo: lol_hi
toKebabCase: ${key | toKebabCase }
toCamelCase: ${keyTwo | toCamelCase }
Functions will convert resolved config values with various methods.
object:
one: once
two: twice
objectTwo:
three: third
four: fourth
mergeObjects: ${merge(${object}, ${objectTwo})}
See the tests folder for a bunch of examples!
Configorama allows you to bring your own variable sources.
There are 2 ways to resolve variables from custom sources.
-
Use the baked in javascript method for sync or aysnc resolution.
-
Add your own variable syntax and resolver.
const config = configorama('path/to/configFile', { variableSources: [{ // Match variables ${consul:xyz} match: RegExp(/^consul:/g), // Custom variable source. Must return a promise resolver: (varToProcess, opts, currentObject) => { // Make remote call to consul return Promise.resolve(varToProcess) } }] }) console.log(config)
This would match the following config:
key: ${consul:xyz}
Q: Why should I use this?
Never rendering a stale configuration file again!
Q: Does this work with serverless.yml
Yes it does. Using serverless.js
as your main entry point!
/* serverless.js */
const path = require('path')
const configorama = require('configorama')
const args = require('minimist')(process.argv.slice(2))
// Path to serverless config to be parsed
const yamlFile = path.join(__dirname, 'serverless.config.yml')
module.exports = configorama.sync(yamlFile, { options: args })
How is this different than the serverless variable system?
-
You can use it with any other tool you'd like. Just include
configorama
and go nuts. -
It's pluggable. Add whatever variable syntax/sources you wish.
-
Filters! You can filter values before they are resolved.
key: ${opt:stage | toUpperCase}
-
Cleaner self references
keyOne: subKey: hi # Before key: ${self:keyOne.subKey} # Now key: ${keyOne.subKey}
-
Numbers as defaults are supported
key: ${env:whatever, 2}
-
TOML, YML, JSON, etc support
Configorama will work on any configuration format that can be converted into a JS object.
Parse any config format and pass it into configorama.
-
Configorama has a number of built-in functions.
Build in functions can be used within expressions as another way to transform and combine values. These are similar to the operators but all follow a common syntax:
<FUNCTION NAME>(<ARGUMENT 1>, <ARGUMENT 2>)
example:
${merge('one', 'two')} => 'onetwo'
This is forked out of the serverless framework variable system.
Mad props to:
erikerikson, eahefnawy, HyperBrain, ac360, gcphost, pmuens, horike37, lorengordon, AndrewFarley, tobyhede, johncmckim, mangas, e-e-e, BasileTrujillo, miltador, sammarks, RafalWilinski, indieisaconcept, svdgraaf, infiniteluke, j0k3r, craigw, bsdkurt, aoskotsky-amplify, and all the other folks who contributed to the variable system.
Additionally these tools were very helpful: