ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ /* eslint-disable class-methods-use-this */ 'use strict'; const UTIL = require('util'), PATH = require('path'), EOL = require('os').EOL, Q = require('q'), chalk = require('chalk'), CoaObject = require('./coaobject'), Opt = require('./opt'), Arg = require('./arg'), completion = require('./completion'); /** * Command * * Top level entity. Commands may have options and arguments. * * @namespace * @class Cmd * @extends CoaObject */ class Cmd extends CoaObject { /** * @constructs * @param {COA.Cmd} [cmd] parent command */ constructor(cmd) { super(cmd); this._parent(cmd); this._cmds = []; this._cmdsByName = {}; this._opts = []; this._optsByKey = {}; this._args = []; this._api = null; this._ext = false; } static create(cmd) { return new Cmd(cmd); } /** * Returns object containing all its subcommands as methods * to use from other programs. * * @returns {Object} */ get api() { // Need _this here because of passed arguments into _api const _this = this; this._api || (this._api = function () { return _this.invoke.apply(_this, arguments); }); const cmds = this._cmdsByName; Object.keys(cmds).forEach(cmd => { this._api[cmd] = cmds[cmd].api; }); return this._api; } _parent(cmd) { this._cmd = cmd || this; this.isRootCmd || cmd._cmds.push(this) && this._name && (this._cmd._cmdsByName[this._name] = this); return this; } get isRootCmd() { return this._cmd === this; } /** * Set a canonical command identifier to be used anywhere in the API. * * @param {String} name - command name * @returns {COA.Cmd} - this instance (for chainability) */ name(name) { super.name(name); this.isRootCmd || (this._cmd._cmdsByName[name] = this); return this; } /** * Create new or add existing subcommand for current command. * * @param {COA.Cmd} [cmd] existing command instance * @returns {COA.Cmd} new subcommand instance */ cmd(cmd) { return cmd? cmd._parent(this) : new Cmd(this); } /** * Create option for current command. * * @returns {COA.Opt} new option instance */ opt() { return new Opt(this); } /** * Create argument for current command. * * @returns {COA.Opt} new argument instance */ arg() { return new Arg(this); } /** * Add (or set) action for current command. * * @param {Function} act - action function, * invoked in the context of command instance * and has the parameters: * - {Object} opts - parsed options * - {String[]} args - parsed arguments * - {Object} res - actions result accumulator * It can return rejected promise by Cmd.reject (in case of error) * or any other value treated as result. * @param {Boolean} [force=false] flag for set action instead add to existings * @returns {COA.Cmd} - this instance (for chainability) */ act(act, force) { if(!act) return this; (!this._act || force) && (this._act = []); this._act.push(act); return this; } /** * Make command "helpful", i.e. add -h --help flags for print usage. * * @returns {COA.Cmd} - this instance (for chainability) */ helpful() { return this.opt() .name('help') .title('Help') .short('h') .long('help') .flag() .only() .act(function() { return this.usage(); }) .end(); } /** * Adds shell completion to command, adds "completion" subcommand, * that makes all the magic. * Must be called only on root command. * * @returns {COA.Cmd} - this instance (for chainability) */ completable() { return this.cmd() .name('completion') .apply(completion) .end(); } /** * Allow command to be extendable by external node.js modules. * * @param {String} [pattern] Pattern of node.js module to find subcommands at. * @returns {COA.Cmd} - this instance (for chainability) */ extendable(pattern) { this._ext = pattern || true; return this; } _exit(msg, code) { return process.once('exit', function(exitCode) { msg && console[code === 0 ? 'log' : 'error'](msg); process.exit(code || exitCode || 0); }); } /** * Build full usage text for current command instance. * * @returns {String} usage text */ usage() { const res = []; this._title && res.push(this._fullTitle()); res.push('', 'Usage:'); this._cmds.length && res.push([ '', '', chalk.redBright(this._fullName()), chalk.blueBright('COMMAND'), chalk.greenBright('[OPTIONS]'), chalk.magentaBright('[ARGS]') ].join(' ')); (this._opts.length + this._args.length) && res.push([ '', '', chalk.redBright(this._fullName()), chalk.greenBright('[OPTIONS]'), chalk.magentaBright('[ARGS]') ].join(' ')); res.push( this._usages(this._cmds, 'Commands'), this._usages(this._opts, 'Options'), this._usages(this._args, 'Arguments') ); return res.join(EOL); } _usage() { return chalk.blueBright(this._name) + ' : ' + this._title; } _usages(os, title) { if(!os.length) return; return ['', title + ':'] .concat(os.map(o => ` ${o._usage()}`)) .join(EOL); } _fullTitle() { return `${this.isRootCmd? '' : this._cmd._fullTitle() + EOL}${this._title}`; } _fullName() { return `${this.isRootCmd? '' : this._cmd._fullName() + ' '}${PATH.basename(this._name)}`; } _ejectOpt(opts, opt) { const pos = opts.indexOf(opt); if(pos === -1) return; return opts[pos]._arr? opts[pos] : opts.splice(pos, 1)[0]; } _checkRequired(opts, args) { if(this._opts.some(opt => opt._only && opts.hasOwnProperty(opt._name))) return; const all = this._opts.concat(this._args); let i; while(i = all.shift()) if(i._req && i._checkParsed(opts, args)) return this.reject(i._requiredText()); } _parseCmd(argv, unparsed) { unparsed || (unparsed = []); let i, optSeen = false; while(i = argv.shift()) { i.indexOf('-') || (optSeen = true); if(optSeen || !/^\w[\w-_]*$/.test(i)) { unparsed.push(i); continue; } let pkg, cmd = this._cmdsByName[i]; if(!cmd && this._ext) { if(this._ext === true) { pkg = i; let c = this; while(true) { // eslint-disable-line pkg = c._name + '-' + pkg; if(c.isRootCmd) break; c = c._cmd; } } else if(typeof this._ext === 'string') pkg = ~this._ext.indexOf('%s')? UTIL.format(this._ext, i) : this._ext + i; let cmdDesc; try { cmdDesc = require(pkg); } catch(e) { // Dummy } if(cmdDesc) { if(typeof cmdDesc === 'function') { this.cmd().name(i).apply(cmdDesc).end(); } else if(typeof cmdDesc === 'object') { this.cmd(cmdDesc); cmdDesc.name(i); } else throw new Error('Error: Unsupported command declaration type, ' + 'should be a function or COA.Cmd() object'); cmd = this._cmdsByName[i]; } } if(cmd) return cmd._parseCmd(argv, unparsed); unparsed.push(i); } return { cmd : this, argv : unparsed }; } _parseOptsAndArgs(argv) { const opts = {}, args = {}, nonParsedOpts = this._opts.concat(), nonParsedArgs = this._args.concat(); let res, i; while(i = argv.shift()) { if(i !== '--' && i[0] === '-') { const m = i.match(/^(--\w[\w-_]*)=(.*)$/); if(m) { i = m[1]; this._optsByKey[i]._flag || argv.unshift(m[2]); } const opt = this._ejectOpt(nonParsedOpts, this._optsByKey[i]); if(!opt) return this.reject(`Unknown option: ${i}`); if(Q.isRejected(res = opt._parse(argv, opts))) return res; continue; } i === '--' && (i = argv.splice(0)); Array.isArray(i) || (i = [i]); let a; while(a = i.shift()) { let arg = nonParsedArgs.shift(); if(!arg) return this.reject(`Unknown argument: ${a}`); arg._arr && nonParsedArgs.unshift(arg); if(Q.isRejected(res = arg._parse(a, args))) return res; } } return { opts : this._setDefaults(opts, nonParsedOpts), args : this._setDefaults(args, nonParsedArgs) }; } _setDefaults(params, desc) { for(const item of desc) item._def !== undefined && !params.hasOwnProperty(item._name) && item._saveVal(params, item._def); return params; } _processParams(params, desc) { const notExists = []; for(const item of desc) { const n = item._name; if(!params.hasOwnProperty(n)) { notExists.push(item); continue; } const vals = Array.isArray(params[n])? params[n] : [params[n]]; delete params[n]; let res; for(const v of vals) if(Q.isRejected(res = item._saveVal(params, v))) return res; } return this._setDefaults(params, notExists); } _parseArr(argv) { return Q.when(this._parseCmd(argv), p => Q.when(p.cmd._parseOptsAndArgs(p.argv), r => ({ cmd : p.cmd, opts : r.opts, args : r.args }))); } _do(inputPromise) { return Q.when(inputPromise, input => { return [this._checkRequired] .concat(input.cmd._act || []) .reduce((res, act) => Q.when(res, prev => act.call(input.cmd, input.opts, input.args, prev)), undefined); }); } /** * Parse arguments from simple format like NodeJS process.argv * and run ahead current program, i.e. call process.exit when all actions done. * * @param {String[]} argv - arguments * @returns {COA.Cmd} - this instance (for chainability) */ run(argv) { argv || (argv = process.argv.slice(2)); const cb = code => res => res? this._exit(res.stack || res.toString(), (res.hasOwnProperty('exitCode')? res.exitCode : code) || 0) : this._exit(); Q.when(this.do(argv), cb(0), cb(1)).done(); return this; } /** * Invoke specified (or current) command using provided * options and arguments. * * @param {String|String[]} [cmds] - subcommand to invoke (optional) * @param {Object} [opts] - command options (optional) * @param {Object} [args] - command arguments (optional) * @returns {Q.Promise} */ invoke(cmds, opts, args) { cmds || (cmds = []); opts || (opts = {}); args || (args = {}); typeof cmds === 'string' && (cmds = cmds.split(' ')); if(arguments.length < 3 && !Array.isArray(cmds)) { args = opts; opts = cmds; cmds = []; } return Q.when(this._parseCmd(cmds), p => { if(p.argv.length) return this.reject(`Unknown command: ${cmds.join(' ')}`); return Q.all([ this._processParams(opts, this._opts), this._processParams(args, this._args) ]).spread((_opts, _args) => this._do({ cmd : p.cmd, opts : _opts, args : _args }) .fail(res => (res && res.exitCode === 0)? res.toString() : this.reject(res))); }); } } /** * Convenient function to run command from tests. * * @param {String[]} argv - arguments * @returns {Q.Promise} */ Cmd.prototype.do = function(argv) { return this._do(this._parseArr(argv || [])); }; module.exports = Cmd;