UNPKG

5.38 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const cli_framework_1 = require("@ionic/cli-framework");
4const utils_terminal_1 = require("@ionic/utils-terminal");
5const guards_1 = require("../guards");
6const color_1 = require("./color");
7const logger_1 = require("./utils/logger");
8class Command extends cli_framework_1.BaseCommand {
9 constructor(namespace) {
10 super(namespace);
11 this.namespace = namespace;
12 this.taskChains = [];
13 }
14 get env() {
15 return this.namespace.root.env;
16 }
17 get project() {
18 return this.namespace.root.project;
19 }
20 createTaskChain() {
21 let output;
22 const formatter = logger_1.createFormatter();
23 if (this.env.flags.interactive) {
24 output = new cli_framework_1.LogUpdateOutputStrategy();
25 this.env.log.handlers = new Set([new cli_framework_1.StreamHandler({ stream: output.stream, formatter })]);
26 }
27 else {
28 this.env.log.handlers = logger_1.createDefaultLoggerHandlers();
29 output = new cli_framework_1.StreamOutputStrategy({ stream: this.env.log.createWriteStream(cli_framework_1.LOGGER_LEVELS.INFO, false) });
30 }
31 const chain = output.createTaskChain();
32 this.taskChains.push(chain);
33 chain.on('end', () => {
34 this.env.log.handlers = logger_1.createDefaultLoggerHandlers();
35 });
36 return chain;
37 }
38 async execute(inputs, options, runinfo) {
39 if (guards_1.isCommandPreRun(this)) {
40 await this.preRun(inputs, options, runinfo);
41 }
42 try {
43 await this.validate(inputs);
44 }
45 catch (e) {
46 if (!this.env.flags.interactive) {
47 this.env.log.warn(`Command ran non-interactively due to ${color_1.input('--no-interactive')} flag, CI being detected, non-TTY, or a config setting.`);
48 }
49 throw e;
50 }
51 const runPromise = this.run(inputs, options, runinfo);
52 const telemetryPromise = (async () => {
53 if (this.env.config.get('telemetry') !== false && !utils_terminal_1.TERMINAL_INFO.ci && utils_terminal_1.TERMINAL_INFO.tty) {
54 const { Telemetry } = await Promise.resolve().then(() => require('./telemetry'));
55 let cmdInputs = [];
56 const metadata = await this.getMetadata();
57 if (metadata.name === 'login' || metadata.name === 'logout') {
58 // This is a hack to wait until the selected commands complete before
59 // sending telemetry data. These commands update `this.env` in some
60 // way, which is used in the `Telemetry` instance.
61 await runPromise;
62 }
63 else if (metadata.name === 'completion') {
64 // Ignore telemetry for these commands.
65 return;
66 }
67 else if (metadata.name === 'help') {
68 cmdInputs = inputs;
69 }
70 else {
71 cmdInputs = await this.getCleanInputsForTelemetry(inputs, options);
72 }
73 const cmd = this;
74 const path = await cli_framework_1.generateCommandPath(cmd);
75 const telemetry = new Telemetry({ client: this.env.client, config: this.env.config, getInfo: this.env.getInfo, ctx: this.env.ctx, project: this.project, session: this.env.session });
76 await telemetry.sendCommand(path.map(([p]) => p).join(' '), cmdInputs);
77 }
78 })();
79 await Promise.all([runPromise, telemetryPromise]);
80 }
81 async getCleanInputsForTelemetry(inputs, options) {
82 const initialOptions = { _: [] };
83 const metadata = await this.getMetadata();
84 const filteredInputs = inputs.map((input, i) => metadata.inputs && (metadata.inputs[i] && metadata.inputs[i].private) ? '*****' : input);
85 const filteredOptions = Object.keys(options)
86 .filter(optionName => {
87 if (optionName === '_') {
88 return false;
89 }
90 const metadataOption = metadata.options && metadata.options.find(o => {
91 return o.name === optionName || (typeof o.aliases !== 'undefined' && o.aliases.includes(optionName));
92 });
93 if (metadataOption && metadataOption.aliases && metadataOption.aliases.includes(optionName)) {
94 return false; // exclude aliases
95 }
96 if (!metadataOption) {
97 return true; // include unknown options
98 }
99 if (metadataOption.private) {
100 return false; // exclude private options
101 }
102 if (typeof metadataOption.default !== 'undefined' && metadataOption.default === options[optionName]) {
103 return false; // exclude options that match their default value (means it wasn't supplied by user)
104 }
105 return true;
106 })
107 .reduce((allOptions, optionName) => {
108 allOptions[optionName] = options[optionName];
109 return allOptions;
110 }, initialOptions);
111 const optionInputs = cli_framework_1.unparseArgs(filteredOptions, { useDoubleQuotes: true });
112 return filteredInputs.concat(optionInputs);
113 }
114}
115exports.Command = Command;