UNPKG

5.25 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const pjson = require('../package.json');
4const Config = require("@oclif/config");
5const Errors = require("@oclif/errors");
6const util_1 = require("util");
7const util_2 = require("./util");
8const plugin_help_1 = require("@oclif/plugin-help");
9/**
10 * swallows stdout epipe errors
11 * this occurs when stdout closes such as when piping to head
12 */
13process.stdout.on('error', err => {
14 if (err && err.code === 'EPIPE')
15 return;
16 throw err;
17});
18/**
19 * An abstract class which acts as the base for each command
20 * in your project.
21 */
22class Command {
23 constructor(argv, config) {
24 this.argv = argv;
25 this.config = config;
26 this.id = this.ctor.id;
27 try {
28 this.debug = require('debug')(this.id ? `${this.config.bin}:${this.id}` : this.config.bin);
29 }
30 catch (_a) {
31 this.debug = () => { };
32 }
33 }
34 get ctor() {
35 return this.constructor;
36 }
37 async _run() {
38 let err;
39 try {
40 // remove redirected env var to allow subsessions to run autoupdated client
41 delete process.env[this.config.scopedEnvVarKey('REDIRECTED')];
42 await this.init();
43 return await this.run();
44 }
45 catch (error) {
46 err = error;
47 await this.catch(error);
48 }
49 finally {
50 await this.finally(err);
51 }
52 }
53 exit(code = 0) {
54 return Errors.exit(code);
55 }
56 warn(input) {
57 Errors.warn(input);
58 }
59 error(input, options = {}) {
60 return Errors.error(input, options);
61 }
62 log(message = '', ...args) {
63 // tslint:disable-next-line strict-type-predicates
64 message = typeof message === 'string' ? message : util_1.inspect(message);
65 process.stdout.write(util_1.format(message, ...args) + '\n');
66 }
67 async init() {
68 this.debug('init version: %s argv: %o', this.ctor._base, this.argv);
69 if (this.config.debug)
70 Errors.config.debug = true;
71 if (this.config.errlog)
72 Errors.config.errlog = this.config.errlog;
73 // global['cli-ux'].context = global['cli-ux'].context || {
74 // command: compact([this.id, ...this.argv]).join(' '),
75 // version: this.config.userAgent,
76 // }
77 const g = global;
78 g['http-call'] = g['http-call'] || {};
79 g['http-call'].userAgent = this.config.userAgent;
80 if (this._helpOverride())
81 return this._help();
82 }
83 parse(options, argv = this.argv) {
84 if (!options)
85 options = this.constructor;
86 return require('@oclif/parser').parse(argv, Object.assign({ context: this }, options));
87 }
88 async catch(err) {
89 if (!err.message)
90 throw err;
91 if (err.message.match(/Unexpected arguments?: (-h|--help|help)(,|\n)/)) {
92 return this._help();
93 }
94 if (err.message.match(/Unexpected arguments?: (-v|--version|version)(,|\n)/)) {
95 return this._version();
96 }
97 try {
98 const { cli } = require('cli-ux');
99 const chalk = require('chalk'); // eslint-disable-line node/no-extraneous-require
100 cli.action.stop(chalk.bold.red('!'));
101 }
102 catch (_a) { }
103 throw err;
104 }
105 async finally(_) {
106 try {
107 const config = require('@oclif/errors').config;
108 if (config.errorLogger)
109 await config.errorLogger.flush();
110 // tslint:disable-next-line no-console
111 }
112 catch (error) {
113 console.error(error);
114 }
115 }
116 _help() {
117 const HelpClass = plugin_help_1.getHelpClass(this.config);
118 const help = new HelpClass(this.config);
119 const cmd = Config.Command.toCached(this.ctor);
120 if (!cmd.id)
121 cmd.id = '';
122 let topics = this.config.topics;
123 topics = topics.filter((t) => !t.hidden);
124 topics = util_2.sortBy(topics, (t) => t.name);
125 topics = util_2.uniqBy(topics, (t) => t.name);
126 help.showCommandHelp(cmd, topics);
127 return this.exit(0);
128 }
129 _helpOverride() {
130 for (const arg of this.argv) {
131 if (arg === '--help')
132 return true;
133 if (arg === '--')
134 return false;
135 }
136 return false;
137 }
138 _version() {
139 this.log(this.config.userAgent);
140 return this.exit(0);
141 }
142}
143exports.default = Command;
144Command._base = `${pjson.name}@${pjson.version}`;
145/** An array of aliases for this command */
146Command.aliases = [];
147/** When set to false, allows a variable amount of arguments */
148Command.strict = true;
149Command.parse = true;
150Command.parserOptions = {};
151/**
152 * instantiate and run the command
153 * @param {Config.Command.Class} this Class
154 * @param {string[]} argv argv
155 * @param {Config.LoadOptions} opts options
156 */
157Command.run = async function (argv, opts) {
158 if (!argv)
159 argv = process.argv.slice(2);
160 const config = await Config.load(opts || (module.parent && module.parent.parent && module.parent.parent.filename) || __dirname);
161 const cmd = new this(argv, config);
162 return cmd._run(argv);
163};