{"id":15019659,"url":"https://github.com/onebeyond/confabulous","last_synced_at":"2025-10-24T14:31:25.115Z","repository":{"id":8992251,"uuid":"60326281","full_name":"onebeyond/confabulous","owner":"onebeyond","description":"Confabulous is a hierarchical, asynchronous config loader and post processor.","archived":false,"fork":false,"pushed_at":"2024-07-01T10:01:27.000Z","size":640,"stargazers_count":13,"open_issues_count":4,"forks_count":2,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-02-07T18:58:14.231Z","etag":null,"topics":["configuration","node-js"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onebeyond.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-03T07:07:44.000Z","updated_at":"2024-07-01T10:01:13.000Z","dependencies_parsed_at":"2024-06-18T20:01:40.828Z","dependency_job_id":"2865dd77-f926-48a7-ba22-0f4865cb3680","html_url":"https://github.com/onebeyond/confabulous","commit_stats":{"total_commits":184,"total_committers":8,"mean_commits":23.0,"dds":0.6413043478260869,"last_synced_commit":"cc4c32dea8cd151df8b715d8a5975626a59938f2"},"previous_names":["guidesmiths/confabulous"],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onebeyond%2Fconfabulous","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onebeyond%2Fconfabulous/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onebeyond%2Fconfabulous/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onebeyond%2Fconfabulous/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onebeyond","download_url":"https://codeload.github.com/onebeyond/confabulous/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237982389,"owners_count":19397251,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","node-js"],"created_at":"2024-09-24T19:53:51.508Z","updated_at":"2025-10-24T14:31:22.982Z","avatar_url":"https://github.com/onebeyond.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Confabulous\n\nConfabulous is a hierarchical, asynchronous config loader and post processor. It can load config from command line arguments, environment variables, files, web servers, databases, and even scm systems. It's easy to extend too. You can watch config sources for changes and apply post processors to do things like decrypt secrets or unflatten key/value pairs into structured objects.\n\n[![NPM version](https://img.shields.io/npm/v/confabulous.svg?style=flat-square)](https://www.npmjs.com/package/confabulous)\n[![NPM downloads](https://img.shields.io/npm/dm/confabulous.svg?style=flat-square)](https://www.npmjs.com/package/confabulous)\n[![Node.js CI](https://github.com/onebeyond/confabulous/actions/workflows/ci.yml/badge.svg)](https://github.com/onebeyond/confabulous/actions/workflows/ci.yml)\n[![Release and Publish](https://github.com/onebeyond/confabulous/actions/workflows/release-and-publish.yml/badge.svg)](https://github.com/onebeyond/confabulous/actions/workflows/release-and-publish.yml)\n[![Code Climate](https://codeclimate.com/github/onebeyond/confabulous/badges/gpa.svg)](https://codeclimate.com/github/onebeyond/confabulous)\n[![Test Coverage](https://codeclimate.com/github/onebeyond/confabulous/badges/coverage.svg)](https://codeclimate.com/github/onebeyond/confabulous/coverage)\n[![Code Style](https://img.shields.io/badge/code%20style-prettier-brightgreen.svg)](https://github.com/prettier/prettier)\n\n## TL;DR\n\n```js\nconst Confabulous = require('confabulous');\nconst loaders = Confabulous.loaders;\n\nconst confabulous = new Confabulous()\n  .add((config) =\u003e loaders.require({ path: './conf/defaults.js' }))\n  .add((config) =\u003e loaders.require({ path: './conf/production.js' }))\n  .end((err, config) =\u003e {\n    // Your code goes here\n  });\n```\n\n## Merging\n\nConfabulous recursively merges (and subsequently freezes) configuration from multiple sources. If you want to override the [default merge](https://ramdajs.com/docs/#mergeDeepRight) behaviour you can supply your own merge function, providing it is varardic and favours the right most parameter, e.g.\n\n```js\nfunction shallow(...args) {\n  return Object.assign({}, ...args);\n}\n\nnew Confabulous({ merge: shallow })\n  .add((config) =\u003e loaders.require({ path: './conf/defaults.js' }))\n  .add((config) =\u003e loaders.require({ path: './conf/production.js' }))\n  .end((err, config) =\u003e {\n    // Your code goes here\n  });\n```\n\n## Loaders\n\nLoaders are used to load config. Out of the box you can load config from command line parameters, environment variables and files.\n\n### args\n\nLoads config from command line arguments\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.args();\n});\n```\n\nYou cannot watch command line arguments\n\n### env\n\nLoads config from envrionment variables\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env();\n});\n```\n\nYou cannot watch environment variables\n\n### require\n\nLoads config from a .js or .json file\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.require({ path: './conf/defaults.js' });\n});\n```\n\n| Option    | Type    | Default   | Notes                                                                                                                                                                     |\n| --------- | ------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| path      | string  | undefined | The javascript or json config file to be required                                                                                                                         |\n| mandatory | boolean | true      | Causes an error/reload_error to be emitted if the configuration does not exist                                                                                            |\n| watch     | boolean | undefined | Watching implemented via [fs.watch](https://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener). Be sure to read the caveats section if you encounter problems. |\n\n### file\n\nLoads config from the specified file. Files are read using the specified encoding (defaults to 'utf8'). Use a post processor if you want to convert them to json.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.file({ path: './conf/defaults.js' }, [processors.json()]);\n});\n```\n\n| Option    | Type    | Default   | Notes                                                                                                                                                                     |\n| --------- | ------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| path      | string  | undefined | The config file to be read                                                                                                                                                |\n| mandatory | boolean | true      | Causes an error/reload_error to be emitted if the configuration does not exist                                                                                            |\n| watch     | boolean | undefined | Watching implemented via [fs.watch](https://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener). Be sure to read the caveats section if you encounter problems. |\n| encoding  | string  | utf8      | Specified the file encoding                                                                                                                                               |\n\n### More Loaders\n\nThe following loaders are proviced as separate modules\n\n- [http-loader](https://www.npmjs.com/package/confabulous-http-loader)\n- [etcd-loader](https://www.npmjs.com/package/confabulous-etcd-loader)\n- [vault-loader](https://www.npmjs.com/package/confabulous-vault-loader)\n- [postgres-loader](https://www.npmjs.com/package/confabulous-postgres-loader)\n- [s3-loader](https://www.npmjs.com/package/confabulous-s3-loader)\n\n## Post Processors\n\nPost processes can be used to transform or validate your configuration after it's been loaded. Out of the box you can mount config at a specified key, unflatten key value pairs into structured documents, parse json, decrypt content and transform environment variables.\n\n#### mount\n\nMounts the configuration at the specified key\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.require({ path: './extra.json' }, [processors.mount({ key: 'move.to.here' })]);\n});\n```\n\n#### unflatten\n\nUnflattens config into structured documents. Useful for command line arguments and environment variables.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([processors.unflatten()]);\n});\n```\n\n#### envToProp\n\nConverts environment variables in the form `NODE_ENV=test` to nested properties in the form `{ node: { env: \"test\" } }`\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([processors.envToProp()]);\n});\n```\n\nIf you want to prefix your environment variables with an application discriminator you can also strip the prefix.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([\n    processors.envToProp({ prefix: 'GS_' }), // GS_SERVER_PORT =\u003e server.port\n  ]);\n});\n```\n\nYou can also filter environment variables to include only those you want\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([\n    processors.envToProp({ filter: /^GS_/ }), // Only include environment variables starting with GS_\n  ]);\n});\n```\n\n#### envToCamelCaseProp\n\nConverts environment variables in the form `USER__FIRST_NAME=fred` to nested properties in the form `{ user: { firstName: \"fred\" } }`\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([processors.envToCamelCaseProp()]);\n});\n```\n\nIf you want to prefix your environment variables with an application discriminator you can also strip the prefix.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([\n    // GS_SERVER_PORT =\u003e server.port\n    processors.envToCamelCaseProp({ prefix: 'GS_' }),\n  ]);\n});\n```\n\nYou can also filter environment variables to include only those you want\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.env([\n    // Only include environment variables starting with GS_\n    processors.envToCamelCaseProp({ filter: /^GS_/ }),\n  ]);\n});\n```\n\n#### json\n\nParses text into JSON.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.file({ path: './config.json.encrypted' }, [processors.json()]);\n});\n```\n\n#### decrypt\n\nDecrypts encrypted configuration.\n\n```js\nnew Confabulous().add((config) =\u003e {\n  return loaders.file({ path: './config.json.encrypted' }, [\n    processors.decrypt({\n      algorithm: 'aes-192-cbc',\n      key: process.env.SECRET_KEY,\n      iv: process.env.IV,\n    }),\n    processors.json(),\n  ]);\n});\n```\n\n## Events\n\n### closing\n\nCalling confabulous.close will emit a 'closing' event. This can be used by loaders to free up resources (e.g. close file watchers)\n\n### loaded\n\n**Deprecated. Pass a callback to the `end` function instead.**\nEmitted when loading config for the first time.\n\n### error\n\n**Deprecated. Pass a callback to the `end` function instead.**\nEmitted when an error occurs loading config for the first time.\n\n### reloaded\n\nEmitted when confabulous successfully reloads a watched config.\n\n### reload_error\n\nEmitted when confabulous encounters an error reloading a watched config\n\n#### FAQ\n\nQ. Why doesn't Confabulous notice new files?\u003cbr/\u003e\nA. Because fs.watch doesn't notice them either. You can workaround by modifying some configuration watched by a different loader higher up in the confabulous stack\n\nQ. Why does jest emit a FSEVENTWRAP error?\u003cbr/\u003e\nA. Because you have configured a loader to watch for changes, but not called confabulous.close() in your test teardown\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonebeyond%2Fconfabulous","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonebeyond%2Fconfabulous","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonebeyond%2Fconfabulous/lists"}