| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | # config-chain |
| 2 | |
| 3 | A module for loading custom configurations |
| 4 | |
| 5 | ## NOTE: Feature Freeze |
| 6 | |
| 7 | [](http://github.com/badges/stability-badges) |
| 8 | |
| 9 | This module is frozen. |
| 10 | |
| 11 | In general, we recommend using [rc](https://github.com/dominictarr/rc) instead, |
| 12 | but as [npm](https://github.com/npmjs/npm) depends on this, it cannot be changed. |
| 13 | |
| 14 | |
| 15 | ## Install |
| 16 | |
| 17 | ```sh |
| 18 | yarn add config-chain |
| 19 | |
| 20 | # npm users |
| 21 | npm install --save config-chain |
| 22 | ``` |
| 23 | |
| 24 | ## Usage |
| 25 | |
| 26 | ```js |
| 27 | const cc = require('config-chain'); |
| 28 | |
| 29 | console.log(cc.env('TERM_', process.env)); |
| 30 | /* |
| 31 | { SESSION_ID: 'w1:5F38', |
| 32 | PROGRAM_VERSION: '3.1.2', |
| 33 | PROGRAM: 'iTerm.app' } |
| 34 | */ |
| 35 | ``` |
| 36 | |
| 37 | The `.env` function gets all the keys on the provided object which are |
| 38 | prefixed by the specified prefix, removes the prefix, and puts the values on a new object. |
| 39 | |
| 40 | <br/> |
| 41 | |
| 42 | ## Full Usage |
| 43 | |
| 44 | ``` js |
| 45 | |
| 46 | // npm install config-chain |
| 47 | |
| 48 | var cc = require('config-chain') |
| 49 | , opts = require('optimist').argv //ALWAYS USE OPTIMIST FOR COMMAND LINE OPTIONS. |
| 50 | , env = opts.env || process.env.YOUR_APP_ENV || 'dev' //SET YOUR ENV LIKE THIS. |
| 51 | |
| 52 | // EACH ARG TO CONFIGURATOR IS LOADED INTO CONFIGURATION CHAIN |
| 53 | // EARLIER ITEMS OVERIDE LATER ITEMS |
| 54 | // PUTS COMMAND LINE OPTS FIRST, AND DEFAULTS LAST! |
| 55 | |
| 56 | //strings are interpereted as filenames. |
| 57 | //will be loaded synchronously |
| 58 | |
| 59 | var conf = |
| 60 | cc( |
| 61 | //OVERRIDE SETTINGS WITH COMMAND LINE OPTS |
| 62 | opts, |
| 63 | |
| 64 | //ENV VARS IF PREFIXED WITH 'myApp_' |
| 65 | |
| 66 | cc.env('myApp_'), //myApp_foo = 'like this' |
| 67 | |
| 68 | //FILE NAMED BY ENV |
| 69 | path.join(__dirname, 'config.' + env + '.json'), |
| 70 | |
| 71 | //IF `env` is PRODUCTION |
| 72 | env === 'prod' |
| 73 | ? path.join(__dirname, 'special.json') //load a special file |
| 74 | : null //NULL IS IGNORED! |
| 75 | |
| 76 | //SUBDIR FOR ENV CONFIG |
| 77 | path.join(__dirname, 'config', env, 'config.json'), |
| 78 | |
| 79 | //SEARCH PARENT DIRECTORIES FROM CURRENT DIR FOR FILE |
| 80 | cc.find('config.json'), |
| 81 | |
| 82 | //PUT DEFAULTS LAST |
| 83 | { |
| 84 | host: 'localhost' |
| 85 | port: 8000 |
| 86 | }) |
| 87 | |
| 88 | var host = conf.get('host') |
| 89 | |
| 90 | // or |
| 91 | |
| 92 | var host = conf.store.host |
| 93 | |
| 94 | ``` |
| 95 | |
| 96 | Finally, flexible configurations! 👌 |
| 97 | |
| 98 | ## Custom Configuations |
| 99 | |
| 100 | ```javascript |
| 101 | var cc = require('config-chain') |
| 102 | |
| 103 | // all the stuff you did before |
| 104 | var config = cc({ |
| 105 | some: 'object' |
| 106 | }, |
| 107 | cc.find('config.json'), |
| 108 | cc.env('myApp_') |
| 109 | ) |
| 110 | // CONFIGS AS A SERVICE, aka "CaaS", aka EVERY DEVOPS DREAM OMG! |
| 111 | .addUrl('http://configurator:1234/my-configs') |
| 112 | // ASYNC FTW! |
| 113 | .addFile('/path/to/file.json') |
| 114 | |
| 115 | // OBJECTS ARE OK TOO, they're SYNC but they still ORDER RIGHT |
| 116 | // BECAUSE PROMISES ARE USED BUT NO, NOT *THOSE* PROMISES, JUST |
| 117 | // ACTUAL PROMISES LIKE YOU MAKE TO YOUR MOM, KEPT OUT OF LOVE |
| 118 | .add({ another: 'object' }) |
| 119 | |
| 120 | // DIE A THOUSAND DEATHS IF THIS EVER HAPPENS!! |
| 121 | .on('error', function (er) { |
| 122 | // IF ONLY THERE WAS SOMETHIGN HARDER THAN THROW |
| 123 | // MY SORROW COULD BE ADEQUATELY EXPRESSED. /o\ |
| 124 | throw er |
| 125 | }) |
| 126 | |
| 127 | // THROW A PARTY IN YOUR FACE WHEN ITS ALL LOADED!! |
| 128 | .on('load', function (config) { |
| 129 | console.awesome('HOLY SHIT!') |
| 130 | }) |
| 131 | ``` |
| 132 | |
| 133 | # API Docs |
| 134 | |
| 135 | ## cc(...args) |
| 136 | |
| 137 | MAKE A CHAIN AND ADD ALL THE ARGS. |
| 138 | |
| 139 | If the arg is a STRING, then it shall be a JSON FILENAME. |
| 140 | |
| 141 | RETURN THE CHAIN! |
| 142 | |
| 143 | ## cc.json(...args) |
| 144 | |
| 145 | Join the args into a JSON filename! |
| 146 | |
| 147 | SYNC I/O! |
| 148 | |
| 149 | ## cc.find(relativePath) |
| 150 | |
| 151 | SEEK the RELATIVE PATH by climbing the TREE OF DIRECTORIES. |
| 152 | |
| 153 | RETURN THE FOUND PATH! |
| 154 | |
| 155 | SYNC I/O! |
| 156 | |
| 157 | ## cc.parse(content, file, type) |
| 158 | |
| 159 | Parse the content string, and guess the type from either the |
| 160 | specified type or the filename. |
| 161 | |
| 162 | RETURN THE RESULTING OBJECT! |
| 163 | |
| 164 | NO I/O! |
| 165 | |
| 166 | ## cc.env(prefix, env=process.env) |
| 167 | |
| 168 | Get all the keys on the provided object which are |
| 169 | prefixed by the specified prefix, removes the prefix, and puts the values on a new object. |
| 170 | |
| 171 | RETURN THE RESULTING OBJECT! |
| 172 | |
| 173 | NO I/O! |
| 174 | |
| 175 | ## cc.ConfigChain() |
| 176 | |
| 177 | The ConfigChain class for CRAY CRAY JQUERY STYLE METHOD CHAINING! |
| 178 | |
| 179 | One of these is returned by the main exported function, as well. |
| 180 | |
| 181 | It inherits (prototypically) from |
| 182 | [ProtoList](https://github.com/isaacs/proto-list/), and also inherits |
| 183 | (parasitically) from |
| 184 | [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter) |
| 185 | |
| 186 | It has all the methods from both, and except where noted, they are |
| 187 | unchanged. |
| 188 | |
| 189 | ### LET IT BE KNOWN THAT chain IS AN INSTANCE OF ConfigChain. |
| 190 | |
| 191 | ## chain.sources |
| 192 | |
| 193 | A list of all the places where it got stuff. The keys are the names |
| 194 | passed to addFile or addUrl etc, and the value is an object with some |
| 195 | info about the data source. |
| 196 | |
| 197 | ## chain.addFile(filename, type, [name=filename]) |
| 198 | |
| 199 | Filename is the name of the file. Name is an arbitrary string to be |
| 200 | used later if you desire. Type is either 'ini' or 'json', and will |
| 201 | try to guess intelligently if omitted. |
| 202 | |
| 203 | Loaded files can be saved later. |
| 204 | |
| 205 | ## chain.addUrl(url, type, [name=url]) |
| 206 | |
| 207 | Same as the filename thing, but with a url. |
| 208 | |
| 209 | Can't be saved later. |
| 210 | |
| 211 | ## chain.addEnv(prefix, env, [name='env']) |
| 212 | |
| 213 | Add all the keys from the env object that start with the prefix. |
| 214 | |
| 215 | ## chain.addString(data, file, type, [name]) |
| 216 | |
| 217 | Parse the string and add it to the set. (Mainly used internally.) |
| 218 | |
| 219 | ## chain.add(object, [name]) |
| 220 | |
| 221 | Add the object to the set. |
| 222 | |
| 223 | ## chain.root {Object} |
| 224 | |
| 225 | The root from which all the other config objects in the set descend |
| 226 | prototypically. |
| 227 | |
| 228 | Put your defaults here. |
| 229 | |
| 230 | ## chain.set(key, value, name) |
| 231 | |
| 232 | Set the key to the value on the named config object. If name is |
| 233 | unset, then set it on the first config object in the set. (That is, |
| 234 | the one with the highest priority, which was added first.) |
| 235 | |
| 236 | ## chain.get(key, [name]) |
| 237 | |
| 238 | Get the key from the named config object explicitly, or from the |
| 239 | resolved configs if not specified. |
| 240 | |
| 241 | ## chain.save(name, type) |
| 242 | |
| 243 | Write the named config object back to its origin. |
| 244 | |
| 245 | Currently only supported for env and file config types. |
| 246 | |
| 247 | For files, encode the data according to the type. |
| 248 | |
| 249 | ## chain.on('save', function () {}) |
| 250 | |
| 251 | When one or more files are saved, emits `save` event when they're all |
| 252 | saved. |
| 253 | |
| 254 | ## chain.on('load', function (chain) {}) |
| 255 | |
| 256 | When the config chain has loaded all the specified files and urls and |
| 257 | such, the 'load' event fires. |