{"_id":"12factorial","_rev":"10-ed87c50839806d5b058b2241b1abf8c6","name":"12factorial","description":"A library for consuming config from environment variables and Consul","dist-tags":{"latest":"0.6.1"},"versions":{"0.3.0":{"name":"12factorial","version":"0.3.0","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0","jasmine":"^2.5.3"},"gitHead":"74fe5ae2984d8d8d7f6447fbf44b8771f4a6ceae","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.3.0","_shasum":"cceb1260f901f7b271ea0df035db8b89ca3a29c4","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"cceb1260f901f7b271ea0df035db8b89ca3a29c4","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.3.0.tgz","integrity":"sha512-vKMem0a5SflIddQyHoEtSa+ACcol1P2z6dHNLBbLuT/cFsNU1fQ8D2I7Um9yH54/Vu2GAkiiBXzEe/WHDZJMFw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEUgp2938UMQ8Uqpc+a12NZ1LwNwip3JRiiKw4PVIPMwIhAL8EOvPb5yBHpEGwCqHdWiGRSk3iOHp7GcmhGP/uDGqW"}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/12factorial-0.3.0.tgz_1492940003427_0.7735400695819408"}},"0.4.0":{"name":"12factorial","version":"0.4.0","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"b97636a20ac3c5fc253b2b55fde2b971e809437c","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.4.0","_shasum":"104bdf06a726665c9d8c70f78beb6436b81fa7e5","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"104bdf06a726665c9d8c70f78beb6436b81fa7e5","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.4.0.tgz","integrity":"sha512-tjzM1hanssvtMNeux7oqdqByvGIoVIFFZO9Gj/HfkiRyjvdjt6JOzaYBrbLeib/ICLzZERJHyHDDG7tbnuu31A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAXJeVud1dcqpaTHbn52mBo+06U4kfxsGN2/bjRy35zcAiAwWMj6v+VchpT0TXdJPLAsyx+HrLvtuBwuBy2NY8YbrA=="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/12factorial-0.4.0.tgz_1493038745836_0.8896923274733126"}},"0.4.1":{"name":"12factorial","version":"0.4.1","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"a1ef02e458594190462f38f90986050cbe791299","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.4.1","_shasum":"0af979a812e053f79e55ff33bd8fb82702849a1c","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"0af979a812e053f79e55ff33bd8fb82702849a1c","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.4.1.tgz","integrity":"sha512-yFe2rLLToJADZJBSX/UA5E+ISUPNIq+IEFOWMI/abEk7O25gyWUQhhwdzXZDAs8k7OnWPtSnafTTpmkxQ7Wn4g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBoP04ErkaayGeI+OoNh75+yVmNvLqdLJKMKADDWSd/3AiARDnu6yMCLyiP9X6nVLIeQB7ePRNamVs7raeQyT5blGg=="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/12factorial-0.4.1.tgz_1493041434599_0.33498517354018986"}},"0.5.0":{"name":"12factorial","version":"0.5.0","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"a274ad58a6f28e8bbef648ed64ef37609e60dc6e","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.5.0","_shasum":"7d2eefd2155811db50b56dde8c4042a4e225137a","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"7d2eefd2155811db50b56dde8c4042a4e225137a","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.5.0.tgz","integrity":"sha512-ALteppMmitVCkc2NhYtaPYA/9tG401zKmJLwaYl5mCo2+Jn0KP/jZXeGWdQ8BBtEPXvaHF4oiNZAnHgsYwyIZw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDvtwPL0d/sPk34I0maRxvCun83N5BDypQfuMDC8WmOjAiEAq06tO4diLhySkMahumZ+fy5lkksSt/qecpzdX2ZTTpE="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/12factorial-0.5.0.tgz_1493048238845_0.39580506994389"}},"0.5.1":{"name":"12factorial","version":"0.5.1","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"5d711d8627c8ec1d28f77c2955342c1a641479b3","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.5.1","_shasum":"e05561f6ad56eed8b0c53fd46710815cfd226ea6","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"e05561f6ad56eed8b0c53fd46710815cfd226ea6","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.5.1.tgz","integrity":"sha512-dKrVP0e3LaUrK4BJdIC4EbHbeOGDxsimlbB0mbsqSm2IiKDLMXlrgvaZ8YBdzSdBk34AlyBlbvUb0Ko24l9/zw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1pbSbrtojbcmB6bjEp8sljUWxYhYOWgjTuoU3lG+K2gIhAJNpZC98WnfC/fNHTrnFNBCG/mDc0B6uC5rRnnc2ssXd"}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/12factorial-0.5.1.tgz_1493051989001_0.032548603834584355"}},"0.5.2":{"name":"12factorial","version":"0.5.2","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"11c7b77cbfb9b64ec34de20ee939d64c4bd750fd","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.5.2","_shasum":"21318c0416fb685adc3d6846e592a91a0bdbe5a1","_from":".","_npmVersion":"4.5.0","_nodeVersion":"7.7.3","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"shasum":"21318c0416fb685adc3d6846e592a91a0bdbe5a1","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.5.2.tgz","integrity":"sha512-TUY7rxNzNLosAHT5xqzUlFbuFvBHNRoWWz7HJyfXDIz/y3BeN7VXRcP1gpwtifXk9q3EUiWqtzAXZM7UU66hoQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHAkJ+Qn44VTE1i/85e0E+ySRATWaGL9aW5txbqYGSfXAiEA+ZMVLwRFeepIbzvtMmUiE0aMb8LxG7C4HJ5SNCUF7Js="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/12factorial-0.5.2.tgz_1493109314270_0.06323433644138277"}},"0.6.0":{"name":"12factorial","version":"0.6.0","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"d05df557fb1b8267575f202231fe2e828f49f36a","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.6.0","_npmVersion":"5.5.1","_nodeVersion":"8.8.1","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"integrity":"sha512-CYjPMrsBv1EFfcoAFbjsrP9uXh6fg1++cS8lv0IX0YEvGOfCIlCNxh4PlneW4wsoOVwj5LbXLjxS1h/WosTRiA==","shasum":"22ff1c93e1cee162f7834694f653e67ab3207773","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.6.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIApGLwT91f6N9IPH+B3LkSof7ClKntTLqYx6zSpc28nBAiEAxuezCxYvxmdJz8ecCrhVrIHWq7flIYC/Z7vArVmCldM="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/12factorial-0.6.0.tgz_1510844825624_0.7291041826829314"}},"0.6.1":{"name":"12factorial","version":"0.6.1","repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"keywords":["consul","configuration","environment"],"description":"A library for consuming config from environment variables and Consul","main":"index.js","scripts":{"test":"node_modules/jasmine/bin/jasmine.js test/index.js"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"license":"MIT","dependencies":{"consul":"^0.28.0"},"devDependencies":{"jasmine":"^2.5.3"},"gitHead":"2a4aa132d132d5a84ea0eaa66d8e0cd3b5e08028","bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"homepage":"https://github.com/bobthemighty/12factorial#readme","_id":"12factorial@0.6.1","_npmVersion":"5.6.0","_nodeVersion":"9.3.0","_npmUser":{"name":"bobthemighty","email":"pathogenix@gmail.com"},"dist":{"integrity":"sha512-TPnPCWooIlUbmfdY9tPgPXZBudCDqM7jw5VjEBeszsTHpf9lrrqT9p43mkhttzzzloQB/mld0IxTx7UQCxrUWw==","shasum":"336e59b68f94f753c8cb880fe57d31156ae1b1cf","tarball":"https://registry.npmjs.org/12factorial/-/12factorial-0.6.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAdZOBTQAZgpeDTTYEmn+E22y5uMDOkpEk41NENMACddAiAz3aIrjE0dZ/fX0XuDGeKvSgMRNBIrhWPfQH/TG9m1PQ=="}]},"maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/12factorial-0.6.1.tgz_1513691715127_0.628548595122993"}}},"readme":"# 12 Factorial\n\n12 Factorial is a simple lib for building dynamic configuration from environment variables and Consul. \n## What does it do?\n\n```\n// myconfig.js\nimport cfg from '12factorial'\n\n// Configs are described as plain javascript objects.\nconst spec = {\n\n  // they can contain any data you like\n  constantValue: 'abc-123',\n  someOtherValue: myFunction(),\n\n  // 12factorial.service will synchronise a field\n  // with a consul service, or with env vars.\n  database: cfg.service('my-db'),\n\n  credentials: {\n    // 12factorial.value will synchronise a field\n    // with consul's KV store, or with an env var.\n    username: cfg.value(),\n    password: cfg.value()\n  },\n}\n\n// 12factorial.build is the factory function that turns your\n// object into a synchronised config object\ncfg.build(spec).then((x) => doSomethingWithConfig(x))\n```\n\n## Using values\n\nThe `value` function synchronises an object field with a scalar value. Env vars take precedence over values stored in Consul, and defaults can be provided. Keys and environment variable names are generated by convention. Values can be declared with a default.\n\n```\n{\n  // This can be set with the env var `VALUE` or the consul key `consul-prefix/value`\n  value: cfg.value(),\n\n  // this can be set with the env var `NESTED_OBJECT_VALUE` or the \n  // consul key `consul-prefix/nested/object/value`\n  nested: {\n     object: {\n        value: cfg.value()\n     }\n  },\n\n  // defaults to 'cheese' if no env var or consul key is available.\n  defaulted: cfg.value({ default: 'cheese' })\n}\n```\n\n\n### Namespacing environment variables\n\nEnvironment variables can be namespaced. In the following example, we use an `envPrefix` of `myapp`. This prefix will be added to the variable names.\n\n```\nspec = {\n  nested: {\n    value: cfg.value()\n  }\n}\n\nprocess.env.MYAPP_NESTED_VALUE = 'beep'\n\ncfg.build(spec, {envPrefix: 'myapp'}).then(config => { \n    console.log(config.nested.value) // prints beep\n});\n```\n\n### Syncing with consul\n\nValues can be synchronised with Consul by passing consul configuration to `12factor.build`. If no consul config is provided, we will skip consul synchronisation. Only the 'prefix' key is required, the other values default to development values. Values are kept up to date with a Consul Watch.\n\n```\nconst consulConfig = {\n\n  prefix: 'myapp',     // required.\n\n  host: '127.0.0.1',   // defaults\n  port: 8500,\n  scheme: 'http'\n}\n\nconst spec = {\n    nested: {\n        value: cfg.value()\n    }\n}\n\ncfg.build(spec, { consul: consulConfig }).then( config => {\n        console.log(config.nested.value) // prints the value of myapp/nested/value from consul kv.\n});\n```\n\n## Using Services\n\nThe `12factor.service` function synchronises an object key with the address and port of a service. As with values, environment variables take precedence over Consul values. Environment variable names are generated by convention, and support namespacing. \n\n```\nconst spec = {\n   web: cfg.service('my-web-service'),\n   db: cfg.service('my-database')\n}\n\nprocess.env.MYAPP_WEB_ADDRESS = '127.0.0.1'\nprocess.env.MYAPP_WEB_PORT = '3002'\n\nconst config = await cfg.build(spec, { envPrefix: 'myapp' })\n\nconsole.log(config.web.getAddress())             // prints 127.0.0.1:3002\nconsole.log(config.web.buildUri('/hello/world')) // prints 127.0.0.1:3002/hello/world\n\nconsole.log(config.db.getAddress())              // prints the address + port of the 'my-database' \n                                                 // service registered in Consul.\n```\n\n### Using Services from Consul\n\nServices are automatically synchronised from Consul. By default, we use 'http://127.0.0.1:8500' as the address of our consul server. Services from Consul are kept up to date with a Consul watch.\n\nIf there are multiple addresses registered for a service, 12factorial will select an address at random and return that address consistently until the service is updated in Consul.\n\n\n### Mixing Values into Services\n\nOccasionally, for ease of consumption, you might want to add extra values into a service object. This is typically useful for storing credentials with a service's address. This use case is covered by the `extend` method of a `service`.\n\n\n```\n\nconst spec = {\n    database: cfg.service('myapp-db').extend({\n        username: cfg.value(),\n        password: cfg.value({ sensitive: true })\n    })\n}   \n\nconst config = await cfg.build(spec)\n\nconsole.log(config.database.getAddress())\nconsole.log(config.database.username)\nconsole.log(config.database.password)\n```\n\n### Type Coercion\n\nValues can be automagically coerced from strings. If you set a default, we will coerce to the same type as the default value. You can override the parsing of your values by passing a reader function.\n\n```\nconst spec = {\n    number: cfg.value({ default: 123 }).\n    bool: cfg.value({ default: true }),\n    custom: cfg.value({ reader: function (x) { return {msg: x } } })\n}   \n\nprocess.env.NUMBER = \"0xFF\"\nprocess.env.BOOL = FALSE // or false\nprocess.env.CUSTOM = 'Hello World'\n\nconst config = await cfg.build(spec)\n\nconsole.log(config.number) // 255\nconsole.log(config.bool) // false\nconsole.log(config.custom.msg) // hello world\n\n```\n\n## Current Status\n\nThis is alpha-quality. There are some missing features, and little error handling. This is intended to meet my own requirements for a production system, but may not meet yours. Feel free to play around and report bugs. \n\n## Roadmap\n\n- [X] Add logging\n- [ ] Make sure we handle errors properly\n- [ ] Add type coercion for values\n- [ ] Allow consul values to query using data center, tags etc.\n- [ ] Extend env var opts to support an arbitrary variable name\n- [ ] Support Hashicorp Vault for secrets.\n- [ ] Consider supporting other back-ends\n- [ ] Basic validity checks, eg. required fields.\n- [ ] Reactivity, eg. raise an event when the database service updates so we can close connections etc\n\n","maintainers":[{"name":"bobthemighty","email":"pathogenix@gmail.com"}],"time":{"modified":"2022-06-12T14:05:42.124Z","created":"2017-04-23T09:33:23.985Z","0.3.0":"2017-04-23T09:33:23.985Z","0.4.0":"2017-04-24T12:59:06.548Z","0.4.1":"2017-04-24T13:43:55.335Z","0.5.0":"2017-04-24T15:37:20.760Z","0.5.1":"2017-04-24T16:39:51.000Z","0.5.2":"2017-04-25T08:35:16.224Z","0.6.0":"2017-11-16T15:07:06.921Z","0.6.1":"2017-12-19T13:55:16.151Z"},"homepage":"https://github.com/bobthemighty/12factorial#readme","keywords":["consul","configuration","environment"],"repository":{"type":"git","url":"git+https://github.com/bobthemighty/12factorial.git"},"author":{"name":"Bob Gregory","email":"bob@codefiend.co.uk"},"bugs":{"url":"https://github.com/bobthemighty/12factorial/issues"},"license":"MIT","readmeFilename":"README.md"}