Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: export Ux and add configAggregator to SfCommand #106

Merged
merged 7 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"/messages"
],
"dependencies": {
"@oclif/core": "^1.16.4",
"@oclif/core": "^1.19.0",
"@salesforce/core": "^3.30.9",
"@salesforce/kit": "^1.7.0",
"@salesforce/ts-types": "^1.5.20",
Expand Down Expand Up @@ -71,4 +71,4 @@
"publishConfig": {
"access": "public"
}
}
}
2 changes: 1 addition & 1 deletion src/exported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Flags as OclifFlags } from '@oclif/core';
export { toHelpSection, parseVarArgs } from './util';
export { Deployable, Deployer, DeployerResult } from './deployer';
export { Deauthorizer } from './deauthorizer';
export { Progress, Prompter, generateTableChoices } from './ux';
export { Progress, Prompter, generateTableChoices, Ux } from './ux';
export { SfHook } from './hooks';
export * from './types';
export { SfCommand, SfCommandInterface, StandardColors } from './sfCommand';
Expand Down
3 changes: 2 additions & 1 deletion src/flags/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export type DurationFlagConfig = {
*/
export const durationFlag = Flags.custom<Duration, DurationFlagConfig>({
parse: async (input, _, opts) => validate(input, opts),
default: async (context) => context.options.defaultValue ? toDuration(context.options.defaultValue, context.options.unit) : undefined,
default: async (context) =>
context.options.defaultValue ? toDuration(context.options.defaultValue, context.options.unit) : undefined,
});

const validate = (input: string, config: DurationFlagConfig): Duration => {
Expand Down
42 changes: 40 additions & 2 deletions src/sfCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import {
Mode,
EnvironmentVariable,
SfError,
ConfigAggregator,
SfdxConfigAggregator,
} from '@salesforce/core';
import { env } from '@salesforce/kit';
import { AnyJson } from '@salesforce/ts-types';
import * as chalk from 'chalk';
import { Progress, Prompter, Spinner, Ux } from './ux';
Expand Down Expand Up @@ -158,6 +161,34 @@ export abstract class SfCommand<T> extends Command {
public progress: Progress;
public project!: SfProject;

/**
* ConfigAggregator instance for accessing global and local configuration.
*
* NOTE: If the active executable is sfdx, this will be an instance of SfdxConfigAggregator, which supports
* the deprecated sfdx config vars like defaultusername, defaultdevhubusername, apiversion, etc. Otherwise,
* it will be an instance of ConfigAggregator will only supports the config vars introduce by @salesforce/core@v3.
*
* The executable is determined by `this.config.bin` which is supplied by the base oclif/core Command class. The value
* of `this.config.bin` will be the executable running (e.g. sfdx or sf) or, for local development (e.g. using bin/dev),
* it will be the value of oclif.bin in the plugin's package.json.
*
* If you need to write NUTS for a plugin that needs to work with both sets of config vars you can
* use set the `SF_USE_DEPRECATED_CONFIG_VARS` to `true` to force configAggregator to be an instance of SfdxConfigAggregator or
* `false` to force configAggregator to be an instance of ConfigAggregator.
*
* @example
* ```
* import { execCmd } from '@salesforce/cli-plugins-testkit';
* execCmd('config:set [email protected]', {
* env: {
* ...process.env,
* SF_USE_DEPRECATED_CONFIG_VARS: true,
* }
* })
* ```
*/
public configAggregator!: ConfigAggregator;

private warnings: SfCommand.Warning[] = [];
private ux: Ux;
private prompter: Prompter;
Expand All @@ -166,10 +197,10 @@ export abstract class SfCommand<T> extends Command {
public constructor(argv: string[], config: Config) {
super(argv, config);
const outputEnabled = !this.jsonEnabled();
this.spinner = new Spinner(outputEnabled);
this.progress = new Progress(outputEnabled && envVars.getBoolean(EnvironmentVariable.SF_USE_PROGRESS_BAR, true));
this.ux = new Ux(outputEnabled);
this.prompter = new Prompter();
this.spinner = this.ux.spinner;
this.prompter = this.ux.prompter;
this.lifecycle = Lifecycle.getInstance();
}

Expand Down Expand Up @@ -329,6 +360,13 @@ export abstract class SfCommand<T> extends Command {
}

public async _run<R>(): Promise<R | undefined> {
this.configAggregator =
this.config.bin === 'sfdx' ??
env.getBoolean('SF_USE_DEPRECATED_CONFIG_VARS') ??
env.getBoolean('SFDX_USE_DEPRECATED_CONFIG_VARS')
? await SfdxConfigAggregator.create()
: await ConfigAggregator.create();

if (this.statics.requiresProject) {
this.project = await this.assignProject();
}
Expand Down
2 changes: 1 addition & 1 deletion src/ux/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { AnyFunction } from '@salesforce/ts-types';

export class UxBase {
public constructor(protected outputEnabled: boolean) {}
public constructor(public readonly outputEnabled: boolean) {}

protected maybeNoop(fn: AnyFunction<unknown>): void {
if (this.outputEnabled) fn();
Expand Down
78 changes: 75 additions & 3 deletions src/ux/ux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,100 @@
import { CliUx } from '@oclif/core';
import { AnyJson } from '@salesforce/ts-types';
import { UxBase } from './base';
import { Prompter } from './prompter';
import { Spinner } from './spinner';

/**
* UX methods for plugins. Automatically suppress console output if outputEnabled is set to false.
*
* @example
* ```
* import { SfCommand, Ux } from '@salesforce/sf-plugins-core';
* import { AnyJson } from '@salesforce/ts-types';
*
* class MyCommand extends SfCommand<AnyJson> {
* public async run(): Promise<AnyJson> {
* const ux = new Ux(!this.jsonEnabled());
* }
* }
*
* ```
*/
export class Ux extends UxBase {
public constructor(outputEnabled: boolean) {
public spinner: Spinner;
public prompter: Prompter;

public constructor(public readonly outputEnabled: boolean) {
super(outputEnabled);
this.spinner = new Spinner(outputEnabled);
this.prompter = new Prompter();
}

/**
* Log a message to the console. This will be automatically suppressed if output is disabled.
*
* @param message Message to log. Formatting is supported.
* @param args Args to be used for formatting.
*/
public log(message?: string, ...args: string[]): void {
this.maybeNoop(() => CliUx.ux.log(message, ...args));
}

/**
* Log a warning message to the console. This will be automatically suppressed if output is disabled.
*
* @param message Warning message to log.
*/
public warn(message: string | Error): void {
this.maybeNoop(() => CliUx.ux.warn(message));
}

/**
* Display a table to the console. This will be automatically suppressed if output is disabled.
*
* @param data Data to be displayed
* @param columns Columns to display the data in
* @param options Options for how the table should be displayed
*/
public table<T extends Ux.Table.Data>(data: T[], columns: Ux.Table.Columns<T>, options?: Ux.Table.Options): void {
this.maybeNoop(() => CliUx.ux.table(data, columns, options));
}

/**
* Display a url to the console. This will be automatically suppressed if output is disabled.
*
* @param text text to display
* @param uri URL link
* @param params
*/
public url(text: string, uri: string, params = {}): void {
this.maybeNoop(() => CliUx.ux.url(text, uri, params));
}

/**
* Display stylized JSON to the console. This will be automatically suppressed if output is disabled.
*
* @param obj JSON to display
*/
public styledJSON(obj: AnyJson): void {
this.maybeNoop(() => CliUx.ux.styledJSON(obj));
}

public styledObject(obj: AnyJson): void {
this.maybeNoop(() => CliUx.ux.styledObject(obj));
/**
* Display stylized object to the console. This will be automatically suppressed if output is disabled.
*
* @param obj Object to display
* @param keys Keys of object to display
*/
public styledObject(obj: AnyJson, keys?: string[]): void {
this.maybeNoop(() => CliUx.ux.styledObject(obj, keys));
}

/**
* Display stylized header to the console. This will be automatically suppressed if output is disabled.
*
* @param text header to display
*/
public styledHeader(text: string): void {
this.maybeNoop(() => CliUx.ux.styledHeader(text));
}
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,10 @@
is-wsl "^2.1.1"
tslib "^2.0.0"

"@oclif/core@^1.16.4", "@oclif/core@^1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.18.0.tgz#93c790c663c6b24a609d1ea44362f5438cb19d73"
integrity sha512-12SWbbDbMrhBmEuN9cOQkbN+sFUKlSTw+NlCPVVIg3uEhnmkXgx2wZJtCN4c+IBMJjC27L9lDneeoe70yQuiVg==
"@oclif/core@^1.18.0", "@oclif/core@^1.19.0":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.19.0.tgz#b2e5260c2344e5905312efd7538daacaedb75cbf"
integrity sha512-4R087E3TAG6Q9cvr+4wnlryHbciioXkZmUF/Qmc08dReoFus1BIfwtR5kUa/thNmQBw5oeGnrxnl9yA/TaxAmA==
dependencies:
"@oclif/linewrap" "^1.0.0"
"@oclif/screen" "^3.0.2"
Expand Down