1'use strict'; 2 3var util = require('util'); 4var path = require('path'); 5var fs = require('fs'); 6 7function camelCase(str) { 8 const isCamelCase = str !== str.toLowerCase() && str !== str.toUpperCase(); 9 if (!isCamelCase) { 10 str = str.toLowerCase(); 11 } 12 if (str.indexOf('-') === -1 && str.indexOf('_') === -1) { 13 return str; 14 } 15 else { 16 let camelcase = ''; 17 let nextChrUpper = false; 18 const leadingHyphens = str.match(/^-+/); 19 for (let i = leadingHyphens ? leadingHyphens[0].length : 0; i < str.length; i++) { 20 let chr = str.charAt(i); 21 if (nextChrUpper) { 22 nextChrUpper = false; 23 chr = chr.toUpperCase(); 24 } 25 if (i !== 0 && (chr === '-' || chr === '_')) { 26 nextChrUpper = true; 27 } 28 else if (chr !== '-' && chr !== '_') { 29 camelcase += chr; 30 } 31 } 32 return camelcase; 33 } 34} 35function decamelize(str, joinString) { 36 const lowercase = str.toLowerCase(); 37 joinString = joinString || '-'; 38 let notCamelcase = ''; 39 for (let i = 0; i < str.length; i++) { 40 const chrLower = lowercase.charAt(i); 41 const chrString = str.charAt(i); 42 if (chrLower !== chrString && i > 0) { 43 notCamelcase += `${joinString}${lowercase.charAt(i)}`; 44 } 45 else { 46 notCamelcase += chrString; 47 } 48 } 49 return notCamelcase; 50} 51function looksLikeNumber(x) { 52 if (x === null || x === undefined) 53 return false; 54 if (typeof x === 'number') 55 return true; 56 if (/^0x[0-9a-f]+$/i.test(x)) 57 return true; 58 if (/^0[^.]/.test(x)) 59 return false; 60 return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); 61} 62 63function tokenizeArgString(argString) { 64 if (Array.isArray(argString)) { 65 return argString.map(e => typeof e !== 'string' ? e + '' : e); 66 } 67 argString = argString.trim(); 68 let i = 0; 69 let prevC = null; 70 let c = null; 71 let opening = null; 72 const args = []; 73 for (let ii = 0; ii < argString.length; ii++) { 74 prevC = c; 75 c = argString.charAt(ii); 76 if (c === ' ' && !opening) { 77 if (!(prevC === ' ')) { 78 i++; 79 } 80 continue; 81 } 82 if (c === opening) { 83 opening = null; 84 } 85 else if ((c === "'" || c === '"') && !opening) { 86 opening = c; 87 } 88 if (!args[i]) 89 args[i] = ''; 90 args[i] += c; 91 } 92 return args; 93} 94 95var DefaultValuesForTypeKey; 96(function (DefaultValuesForTypeKey) { 97 DefaultValuesForTypeKey["BOOLEAN"] = "boolean"; 98 DefaultValuesForTypeKey["STRING"] = "string"; 99 DefaultValuesForTypeKey["NUMBER"] = "number"; 100 DefaultValuesForTypeKey["ARRAY"] = "array"; 101})(DefaultValuesForTypeKey || (DefaultValuesForTypeKey = {})); 102 103let mixin; 104class YargsParser { 105 constructor(_mixin) { 106 mixin = _mixin; 107 } 108 parse(argsInput, options) { 109 const opts = Object.assign({ 110 alias: undefined, 111 array: undefined, 112 boolean: undefined, 113 config: undefined, 114 configObjects: undefined, 115 configuration: undefined, 116 coerce: undefined, 117 count: undefined, 118 default: undefined, 119 envPrefix: undefined, 120 narg: undefined, 121 normalize: undefined, 122 string: undefined, 123 number: undefined, 124 __: undefined, 125 key: undefined 126 }, options); 127 const args = tokenizeArgString(argsInput); 128 const inputIsString = typeof argsInput === 'string'; 129 const aliases = combineAliases(Object.assign(Object.create(null), opts.alias)); 130 const configuration = Object.assign({ 131 'boolean-negation': true, 132 'camel-case-expansion': true, 133 'combine-arrays': false, 134 'dot-notation': true, 135 'duplicate-arguments-array': true, 136 'flatten-duplicate-arrays': true, 137 'greedy-arrays': true, 138 'halt-at-non-option': false, 139 'nargs-eats-options': false, 140 'negation-prefix': 'no-', 141 'parse-numbers': true, 142 'parse-positional-numbers': true, 143 'populate--': false, 144 'set-placeholder-key': false, 145 'short-option-groups': true, 146 'strip-aliased': false, 147 'strip-dashed': false, 148 'unknown-options-as-args': false 149 }, opts.configuration); 150 const defaults = Object.assign(Object.create(null), opts.default); 151 const configObjects = opts.configObjects || []; 152 const envPrefix = opts.envPrefix; 153 const notFlagsOption = configuration['populate--']; 154 const notFlagsArgv = notFlagsOption ? '--' : '_'; 155 const newAliases = Object.create(null); 156 const defaulted = Object.create(null); 157 const __ = opts.__ || mixin.format; 158 const flags = { 159 aliases: Object.create(null), 160 arrays: Object.create(null), 161 bools: Object.create(null), 162 strings: Object.create(null), 163 numbers: Object.create(null), 164 counts: Object.create(null), 165 normalize: Object.create(null), 166 configs: Object.create(null), 167 nargs: Object.create(null), 168 coercions: Object.create(null), 169 keys: [] 170 }; 171 const negative = /^-([0-9]+(\.[0-9]+)?|\.[0-9]+)$/; 172 const negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)'); 173 [].concat(opts.array || []).filter(Boolean).forEach(function (opt) { 174 const key = typeof opt === 'object' ? opt.key : opt; 175 const assignment = Object.keys(opt).map(function (key) { 176 const arrayFlagKeys = { 177 boolean: 'bools', 178 string: 'strings', 179 number: 'numbers' 180 }; 181 return arrayFlagKeys[key]; 182 }).filter(Boolean).pop(); 183 if (assignment) { 184 flags[assignment][key] = true; 185 } 186 flags.arrays[key] = true; 187 flags.keys.push(key); 188 }); 189 [].concat(opts.boolean || []).filter(Boolean).forEach(function (key) { 190 flags.bools[key] = true; 191 flags.keys.push(key); 192 }); 193 [].concat(opts.string || []).filter(Boolean).forEach(function (key) { 194 flags.strings[key] = true; 195 flags.keys.push(key); 196 }); 197 [].concat(opts.number || []).filter(Boolean).forEach(function (key) { 198 flags.numbers[key] = true; 199 flags.keys.push(key); 200 }); 201 [].concat(opts.count || []).filter(Boolean).forEach(function (key) { 202 flags.counts[key] = true; 203 flags.keys.push(key); 204 }); 205 [].concat(opts.normalize || []).filter(Boolean).forEach(function (key) { 206 flags.normalize[key] = true; 207 flags.keys.push(key); 208 }); 209 if (typeof opts.narg === 'object') { 210 Object.entries(opts.narg).forEach(([key, value]) => { 211 if (typeof value === 'number') { 212 flags.nargs[key] = value; 213 flags.keys.push(key); 214 } 215 }); 216 } 217 if (typeof opts.coerce === 'object') { 218 Object.entries(opts.coerce).forEach(([key, value]) => { 219 if (typeof value === 'function') { 220 flags.coercions[key] = value; 221 flags.keys.push(key); 222 } 223 }); 224 } 225 if (typeof opts.config !== 'undefined') { 226 if (Array.isArray(opts.config) || typeof opts.config === 'string') { 227 [].concat(opts.config).filter(Boolean).forEach(function (key) { 228 flags.configs[key] = true; 229 }); 230 } 231 else if (typeof opts.config === 'object') { 232 Object.entries(opts.config).forEach(([key, value]) => { 233 if (typeof value === 'boolean' || typeof value === 'function') { 234 flags.configs[key] = value; 235 } 236 }); 237 } 238 } 239 extendAliases(opts.key, aliases, opts.default, flags.arrays); 240 Object.keys(defaults).forEach(function (key) { 241 (flags.aliases[key] || []).forEach(function (alias) { 242 defaults[alias] = defaults[key]; 243 }); 244 }); 245 let error = null; 246 checkConfiguration(); 247 let notFlags = []; 248 const argv = Object.assign(Object.create(null), { _: [] }); 249 const argvReturn = {}; 250 for (let i = 0; i < args.length; i++) { 251 const arg = args[i]; 252 const truncatedArg = arg.replace(/^-{3,}/, '---'); 253 let broken; 254 let key; 255 let letters; 256 let m; 257 let next; 258 let value; 259 if (arg !== '--' && /^-/.test(arg) && isUnknownOptionAsArg(arg)) { 260 pushPositional(arg); 261 } 262 else if (truncatedArg.match(/^---+(=|$)/)) { 263 pushPositional(arg); 264 continue; 265 } 266 else if (arg.match(/^--.+=/) || (!configuration['short-option-groups'] && arg.match(/^-.+=/))) { 267 m = arg.match(/^--?([^=]+)=([\s\S]*)$/); 268 if (m !== null && Array.isArray(m) && m.length >= 3) { 269 if (checkAllAliases(m[1], flags.arrays)) { 270 i = eatArray(i, m[1], args, m[2]); 271 } 272 else if (checkAllAliases(m[1], flags.nargs) !== false) { 273 i = eatNargs(i, m[1], args, m[2]); 274 } 275 else { 276 setArg(m[1], m[2], true); 277 } 278 } 279 } 280 else if (arg.match(negatedBoolean) && configuration['boolean-negation']) { 281 m = arg.match(negatedBoolean); 282 if (m !== null && Array.isArray(m) && m.length >= 2) { 283 key = m[1]; 284 setArg(key, checkAllAliases(key, flags.arrays) ? [false] : false); 285 } 286 } 287 else if (arg.match(/^--.+/) || (!configuration['short-option-groups'] && arg.match(/^-[^-]+/))) { 288 m = arg.match(/^--?(.+)/); 289 if (m !== null && Array.isArray(m) && m.length >= 2) { 290 key = m[1]; 291 if (checkAllAliases(key, flags.arrays)) { 292 i = eatArray(i, key, args); 293 } 294 else if (checkAllAliases(key, flags.nargs) !== false) { 295 i = eatNargs(i, key, args); 296 } 297 else { 298 next = args[i + 1]; 299 if (next !== undefined && (!next.match(/^-/) || 300 next.match(negative)) && 301 !checkAllAliases(key, flags.bools) && 302 !checkAllAliases(key, flags.counts)) { 303 setArg(key, next); 304 i++; 305 } 306 else if (/^(true|false)$/.test(next)) { 307 setArg(key, next); 308 i++; 309 } 310 else { 311 setArg(key, defaultValue(key)); 312 } 313 } 314 } 315 } 316 else if (arg.match(/^-.\..+=/)) { 317 m = arg.match(/^-([^=]+)=([\s\S]*)$/); 318 if (m !== null && Array.isArray(m) && m.length >= 3) { 319 setArg(m[1], m[2]); 320 } 321 } 322 else if (arg.match(/^-.\..+/) && !arg.match(negative)) { 323 next = args[i + 1]; 324 m = arg.match(/^-(.\..+)/); 325 if (m !== null && Array.isArray(m) && m.length >= 2) { 326 key = m[1]; 327 if (next !== undefined && !next.match(/^-/) && 328 !checkAllAliases(key, flags.bools) && 329 !checkAllAliases(key, flags.counts)) { 330 setArg(key, next); 331 i++; 332 } 333 else { 334 setArg(key, defaultValue(key)); 335 } 336 } 337 } 338 else if (arg.match(/^-[^-]+/) && !arg.match(negative)) { 339 letters = arg.slice(1, -1).split(''); 340 broken = false; 341 for (let j = 0; j < letters.length; j++) { 342 next = arg.slice(j + 2); 343 if (letters[j + 1] && letters[j + 1] === '=') { 344 value = arg.slice(j + 3); 345 key = letters[j]; 346 if (checkAllAliases(key, flags.arrays)) { 347 i = eatArray(i, key, args, value); 348 } 349 else if (checkAllAliases(key, flags.nargs) !== false) { 350 i = eatNargs(i, key, args, value); 351 } 352 else { 353 setArg(key, value); 354 } 355 broken = true; 356 break; 357 } 358 if (next === '-') { 359 setArg(letters[j], next); 360 continue; 361 } 362 if (/[A-Za-z]/.test(letters[j]) && 363 /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next) && 364 checkAllAliases(next, flags.bools) === false) { 365 setArg(letters[j], next); 366 broken = true; 367 break; 368 } 369 if (letters[j + 1] && letters[j + 1].match(/\W/)) { 370 setArg(letters[j], next); 371 broken = true; 372 break; 373 } 374 else { 375 setArg(letters[j], defaultValue(letters[j])); 376 } 377 } 378 key = arg.slice(-1)[0]; 379 if (!broken && key !== '-') { 380 if (checkAllAliases(key, flags.arrays)) { 381 i = eatArray(i, key, args); 382 } 383 else if (checkAllAliases(key, flags.nargs) !== false) { 384 i = eatNargs(i, key, args); 385 } 386 else { 387 next = args[i + 1]; 388 if (next !== undefined && (!/^(-|--)[^-]/.test(next) || 389 next.match(negative)) && 390 !checkAllAliases(key, flags.bools) && 391 !checkAllAliases(key, flags.counts)) { 392 setArg(key, next); 393 i++; 394 } 395 else if (/^(true|false)$/.test(next)) { 396 setArg(key, next); 397 i++; 398 } 399 else { 400 setArg(key, defaultValue(key)); 401 } 402 } 403 } 404 } 405 else if (arg.match(/^-[0-9]$/) && 406 arg.match(negative) && 407 checkAllAliases(arg.slice(1), flags.bools)) { 408 key = arg.slice(1); 409 setArg(key, defaultValue(key)); 410 } 411 else if (arg === '--') { 412 notFlags = args.slice(i + 1); 413 break; 414 } 415 else if (configuration['halt-at-non-option']) { 416 notFlags = args.slice(i); 417 break; 418 } 419 else { 420 pushPositional(arg); 421 } 422 } 423 applyEnvVars(argv, true); 424 applyEnvVars(argv, false); 425 setConfig(argv); 426 setConfigObjects(); 427 applyDefaultsAndAliases(argv, flags.aliases, defaults, true); 428 applyCoercions(argv); 429 if (configuration['set-placeholder-key']) 430 setPlaceholderKeys(argv); 431 Object.keys(flags.counts).forEach(function (key) { 432 if (!hasKey(argv, key.split('.'))) 433 setArg(key, 0); 434 }); 435 if (notFlagsOption && notFlags.length) 436 argv[notFlagsArgv] = []; 437 notFlags.forEach(function (key) { 438 argv[notFlagsArgv].push(key); 439 }); 440 if (configuration['camel-case-expansion'] && configuration['strip-dashed']) { 441 Object.keys(argv).filter(key => key !== '--' && key.includes('-')).forEach(key => { 442 delete argv[key]; 443 }); 444 } 445 if (configuration['strip-aliased']) { 446 [].concat(...Object.keys(aliases).map(k => aliases[k])).forEach(alias => { 447 if (configuration['camel-case-expansion'] && alias.includes('-')) { 448 delete argv[alias.split('.').map(prop => camelCase(prop)).join('.')]; 449 } 450 delete argv[alias]; 451 }); 452 } 453 function pushPositional(arg) { 454 const maybeCoercedNumber = maybeCoerceNumber('_', arg); 455 if (typeof maybeCoercedNumber === 'string' || typeof maybeCoercedNumber === 'number') { 456 argv._.push(maybeCoercedNumber); 457 } 458 } 459 function eatNargs(i, key, args, argAfterEqualSign) { 460 let ii; 461 let toEat = checkAllAliases(key, flags.nargs); 462 toEat = typeof toEat !== 'number' || isNaN(toEat) ? 1 : toEat; 463 if (toEat === 0) { 464 if (!isUndefined(argAfterEqualSign)) { 465 error = Error(__('Argument unexpected for: %s', key)); 466 } 467 setArg(key, defaultValue(key)); 468 return i; 469 } 470 let available = isUndefined(argAfterEqualSign) ? 0 : 1; 471 if (configuration['nargs-eats-options']) { 472 if (args.length - (i + 1) + available < toEat) { 473 error = Error(__('Not enough arguments following: %s', key)); 474 } 475 available = toEat; 476 } 477 else { 478 for (ii = i + 1; ii < args.length; ii++) { 479 if (!args[ii].match(/^-[^0-9]/) || args[ii].match(negative) || isUnknownOptionAsArg(args[ii])) 480 available++; 481 else 482 break; 483 } 484 if (available < toEat) 485 error = Error(__('Not enough arguments following: %s', key)); 486 } 487 let consumed = Math.min(available, toEat); 488 if (!isUndefined(argAfterEqualSign) && consumed > 0) { 489 setArg(key, argAfterEqualSign); 490 consumed--; 491 } 492 for (ii = i + 1; ii < (consumed + i + 1); ii++) { 493 setArg(key, args[ii]); 494 } 495 return (i + consumed); 496 } 497 function eatArray(i, key, args, argAfterEqualSign) { 498 let argsToSet = []; 499 let next = argAfterEqualSign || args[i + 1]; 500 const nargsCount = checkAllAliases(key, flags.nargs); 501 if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) { 502 argsToSet.push(true); 503 } 504 else if (isUndefined(next) || 505 (isUndefined(argAfterEqualSign) && /^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) { 506 if (defaults[key] !== undefined) { 507 const defVal = defaults[key]; 508 argsToSet = Array.isArray(defVal) ? defVal : [defVal]; 509 } 510 } 511 else { 512 if (!isUndefined(argAfterEqualSign)) { 513 argsToSet.push(processValue(key, argAfterEqualSign, true)); 514 } 515 for (let ii = i + 1; ii < args.length; ii++) { 516 if ((!configuration['greedy-arrays'] && argsToSet.length > 0) || 517 (nargsCount && typeof nargsCount === 'number' && argsToSet.length >= nargsCount)) 518 break; 519 next = args[ii]; 520 if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) 521 break; 522 i = ii; 523 argsToSet.push(processValue(key, next, inputIsString)); 524 } 525 } 526 if (typeof nargsCount === 'number' && ((nargsCount && argsToSet.length < nargsCount) || 527 (isNaN(nargsCount) && argsToSet.length === 0))) { 528 error = Error(__('Not enough arguments following: %s', key)); 529 } 530 setArg(key, argsToSet); 531 return i; 532 } 533 function setArg(key, val, shouldStripQuotes = inputIsString) { 534 if (/-/.test(key) && configuration['camel-case-expansion']) { 535 const alias = key.split('.').map(function (prop) { 536 return camelCase(prop); 537 }).join('.'); 538 addNewAlias(key, alias); 539 } 540 const value = processValue(key, val, shouldStripQuotes); 541 const splitKey = key.split('.'); 542 setKey(argv, splitKey, value); 543 if (flags.aliases[key]) { 544 flags.aliases[key].forEach(function (x) { 545 const keyProperties = x.split('.'); 546 setKey(argv, keyProperties, value); 547 }); 548 } 549 if (splitKey.length > 1 && configuration['dot-notation']) { 550 (flags.aliases[splitKey[0]] || []).forEach(function (x) { 551 let keyProperties = x.split('.'); 552 const a = [].concat(splitKey); 553 a.shift(); 554 keyProperties = keyProperties.concat(a); 555 if (!(flags.aliases[key] || []).includes(keyProperties.join('.'))) { 556 setKey(argv, keyProperties, value); 557 } 558 }); 559 } 560 if (checkAllAliases(key, flags.normalize) && !checkAllAliases(key, flags.arrays)) { 561 const keys = [key].concat(flags.aliases[key] || []); 562 keys.forEach(function (key) { 563 Object.defineProperty(argvReturn, key, { 564 enumerable: true, 565 get() { 566 return val; 567 }, 568 set(value) { 569 val = typeof value === 'string' ? mixin.normalize(value) : value; 570 } 571 }); 572 }); 573 } 574 } 575 function addNewAlias(key, alias) { 576 if (!(flags.aliases[key] && flags.aliases[key].length)) { 577 flags.aliases[key] = [alias]; 578 newAliases[alias] = true; 579 } 580 if (!(flags.aliases[alias] && flags.aliases[alias].length)) { 581 addNewAlias(alias, key); 582 } 583 } 584 function processValue(key, val, shouldStripQuotes) { 585 if (shouldStripQuotes) { 586 val = stripQuotes(val); 587 } 588 if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) { 589 if (typeof val === 'string') 590 val = val === 'true'; 591 } 592 let value = Array.isArray(val) 593 ? val.map(function (v) { return maybeCoerceNumber(key, v); }) 594 : maybeCoerceNumber(key, val); 595 if (checkAllAliases(key, flags.counts) && (isUndefined(value) || typeof value === 'boolean')) { 596 value = increment(); 597 } 598 if (checkAllAliases(key, flags.normalize) && checkAllAliases(key, flags.arrays)) { 599 if (Array.isArray(val)) 600 value = val.map((val) => { return mixin.normalize(val); }); 601 else 602 value = mixin.normalize(val); 603 } 604 return value; 605 } 606 function maybeCoerceNumber(key, value) { 607 if (!configuration['parse-positional-numbers'] && key === '_') 608 return value; 609 if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.bools) && !Array.isArray(value)) { 610 const shouldCoerceNumber = looksLikeNumber(value) && configuration['parse-numbers'] && (Number.isSafeInteger(Math.floor(parseFloat(`${value}`)))); 611 if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) { 612 value = Number(value); 613 } 614 } 615 return value; 616 } 617 function setConfig(argv) { 618 const configLookup = Object.create(null); 619 applyDefaultsAndAliases(configLookup, flags.aliases, defaults); 620 Object.keys(flags.configs).forEach(function (configKey) { 621 const configPath = argv[configKey] || configLookup[configKey]; 622 if (configPath) { 623 try { 624 let config = null; 625 const resolvedConfigPath = mixin.resolve(mixin.cwd(), configPath); 626 const resolveConfig = flags.configs[configKey]; 627 if (typeof resolveConfig === 'function') { 628 try { 629 config = resolveConfig(resolvedConfigPath); 630 } 631 catch (e) { 632 config = e; 633 } 634 if (config instanceof Error) { 635 error = config; 636 return; 637 } 638 } 639 else { 640 config = mixin.require(resolvedConfigPath); 641 } 642 setConfigObject(config); 643 } 644 catch (ex) { 645 if (ex.name === 'PermissionDenied') 646 error = ex; 647 else if (argv[configKey]) 648 error = Error(__('Invalid JSON config file: %s', configPath)); 649 } 650 } 651 }); 652 } 653 function setConfigObject(config, prev) { 654 Object.keys(config).forEach(function (key) { 655 const value = config[key]; 656 const fullKey = prev ? prev + '.' + key : key; 657 if (typeof value === 'object' && value !== null && !Array.isArray(value) && configuration['dot-notation']) { 658 setConfigObject(value, fullKey); 659 } 660 else { 661 if (!hasKey(argv, fullKey.split('.')) || (checkAllAliases(fullKey, flags.arrays) && configuration['combine-arrays'])) { 662 setArg(fullKey, value); 663 } 664 } 665 }); 666 } 667 function setConfigObjects() { 668 if (typeof configObjects !== 'undefined') { 669 configObjects.forEach(function (configObject) { 670 setConfigObject(configObject); 671 }); 672 } 673 } 674 function applyEnvVars(argv, configOnly) { 675 if (typeof envPrefix === 'undefined') 676 return; 677 const prefix = typeof envPrefix === 'string' ? envPrefix : ''; 678 const env = mixin.env(); 679 Object.keys(env).forEach(function (envVar) { 680 if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) { 681 const keys = envVar.split('__').map(function (key, i) { 682 if (i === 0) { 683 key = key.substring(prefix.length); 684 } 685 return camelCase(key); 686 }); 687 if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && !hasKey(argv, keys)) { 688 setArg(keys.join('.'), env[envVar]); 689 } 690 } 691 }); 692 } 693 function applyCoercions(argv) { 694 let coerce; 695 const applied = new Set(); 696 Object.keys(argv).forEach(function (key) { 697 if (!applied.has(key)) { 698 coerce = checkAllAliases(key, flags.coercions); 699 if (typeof coerce === 'function') { 700 try { 701 const value = maybeCoerceNumber(key, coerce(argv[key])); 702 ([].concat(flags.aliases[key] || [], key)).forEach(ali => { 703 applied.add(ali); 704 argv[ali] = value; 705 }); 706 } 707 catch (err) { 708 error = err; 709 } 710 } 711 } 712 }); 713 } 714 function setPlaceholderKeys(argv) { 715 flags.keys.forEach((key) => { 716 if (~key.indexOf('.')) 717 return; 718 if (typeof argv[key] === 'undefined') 719 argv[key] = undefined; 720 }); 721 return argv; 722 } 723 function applyDefaultsAndAliases(obj, aliases, defaults, canLog = false) { 724 Object.keys(defaults).forEach(function (key) { 725 if (!hasKey(obj, key.split('.'))) { 726 setKey(obj, key.split('.'), defaults[key]); 727 if (canLog) 728 defaulted[key] = true; 729 (aliases[key] || []).forEach(function (x) { 730 if (hasKey(obj, x.split('.'))) 731 return; 732 setKey(obj, x.split('.'), defaults[key]); 733 }); 734 } 735 }); 736 } 737 function hasKey(obj, keys) { 738 let o = obj; 739 if (!configuration['dot-notation']) 740 keys = [keys.join('.')]; 741 keys.slice(0, -1).forEach(function (key) { 742 o = (o[key] || {}); 743 }); 744 const key = keys[keys.length - 1]; 745 if (typeof o !== 'object') 746 return false; 747 else 748 return key in o; 749 } 750 function setKey(obj, keys, value) { 751 let o = obj; 752 if (!configuration['dot-notation']) 753 keys = [keys.join('.')]; 754 keys.slice(0, -1).forEach(function (key) { 755 key = sanitizeKey(key); 756 if (typeof o === 'object' && o[key] === undefined) { 757 o[key] = {}; 758 } 759 if (typeof o[key] !== 'object' || Array.isArray(o[key])) { 760 if (Array.isArray(o[key])) { 761 o[key].push({}); 762 } 763 else { 764 o[key] = [o[key], {}]; 765 } 766 o = o[key][o[key].length - 1]; 767 } 768 else { 769 o = o[key]; 770 } 771 }); 772 const key = sanitizeKey(keys[keys.length - 1]); 773 const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays); 774 const isValueArray = Array.isArray(value); 775 let duplicate = configuration['duplicate-arguments-array']; 776 if (!duplicate && checkAllAliases(key, flags.nargs)) { 777 duplicate = true; 778 if ((!isUndefined(o[key]) && flags.nargs[key] === 1) || (Array.isArray(o[key]) && o[key].length === flags.nargs[key])) { 779 o[key] = undefined; 780 } 781 } 782 if (value === increment()) { 783 o[key] = increment(o[key]); 784 } 785 else if (Array.isArray(o[key])) { 786 if (duplicate && isTypeArray && isValueArray) { 787 o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : (Array.isArray(o[key][0]) ? o[key] : [o[key]]).concat([value]); 788 } 789 else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) { 790 o[key] = value; 791 } 792 else { 793 o[key] = o[key].concat([value]); 794 } 795 } 796 else if (o[key] === undefined && isTypeArray) { 797 o[key] = isValueArray ? value : [value]; 798 } 799 else if (duplicate && !(o[key] === undefined || 800 checkAllAliases(key, flags.counts) || 801 checkAllAliases(key, flags.bools))) { 802 o[key] = [o[key], value]; 803 } 804 else { 805 o[key] = value; 806 } 807 } 808 function extendAliases(...args) { 809 args.forEach(function (obj) { 810 Object.keys(obj || {}).forEach(function (key) { 811 if (flags.aliases[key]) 812 return; 813 flags.aliases[key] = [].concat(aliases[key] || []); 814 flags.aliases[key].concat(key).forEach(function (x) { 815 if (/-/.test(x) && configuration['camel-case-expansion']) { 816 const c = camelCase(x); 817 if (c !== key && flags.aliases[key].indexOf(c) === -1) { 818 flags.aliases[key].push(c); 819 newAliases[c] = true; 820 } 821 } 822 }); 823 flags.aliases[key].concat(key).forEach(function (x) { 824 if (x.length > 1 && /[A-Z]/.test(x) && configuration['camel-case-expansion']) { 825 const c = decamelize(x, '-'); 826 if (c !== key && flags.aliases[key].indexOf(c) === -1) { 827 flags.aliases[key].push(c); 828 newAliases[c] = true; 829 } 830 } 831 }); 832 flags.aliases[key].forEach(function (x) { 833 flags.aliases[x] = [key].concat(flags.aliases[key].filter(function (y) { 834 return x !== y; 835 })); 836 }); 837 }); 838 }); 839 } 840 function checkAllAliases(key, flag) { 841 const toCheck = [].concat(flags.aliases[key] || [], key); 842 const keys = Object.keys(flag); 843 const setAlias = toCheck.find(key => keys.includes(key)); 844 return setAlias ? flag[setAlias] : false; 845 } 846 function hasAnyFlag(key) { 847 const flagsKeys = Object.keys(flags); 848 const toCheck = [].concat(flagsKeys.map(k => flags[k])); 849 return toCheck.some(function (flag) { 850 return Array.isArray(flag) ? flag.includes(key) : flag[key]; 851 }); 852 } 853 function hasFlagsMatching(arg, ...patterns) { 854 const toCheck = [].concat(...patterns); 855 return toCheck.some(function (pattern) { 856 const match = arg.match(pattern); 857 return match && hasAnyFlag(match[1]); 858 }); 859 } 860 function hasAllShortFlags(arg) { 861 if (arg.match(negative) || !arg.match(/^-[^-]+/)) { 862 return false; 863 } 864 let hasAllFlags = true; 865 let next; 866 const letters = arg.slice(1).split(''); 867 for (let j = 0; j < letters.length; j++) { 868 next = arg.slice(j + 2); 869 if (!hasAnyFlag(letters[j])) { 870 hasAllFlags = false; 871 break; 872 } 873 if ((letters[j + 1] && letters[j + 1] === '=') || 874 next === '-' || 875 (/[A-Za-z]/.test(letters[j]) && /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) || 876 (letters[j + 1] && letters[j + 1].match(/\W/))) { 877 break; 878 } 879 } 880 return hasAllFlags; 881 } 882 function isUnknownOptionAsArg(arg) { 883 return configuration['unknown-options-as-args'] && isUnknownOption(arg); 884 } 885 function isUnknownOption(arg) { 886 arg = arg.replace(/^-{3,}/, '--'); 887 if (arg.match(negative)) { 888 return false; 889 } 890 if (hasAllShortFlags(arg)) { 891 return false; 892 } 893 const flagWithEquals = /^-+([^=]+?)=[\s\S]*$/; 894 const normalFlag = /^-+([^=]+?)$/; 895 const flagEndingInHyphen = /^-+([^=]+?)-$/; 896 const flagEndingInDigits = /^-+([^=]+?\d+)$/; 897 const flagEndingInNonWordCharacters = /^-+([^=]+?)\W+.*$/; 898 return !hasFlagsMatching(arg, flagWithEquals, negatedBoolean, normalFlag, flagEndingInHyphen, flagEndingInDigits, flagEndingInNonWordCharacters); 899 } 900 function defaultValue(key) { 901 if (!checkAllAliases(key, flags.bools) && 902 !checkAllAliases(key, flags.counts) && 903 `${key}` in defaults) { 904 return defaults[key]; 905 } 906 else { 907 return defaultForType(guessType(key)); 908 } 909 } 910 function defaultForType(type) { 911 const def = { 912 [DefaultValuesForTypeKey.BOOLEAN]: true, 913 [DefaultValuesForTypeKey.STRING]: '', 914 [DefaultValuesForTypeKey.NUMBER]: undefined, 915 [DefaultValuesForTypeKey.ARRAY]: [] 916 }; 917 return def[type]; 918 } 919 function guessType(key) { 920 let type = DefaultValuesForTypeKey.BOOLEAN; 921 if (checkAllAliases(key, flags.strings)) 922 type = DefaultValuesForTypeKey.STRING; 923 else if (checkAllAliases(key, flags.numbers)) 924 type = DefaultValuesForTypeKey.NUMBER; 925 else if (checkAllAliases(key, flags.bools)) 926 type = DefaultValuesForTypeKey.BOOLEAN; 927 else if (checkAllAliases(key, flags.arrays)) 928 type = DefaultValuesForTypeKey.ARRAY; 929 return type; 930 } 931 function isUndefined(num) { 932 return num === undefined; 933 } 934 function checkConfiguration() { 935 Object.keys(flags.counts).find(key => { 936 if (checkAllAliases(key, flags.arrays)) { 937 error = Error(__('Invalid configuration: %s, opts.count excludes opts.array.', key)); 938 return true; 939 } 940 else if (checkAllAliases(key, flags.nargs)) { 941 error = Error(__('Invalid configuration: %s, opts.count excludes opts.narg.', key)); 942 return true; 943 } 944 return false; 945 }); 946 } 947 return { 948 aliases: Object.assign({}, flags.aliases), 949 argv: Object.assign(argvReturn, argv), 950 configuration: configuration, 951 defaulted: Object.assign({}, defaulted), 952 error: error, 953 newAliases: Object.assign({}, newAliases) 954 }; 955 } 956} 957function combineAliases(aliases) { 958 const aliasArrays = []; 959 const combined = Object.create(null); 960 let change = true; 961 Object.keys(aliases).forEach(function (key) { 962 aliasArrays.push([].concat(aliases[key], key)); 963 }); 964 while (change) { 965 change = false; 966 for (let i = 0; i < aliasArrays.length; i++) { 967 for (let ii = i + 1; ii < aliasArrays.length; ii++) { 968 const intersect = aliasArrays[i].filter(function (v) { 969 return aliasArrays[ii].indexOf(v) !== -1; 970 }); 971 if (intersect.length) { 972 aliasArrays[i] = aliasArrays[i].concat(aliasArrays[ii]); 973 aliasArrays.splice(ii, 1); 974 change = true; 975 break; 976 } 977 } 978 } 979 } 980 aliasArrays.forEach(function (aliasArray) { 981 aliasArray = aliasArray.filter(function (v, i, self) { 982 return self.indexOf(v) === i; 983 }); 984 const lastAlias = aliasArray.pop(); 985 if (lastAlias !== undefined && typeof lastAlias === 'string') { 986 combined[lastAlias] = aliasArray; 987 } 988 }); 989 return combined; 990} 991function increment(orig) { 992 return orig !== undefined ? orig + 1 : 1; 993} 994function sanitizeKey(key) { 995 if (key === '__proto__') 996 return '___proto___'; 997 return key; 998} 999function stripQuotes(val) { 1000 return (typeof val === 'string' && 1001 (val[0] === "'" || val[0] === '"') && 1002 val[val.length - 1] === val[0]) 1003 ? val.substring(1, val.length - 1) 1004 : val; 1005} 1006 1007var _a, _b, _c; 1008const minNodeVersion = (process && process.env && process.env.YARGS_MIN_NODE_VERSION) 1009 ? Number(process.env.YARGS_MIN_NODE_VERSION) 1010 : 12; 1011const nodeVersion = (_b = (_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node) !== null && _b !== void 0 ? _b : (_c = process === null || process === void 0 ? void 0 : process.version) === null || _c === void 0 ? void 0 : _c.slice(1); 1012if (nodeVersion) { 1013 const major = Number(nodeVersion.match(/^([^.]+)/)[1]); 1014 if (major < minNodeVersion) { 1015 throw Error(`yargs parser supports a minimum Node.js version of ${minNodeVersion}. Read our version support policy: https://github.com/yargs/yargs-parser#supported-nodejs-versions`); 1016 } 1017} 1018const env = process ? process.env : {}; 1019const parser = new YargsParser({ 1020 cwd: process.cwd, 1021 env: () => { 1022 return env; 1023 }, 1024 format: util.format, 1025 normalize: path.normalize, 1026 resolve: path.resolve, 1027 require: (path) => { 1028 if (typeof require !== 'undefined') { 1029 return require(path); 1030 } 1031 else if (path.match(/\.json$/)) { 1032 return JSON.parse(fs.readFileSync(path, 'utf8')); 1033 } 1034 else { 1035 throw Error('only .json config files are supported in ESM'); 1036 } 1037 } 1038}); 1039const yargsParser = function Parser(args, opts) { 1040 const result = parser.parse(args.slice(), opts); 1041 return result.argv; 1042}; 1043yargsParser.detailed = function (args, opts) { 1044 return parser.parse(args.slice(), opts); 1045}; 1046yargsParser.camelCase = camelCase; 1047yargsParser.decamelize = decamelize; 1048yargsParser.looksLikeNumber = looksLikeNumber; 1049 1050module.exports = yargsParser; 1051