├── .gitignore ├── .npmignore ├── __test__ └── index.test.js ├── index.js ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (https://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # TypeScript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # parcel-bundler cache (https://parceljs.org/) 62 | .cache 63 | 64 | # next.js build output 65 | .next 66 | 67 | # nuxt.js build output 68 | .nuxt 69 | 70 | # vuepress build output 71 | .vuepress/dist 72 | 73 | # Serverless directories 74 | .serverless 75 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | __test__ 2 | -------------------------------------------------------------------------------- /__test__/index.test.js: -------------------------------------------------------------------------------- 1 | #!/bin/env/bash node 2 | 3 | const createMiddleware = require('../') 4 | const yargs = require('yargs') 5 | 6 | const middleware = createMiddleware('yconfig') 7 | 8 | yargs.option('key', { type: 'string' }) 9 | .middleware(middleware) 10 | .command('$0', '', () => {}, (argv) => { 11 | console.log(process.env) 12 | }) 13 | .argv -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { serialize, deserialize } = require('kvp') 4 | const win = process.platform === 'win32' 5 | const home = win 6 | ? process.env.USERPROFILE 7 | : process.env.HOME 8 | 9 | const isUppercase = char => 10 | char.charCodeAt(0) >= 65 && char.charCodeAt(0) <= 90 11 | 12 | const simpleSplit = (chars) => { 13 | let str = '' 14 | let out = [] 15 | let index = 0 16 | 17 | const put = value => { 18 | out.push(value) 19 | str = '' 20 | } 21 | 22 | while (index < chars.length) { 23 | let char = chars[index] 24 | let next = chars[index + 1] || '' 25 | str += char.toUpperCase() 26 | index++ 27 | if (isUppercase(next)) { 28 | put(str) 29 | continue 30 | } 31 | if (index === chars.length) { 32 | put(str) 33 | } 34 | } 35 | 36 | return out 37 | } 38 | 39 | const snakeCase = (string) => { 40 | let out = simpleSplit(string.split('')) 41 | return out.join('_') 42 | } 43 | 44 | const normalize = (key = 'yconfig', options = {}) => { 45 | if (key.endsWith('.json')) { 46 | 47 | } 48 | if (!options.path) { 49 | options.path = path.join(home, `.${key}`) 50 | } 51 | 52 | options.path = path.isAbsolute(options.path) 53 | ? options.path 54 | : path.join(home, options.path) 55 | 56 | return { key, options } 57 | } 58 | 59 | module.exports = (...params) => { 60 | let { key, options } = normalize(...params) 61 | 62 | const load = (argv = {}) => { 63 | let config = {} 64 | try { 65 | config = fs.readFileSync(options.path, { encoding: 'utf8' }) 66 | } catch (err) {} 67 | argv[key] = typeof config === 'string' ? deserialize(config) : {} 68 | } 69 | 70 | const save = (argv = {}) => { 71 | let omit = [key, '_', '$0'].concat(options.omit || []) 72 | let props = Object.keys(argv) 73 | .filter(k => !omit.includes(k)) 74 | 75 | let isStale = false 76 | 77 | while (props.length) { 78 | let prop = props.shift() 79 | if (argv[prop] && argv[prop] !== (argv[key] || {})[prop]) { 80 | if (!isStale) { 81 | isStale = true 82 | } 83 | argv[key][prop] = argv[prop] 84 | } 85 | } 86 | for (let prop in argv[key]) { 87 | let type = typeof argv[key][prop] 88 | if (['string', 'boolean', 'number'].includes(type)) { 89 | process.env[snakeCase(prop)] = argv[key][prop] 90 | } 91 | } 92 | if (isStale) { 93 | fs.writeFileSync(options.path, serialize(argv[key])) 94 | } 95 | } 96 | return [ 97 | load, 98 | save 99 | ] 100 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yargs-middleware", 3 | "version": "0.0.2", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "kvp": "^0.0.1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/unshift/yargs-middleware.git" 12 | }, 13 | "devDependencies": { 14 | "yargs": "https://github.com/yargs/yargs" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ansi-regex@^2.0.0: 6 | version "2.1.1" 7 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 8 | 9 | ansi-regex@^3.0.0: 10 | version "3.0.0" 11 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 12 | 13 | camelcase@^4.1.0: 14 | version "4.1.0" 15 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 16 | 17 | cliui@^4.0.0: 18 | version "4.1.0" 19 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" 20 | dependencies: 21 | string-width "^2.1.1" 22 | strip-ansi "^4.0.0" 23 | wrap-ansi "^2.0.0" 24 | 25 | code-point-at@^1.0.0: 26 | version "1.1.0" 27 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 28 | 29 | cross-spawn@^5.0.1: 30 | version "5.1.0" 31 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 32 | dependencies: 33 | lru-cache "^4.0.1" 34 | shebang-command "^1.2.0" 35 | which "^1.2.9" 36 | 37 | decamelize@^2.0.0: 38 | version "2.0.0" 39 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" 40 | dependencies: 41 | xregexp "4.0.0" 42 | 43 | execa@^0.7.0: 44 | version "0.7.0" 45 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" 46 | dependencies: 47 | cross-spawn "^5.0.1" 48 | get-stream "^3.0.0" 49 | is-stream "^1.1.0" 50 | npm-run-path "^2.0.0" 51 | p-finally "^1.0.0" 52 | signal-exit "^3.0.0" 53 | strip-eof "^1.0.0" 54 | 55 | find-up@^3.0.0: 56 | version "3.0.0" 57 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 58 | dependencies: 59 | locate-path "^3.0.0" 60 | 61 | get-caller-file@^1.0.1: 62 | version "1.0.3" 63 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 64 | 65 | get-stream@^3.0.0: 66 | version "3.0.0" 67 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 68 | 69 | invert-kv@^1.0.0: 70 | version "1.0.0" 71 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" 72 | 73 | is-circular@^1.0.2: 74 | version "1.0.2" 75 | resolved "https://registry.yarnpkg.com/is-circular/-/is-circular-1.0.2.tgz#2e0ab4e9835f4c6b0ea2b9855a84acd501b8366c" 76 | 77 | is-fullwidth-code-point@^1.0.0: 78 | version "1.0.0" 79 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 80 | dependencies: 81 | number-is-nan "^1.0.0" 82 | 83 | is-fullwidth-code-point@^2.0.0: 84 | version "2.0.0" 85 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 86 | 87 | is-stream@^1.1.0: 88 | version "1.1.0" 89 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 90 | 91 | isexe@^2.0.0: 92 | version "2.0.0" 93 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 94 | 95 | kvp@^0.0.1: 96 | version "0.0.1" 97 | resolved "https://registry.yarnpkg.com/kvp/-/kvp-0.0.1.tgz#2c5bd530362a0aab36108d5b8b45faec16d6bc24" 98 | dependencies: 99 | is-circular "^1.0.2" 100 | lodash.set "^4.3.2" 101 | 102 | lcid@^1.0.0: 103 | version "1.0.0" 104 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" 105 | dependencies: 106 | invert-kv "^1.0.0" 107 | 108 | locate-path@^3.0.0: 109 | version "3.0.0" 110 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 111 | dependencies: 112 | p-locate "^3.0.0" 113 | path-exists "^3.0.0" 114 | 115 | lodash.set@^4.3.2: 116 | version "4.3.2" 117 | resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" 118 | 119 | lru-cache@^4.0.1: 120 | version "4.1.3" 121 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" 122 | dependencies: 123 | pseudomap "^1.0.2" 124 | yallist "^2.1.2" 125 | 126 | mem@^1.1.0: 127 | version "1.1.0" 128 | resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" 129 | dependencies: 130 | mimic-fn "^1.0.0" 131 | 132 | mimic-fn@^1.0.0: 133 | version "1.2.0" 134 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 135 | 136 | npm-run-path@^2.0.0: 137 | version "2.0.2" 138 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 139 | dependencies: 140 | path-key "^2.0.0" 141 | 142 | number-is-nan@^1.0.0: 143 | version "1.0.1" 144 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 145 | 146 | os-locale@^2.0.0: 147 | version "2.1.0" 148 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" 149 | dependencies: 150 | execa "^0.7.0" 151 | lcid "^1.0.0" 152 | mem "^1.1.0" 153 | 154 | p-finally@^1.0.0: 155 | version "1.0.0" 156 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 157 | 158 | p-limit@^2.0.0: 159 | version "2.0.0" 160 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" 161 | dependencies: 162 | p-try "^2.0.0" 163 | 164 | p-locate@^3.0.0: 165 | version "3.0.0" 166 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 167 | dependencies: 168 | p-limit "^2.0.0" 169 | 170 | p-try@^2.0.0: 171 | version "2.0.0" 172 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" 173 | 174 | path-exists@^3.0.0: 175 | version "3.0.0" 176 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 177 | 178 | path-key@^2.0.0: 179 | version "2.0.1" 180 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 181 | 182 | pseudomap@^1.0.2: 183 | version "1.0.2" 184 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 185 | 186 | require-directory@^2.1.1: 187 | version "2.1.1" 188 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 189 | 190 | require-main-filename@^1.0.1: 191 | version "1.0.1" 192 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" 193 | 194 | set-blocking@^2.0.0: 195 | version "2.0.0" 196 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 197 | 198 | shebang-command@^1.2.0: 199 | version "1.2.0" 200 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 201 | dependencies: 202 | shebang-regex "^1.0.0" 203 | 204 | shebang-regex@^1.0.0: 205 | version "1.0.0" 206 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 207 | 208 | signal-exit@^3.0.0: 209 | version "3.0.2" 210 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 211 | 212 | string-width@^1.0.1: 213 | version "1.0.2" 214 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 215 | dependencies: 216 | code-point-at "^1.0.0" 217 | is-fullwidth-code-point "^1.0.0" 218 | strip-ansi "^3.0.0" 219 | 220 | string-width@^2.0.0, string-width@^2.1.1: 221 | version "2.1.1" 222 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 223 | dependencies: 224 | is-fullwidth-code-point "^2.0.0" 225 | strip-ansi "^4.0.0" 226 | 227 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 228 | version "3.0.1" 229 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 230 | dependencies: 231 | ansi-regex "^2.0.0" 232 | 233 | strip-ansi@^4.0.0: 234 | version "4.0.0" 235 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 236 | dependencies: 237 | ansi-regex "^3.0.0" 238 | 239 | strip-eof@^1.0.0: 240 | version "1.0.0" 241 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 242 | 243 | which-module@^2.0.0: 244 | version "2.0.0" 245 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 246 | 247 | which@^1.2.9: 248 | version "1.3.1" 249 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 250 | dependencies: 251 | isexe "^2.0.0" 252 | 253 | wrap-ansi@^2.0.0: 254 | version "2.1.0" 255 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 256 | dependencies: 257 | string-width "^1.0.1" 258 | strip-ansi "^3.0.1" 259 | 260 | xregexp@4.0.0: 261 | version "4.0.0" 262 | resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" 263 | 264 | "y18n@^3.2.1 || ^4.0.0": 265 | version "4.0.0" 266 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" 267 | 268 | yallist@^2.1.2: 269 | version "2.1.2" 270 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 271 | 272 | yargs-parser@^10.1.0: 273 | version "10.1.0" 274 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" 275 | dependencies: 276 | camelcase "^4.1.0" 277 | 278 | "yargs@https://github.com/yargs/yargs": 279 | version "12.0.1" 280 | resolved "https://github.com/yargs/yargs#18b2fcb19db1e652614d066098d1de4818fbcb3e" 281 | dependencies: 282 | cliui "^4.0.0" 283 | decamelize "^2.0.0" 284 | find-up "^3.0.0" 285 | get-caller-file "^1.0.1" 286 | os-locale "^2.0.0" 287 | require-directory "^2.1.1" 288 | require-main-filename "^1.0.1" 289 | set-blocking "^2.0.0" 290 | string-width "^2.0.0" 291 | which-module "^2.0.0" 292 | y18n "^3.2.1 || ^4.0.0" 293 | yargs-parser "^10.1.0" 294 | --------------------------------------------------------------------------------