1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.SfdxCommand = exports.Result = void 0;
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | const core_1 = require("@oclif/core");
|
11 | const core_2 = require("@salesforce/core");
|
12 | const kit_1 = require("@salesforce/kit");
|
13 | const ts_types_1 = require("@salesforce/ts-types");
|
14 | const chalk_1 = require("chalk");
|
15 | const docOpts_1 = require("./docOpts");
|
16 | const sfdxFlags_1 = require("./sfdxFlags");
|
17 | const ux_1 = require("./ux");
|
18 | core_2.Messages.importMessagesDirectory(__dirname);
|
19 | const messages = core_2.Messages.load('@salesforce/command', 'command', [
|
20 | 'error.RequiresProject',
|
21 | 'error.RequiresUsername',
|
22 | 'warning.ApiVersionOverride',
|
23 | 'error.InvalidVarargsFormat',
|
24 | 'error.DuplicateVarargs',
|
25 | 'error.VarargsRequired',
|
26 | 'error.RequiresDevhubUsername',
|
27 | ]);
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | class Result {
|
35 | constructor(config = {}) {
|
36 | this.tableColumnData = config.tableColumnData;
|
37 | if (config.display) {
|
38 | this.display = config.display.bind(this);
|
39 | }
|
40 | }
|
41 | display() {
|
42 | if (this.tableColumnData) {
|
43 | if (Array.isArray(this.data) && this.data.length) {
|
44 | this.ux.table(this.data, this.tableColumnData);
|
45 | }
|
46 | else {
|
47 | this.ux.log('No results found.');
|
48 | }
|
49 | }
|
50 | }
|
51 | }
|
52 | exports.Result = Result;
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | class SfdxCommand extends core_1.Command {
|
62 | constructor() {
|
63 | super(...arguments);
|
64 |
|
65 | this.lifecycleEventNames = [];
|
66 | this.isJson = false;
|
67 | }
|
68 |
|
69 |
|
70 |
|
71 |
|
72 | static get flags() {
|
73 | return (0, sfdxFlags_1.buildSfdxFlags)(this.flagsConfig, {
|
74 | targetdevhubusername: this.supportsDevhubUsername || this.requiresDevhubUsername,
|
75 | targetusername: this.supportsUsername || this.requiresUsername,
|
76 | });
|
77 | }
|
78 | static get usage() {
|
79 | return docOpts_1.DocOpts.generate(this);
|
80 | }
|
81 |
|
82 | get statics() {
|
83 | return this.constructor;
|
84 | }
|
85 | static getVarArgsConfig() {
|
86 | if ((0, ts_types_1.isBoolean)(this.varargs)) {
|
87 | return this.varargs ? {} : undefined;
|
88 | }
|
89 |
|
90 | return Object.assign({}, this.varargs);
|
91 | }
|
92 | async _run() {
|
93 |
|
94 |
|
95 | if (!this.statics.result.tableColumnData && this.statics.tableColumnData) {
|
96 | this.statics.result.tableColumnData = this.statics.tableColumnData;
|
97 | }
|
98 | this.result = new Result(this.statics.result);
|
99 | let err;
|
100 | try {
|
101 | await this.init();
|
102 | return (this.result.data = await this.run());
|
103 | }
|
104 | catch (e) {
|
105 | err = e;
|
106 | await this.catch(e);
|
107 | }
|
108 | finally {
|
109 | await this.finally(err);
|
110 | }
|
111 | }
|
112 |
|
113 | async assignProject() {
|
114 |
|
115 |
|
116 | try {
|
117 | this.project = await core_2.SfProject.resolve();
|
118 | }
|
119 | catch (err) {
|
120 | if (err instanceof Error && err.name === 'InvalidProjectWorkspace') {
|
121 | throw messages.createError('error.RequiresProject');
|
122 | }
|
123 | throw err;
|
124 | }
|
125 | }
|
126 |
|
127 | async assignOrg() {
|
128 |
|
129 | try {
|
130 | this.org = await core_2.Org.create({
|
131 | aliasOrUsername: this.flags.targetusername,
|
132 | aggregator: this.configAggregator,
|
133 | });
|
134 | if (typeof this.flags.apiversion === 'string') {
|
135 | this.org.getConnection().setApiVersion(this.flags.apiversion);
|
136 | }
|
137 | }
|
138 | catch (err) {
|
139 | if (this.statics.requiresUsername) {
|
140 | if (err instanceof Error && (err.name === 'NoUsernameFoundError' || err.name === 'AuthInfoCreationError')) {
|
141 | throw messages.createError('error.RequiresUsername');
|
142 | }
|
143 | throw err;
|
144 | }
|
145 | }
|
146 | }
|
147 |
|
148 | async assignHubOrg() {
|
149 |
|
150 | try {
|
151 | this.hubOrg = await core_2.Org.create({
|
152 | aliasOrUsername: this.flags.targetdevhubusername,
|
153 | aggregator: this.configAggregator,
|
154 | isDevHub: true,
|
155 | });
|
156 | if (typeof this.flags.apiversion === 'string') {
|
157 | this.hubOrg.getConnection().setApiVersion(this.flags.apiversion);
|
158 | }
|
159 | }
|
160 | catch (err) {
|
161 |
|
162 |
|
163 | if (this.statics.requiresDevhubUsername && err instanceof Error) {
|
164 | if (err.name === 'AuthInfoCreationError' || err.name === 'NoUsernameFoundError') {
|
165 | throw messages.createError('error.RequiresDevhubUsername');
|
166 | }
|
167 | throw core_2.SfError.wrap(err);
|
168 | }
|
169 | }
|
170 | }
|
171 | shouldEmitHelp() {
|
172 |
|
173 |
|
174 | if (!this.argv.includes('-h')) {
|
175 |
|
176 | return false;
|
177 | }
|
178 |
|
179 | const flags = this.statics.flags || {};
|
180 | for (const k of Object.keys(flags)) {
|
181 | if (k !== 'help' && flags[k].char === 'h') {
|
182 |
|
183 | return false;
|
184 | }
|
185 | }
|
186 |
|
187 | return true;
|
188 | }
|
189 | async init() {
|
190 |
|
191 |
|
192 | process.exitCode = 0;
|
193 |
|
194 |
|
195 | const isContentTypeJSON = kit_1.env.getString('SFDX_CONTENT_TYPE', '').toUpperCase() === 'JSON';
|
196 | this.isJson = this.argv.includes('--json') || isContentTypeJSON;
|
197 |
|
198 |
|
199 |
|
200 | const loglevel = this.argv.join(' ').match(/--loglevel\s*=?\s*([a-z]+)/);
|
201 | if (loglevel) {
|
202 | (await core_2.Logger.root()).setLevel(core_2.Logger.getLevelByName(loglevel[1]));
|
203 | }
|
204 | await this.initLoggerAndUx();
|
205 |
|
206 | if (this.shouldEmitHelp()) {
|
207 | const Help = await (0, core_1.loadHelpClass)(this.config);
|
208 |
|
209 | const help = new Help(this.config, this.config.pjson.helpOptions);
|
210 | try {
|
211 |
|
212 | await help.showCommandHelp(this.statics, []);
|
213 | }
|
214 | catch {
|
215 |
|
216 | await help.showHelp(this.argv);
|
217 | }
|
218 | return this.exit(0);
|
219 | }
|
220 |
|
221 | await super.init();
|
222 |
|
223 | const strict = this.statics.varargs ? !this.statics.varargs : this.statics.strict;
|
224 |
|
225 | const { args, flags, argv } = await this.parse({
|
226 | flags: this.statics.flags,
|
227 | args: this.statics.args,
|
228 | strict,
|
229 | });
|
230 | this.flags = flags;
|
231 | this.args = args;
|
232 |
|
233 | if (isContentTypeJSON) {
|
234 | this.flags.json = true;
|
235 | }
|
236 | this.warnIfDeprecated();
|
237 |
|
238 | if (this.statics.varargs) {
|
239 | const argVals = Object.values(args);
|
240 | const varargs = argv.filter((val) => !argVals.includes(val));
|
241 | this.varargs = this.parseVarargs(varargs);
|
242 | }
|
243 | this.logger.info(`Running command [${this.statics.name}] with flags [${JSON.stringify(flags)}] and args [${JSON.stringify(args)}]`);
|
244 |
|
245 |
|
246 |
|
247 | this.configAggregator = await core_2.SfdxConfigAggregator.create();
|
248 |
|
249 | if (this.statics.requiresProject) {
|
250 | await this.assignProject();
|
251 | }
|
252 |
|
253 |
|
254 | const apiVersion = this.configAggregator.getInfo('apiVersion');
|
255 | if (apiVersion?.value && !flags.apiversion) {
|
256 | this.ux.warn(messages.getMessage('warning.ApiVersionOverride', [JSON.stringify(apiVersion.value)]));
|
257 | }
|
258 |
|
259 | if (this.statics.supportsUsername || this.statics.requiresUsername) {
|
260 | await this.assignOrg();
|
261 | }
|
262 |
|
263 | if (this.statics.supportsDevhubUsername || this.statics.requiresDevhubUsername) {
|
264 | await this.assignHubOrg();
|
265 | }
|
266 |
|
267 | await this.hooksFromLifecycleEvent(this.lifecycleEventNames);
|
268 | }
|
269 |
|
270 | async catch(err) {
|
271 |
|
272 | if (err.code === 'EEXIT') {
|
273 | throw err;
|
274 | }
|
275 |
|
276 |
|
277 |
|
278 | if (err instanceof Error) {
|
279 | err.name = err.name === 'SfError' ? 'SfError' : err.name.replace(/Error$/, '');
|
280 | }
|
281 | await this.initLoggerAndUx();
|
282 |
|
283 | const error = core_2.SfError.wrap(err);
|
284 | error.setContext(this.statics.name);
|
285 |
|
286 |
|
287 | process.exitCode = process.exitCode || error.exitCode || 1;
|
288 | const userDisplayError = Object.assign({ result: error.data, status: error.exitCode }, {
|
289 | ...error.toObject(),
|
290 | stack: error.fullStack ?? error.stack,
|
291 | warnings: Array.from(ux_1.UX.warnings),
|
292 |
|
293 | commandName: error.context,
|
294 | });
|
295 | if (this.isJson) {
|
296 |
|
297 | const sendToStdout = kit_1.env.getBoolean('SFDX_JSON_TO_STDOUT', true);
|
298 | if (sendToStdout) {
|
299 | this.ux.logJson(userDisplayError);
|
300 | }
|
301 | else {
|
302 | this.ux.errorJson(userDisplayError);
|
303 | }
|
304 | }
|
305 | else {
|
306 | this.ux.error(...this.formatError(error));
|
307 | if (err.data) {
|
308 | this.result.data = err.data;
|
309 | this.result.display();
|
310 | }
|
311 | }
|
312 |
|
313 |
|
314 |
|
315 |
|
316 | process.emit('cmdError', err, Object.assign({}, this.flags, this.varargs), this.org ?? this.hubOrg);
|
317 | }
|
318 |
|
319 | async finally(err) {
|
320 |
|
321 | if (!err) {
|
322 | if (this.isJson) {
|
323 | let output = this.getJsonResultObject();
|
324 | if (ux_1.UX.warnings.size > 0) {
|
325 | output = Object.assign(output, {
|
326 | warnings: Array.from(ux_1.UX.warnings),
|
327 | });
|
328 | }
|
329 | this.ux.logJson(output);
|
330 | }
|
331 | else {
|
332 | this.result.display();
|
333 | }
|
334 | }
|
335 | }
|
336 |
|
337 | warnIfDeprecated() {
|
338 | if (this.statics.deprecated) {
|
339 | let def;
|
340 | if ((0, ts_types_1.has)(this.statics.deprecated, 'version')) {
|
341 | def = {
|
342 | name: this.statics.name,
|
343 | type: 'command',
|
344 | ...this.statics.deprecated,
|
345 | };
|
346 | }
|
347 | else {
|
348 | def = this.statics.deprecated;
|
349 | }
|
350 | this.ux.warn(ux_1.UX.formatDeprecationWarning(def));
|
351 | }
|
352 | if (this.statics.flagsConfig) {
|
353 |
|
354 | for (const flag of Object.keys(this.flags)) {
|
355 | const def = this.statics.flagsConfig[flag];
|
356 | if (def?.deprecated) {
|
357 | this.ux.warn(ux_1.UX.formatDeprecationWarning({
|
358 | name: flag,
|
359 | type: 'flag',
|
360 | ...def.deprecated,
|
361 | }));
|
362 | }
|
363 | }
|
364 | }
|
365 | }
|
366 | getJsonResultObject(result = this.result.data, status = process.exitCode ?? 0) {
|
367 | return { status, result };
|
368 | }
|
369 | parseVarargs(args = []) {
|
370 | const varargs = {};
|
371 | const descriptor = this.statics.varargs;
|
372 |
|
373 | if (!args.length && !(0, ts_types_1.isBoolean)(descriptor) && descriptor.required) {
|
374 | throw messages.createError('error.VarargsRequired');
|
375 | }
|
376 |
|
377 | args.forEach((arg) => {
|
378 | const split = arg.split('=');
|
379 | if (split.length !== 2) {
|
380 | throw messages.createError('error.InvalidVarargsFormat', [arg]);
|
381 | }
|
382 | const [name, value] = split;
|
383 | if (varargs[name]) {
|
384 | throw messages.createError('error.DuplicateVarargs', [name]);
|
385 | }
|
386 | if (!(0, ts_types_1.isBoolean)(descriptor) && descriptor.validator) {
|
387 | descriptor.validator(name, value);
|
388 | }
|
389 | varargs[name] = value || undefined;
|
390 | });
|
391 | return varargs;
|
392 | }
|
393 | |
394 |
|
395 |
|
396 |
|
397 |
|
398 |
|
399 |
|
400 | formatError(error) {
|
401 | const colorizedArgs = [];
|
402 | const commandName = this.id ?? error.context;
|
403 | const runningWith = commandName ? ` running ${commandName}` : '';
|
404 | colorizedArgs.push(chalk_1.default.bold(`ERROR${runningWith}: `));
|
405 | colorizedArgs.push(chalk_1.default.red(error.message));
|
406 |
|
407 | if ((0, ts_types_1.get)(error, 'actions.length')) {
|
408 | colorizedArgs.push(`\n\n${chalk_1.default.blue(chalk_1.default.bold('Try this:'))}`);
|
409 | if (error.actions) {
|
410 | error.actions.forEach((action) => {
|
411 | colorizedArgs.push(`\n${chalk_1.default.red(action)}`);
|
412 | });
|
413 | }
|
414 | }
|
415 |
|
416 | const stack = error.fullStack ?? error.stack;
|
417 | if (stack && core_2.Global.getEnvironmentMode() === core_2.Mode.DEVELOPMENT) {
|
418 | colorizedArgs.push(chalk_1.default.red(`\n*** Internal Diagnostic ***\n\n${stack}\n******\n`));
|
419 | }
|
420 | return colorizedArgs;
|
421 | }
|
422 | |
423 |
|
424 |
|
425 | async initLoggerAndUx() {
|
426 | if (!this.logger) {
|
427 | this.logger = await core_2.Logger.child(this.statics.name);
|
428 | }
|
429 | if (!this.ux) {
|
430 | this.ux = new ux_1.UX(this.logger, !this.isJson);
|
431 | }
|
432 | if (this.result && !this.result.ux) {
|
433 | this.result.ux = this.ux;
|
434 | }
|
435 | }
|
436 | |
437 |
|
438 |
|
439 | async hooksFromLifecycleEvent(lifecycleEventNames) {
|
440 | const options = {
|
441 | Command: this.ctor,
|
442 | argv: this.argv,
|
443 | commandId: this.id,
|
444 | };
|
445 | const lifecycle = core_2.Lifecycle.getInstance();
|
446 | lifecycleEventNames.forEach((eventName) => {
|
447 | lifecycle.on(eventName, async (result) => {
|
448 | await this.config.runHook(eventName, Object.assign(options, { result }));
|
449 | });
|
450 | });
|
451 | }
|
452 | }
|
453 | exports.SfdxCommand = SfdxCommand;
|
454 |
|
455 | SfdxCommand.supportsUsername = false;
|
456 |
|
457 |
|
458 | SfdxCommand.requiresUsername = false;
|
459 |
|
460 | SfdxCommand.supportsDevhubUsername = false;
|
461 |
|
462 |
|
463 | SfdxCommand.requiresDevhubUsername = false;
|
464 |
|
465 | SfdxCommand.requiresProject = false;
|
466 |
|
467 |
|
468 | SfdxCommand.result = {};
|
469 |
|
470 | SfdxCommand.varargs = false;
|
471 |
|
\ | No newline at end of file |