Skip to content

Commit

Permalink
feat: copy oclif/core ux methods (#537)
Browse files Browse the repository at this point in the history
* feat: copy oclif/core ux methods

* feat: use cli-progress instead of ux.progress

* test: add integration tests for table

* test: remove test

* refactor: use AnyJson for styledObject

* feat!: use next major of oclif/core

BREAKING CHANGE: remove csv, json and yaml from table options

* chore: use ux.stdout from core

* chore: bump @oclif/core

* chore(release): 9.0.3-beta.0 [skip ci]

* chore: bump @oclif/core

* chore(release): 9.0.3-beta.1 [skip ci]

* ci: update preBuildCommands

* ci: update preBuildCommands

* chore: bump core

* chore: bump core

* chore(release): 9.0.14-beta.1 [skip ci]

* fix: core v4

* chore(release): 9.1.1-beta.1 [skip ci]

* test: dont rm oclif/core for external nuts

* test: remove ocilf/core in prebuild

* chore: make new major

* chore(release): 10.0.0-beta.1 [skip ci]

* chore: code review

* style: todo for mutation bug

* test: try slow integration test

* chore: sfdx-core bump for xnuts

* test: re-skip

---------

Co-authored-by: svc-cli-bot <Svc_cli_bot@salesforce.com>
Co-authored-by: mshanemc <shane.mclaughlin@salesforce.com>
  • Loading branch information
3 people committed Jun 5, 2024
1 parent 7072331 commit 97f5584
Show file tree
Hide file tree
Showing 18 changed files with 1,212 additions and 1,174 deletions.
25 changes: 23 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ jobs:
needs: linux-unit-tests
uses: salesforcecli/github-workflows/.github/workflows/unitTestsWindows.yml@main

integration:
needs: linux-unit-tests
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node_version: [lts/*, latest]
exclude:
- os: windows-latest
node_version: lts/*
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node_version }}
cache: yarn
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
- run: yarn build
- run: yarn test:integration

external-nuts-deploy-retrieve:
name: external-nuts-deploy-retrieve
needs: linux-unit-tests
Expand All @@ -38,7 +59,7 @@ jobs:
with:
packageName: '@salesforce/sf-plugins-core'
externalProjectGitUrl: 'https://github.com/salesforcecli/plugin-deploy-retrieve'
preBuildCommands: 'shx rm -rf node_modules/@oclif/core; shx rm -rf node_modules/@salesforce/kit; shx rm -rf node_modules/@salesforce/core; shx rm -rf node_modules/@salesforce/ts-types; shx rm -rf node_modules/@salesforce/cli-plugins-testkit'
preBuildCommands: 'shx rm -rf node_modules/@oclif/core node_modules/@salesforce/kit node_modules/@salesforce/core node_modules/@salesforce/ts-types node_modules/@salesforce/cli-plugins-testkit'
command: ${{ matrix.command }}
os: ${{ matrix.os }}
secrets: inherit
Expand Down Expand Up @@ -67,7 +88,7 @@ jobs:
with:
packageName: '@salesforce/sf-plugins-core'
externalProjectGitUrl: 'https://github.com/salesforcecli/${{matrix.repo}}'
preBuildCommands: 'shx rm -rf node_modules/@oclif/core; shx rm -rf node_modules/@salesforce/kit; shx rm -rf node_modules/@salesforce/core; shx rm -rf node_modules/@salesforce/ts-types'
preBuildCommands: 'shx rm -rf node_modules/@oclif/core node_modules/@salesforce/kit node_modules/@salesforce/core node_modules/@salesforce/ts-types'
command: yarn test:nuts
os: ${{ matrix.os }}
secrets: inherit
1,194 changes: 266 additions & 928 deletions CHANGELOG.md

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@salesforce/sf-plugins-core",
"version": "9.1.1",
"version": "10.0.0-beta.1",
"description": "Utils for writing Salesforce CLI plugins",
"main": "lib/exported",
"types": "lib/exported.d.ts",
Expand All @@ -20,6 +20,7 @@
"prepack": "sf-prepack",
"prepare": "sf-install",
"test": "wireit",
"test:integration": "mocha test/**/*.integration.ts --timeout 30000",
"test:only": "wireit"
},
"exports": {
Expand All @@ -45,15 +46,21 @@
"dependencies": {
"@inquirer/confirm": "^3.1.9",
"@inquirer/password": "^2.1.9",
"@oclif/core": "^3.26.6",
"@salesforce/core": "^7.3.9",
"@oclif/core": "^4",
"@salesforce/core": "^7.3.10",
"@salesforce/kit": "^3.1.2",
"@salesforce/ts-types": "^2.0.9",
"chalk": "^5.3.0"
"ansis": "^3.1.1",
"cli-progress": "^3.12.0",
"natural-orderby": "^3.0.2",
"slice-ansi": "^7.1.0",
"string-width": "^7.1.0",
"terminal-link": "^3.0.0"
},
"devDependencies": {
"@inquirer/type": "^1.3.3",
"@salesforce/dev-scripts": "^9.1.2",
"@types/cli-progress": "^3.11.5",
"eslint-plugin-sf-plugin": "^1.18.5",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
Expand Down
4 changes: 2 additions & 2 deletions src/errorFormatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { Mode, Messages, envVars } from '@salesforce/core';
import type { ChalkInstance } from 'chalk';
import type { Ansis } from 'ansis';
import { StandardColors } from './ux/standardColors.js';
import { SfCommandError } from './types.js';

Expand All @@ -31,7 +31,7 @@ const messages = Messages.loadMessages('@salesforce/sf-plugins-core', 'messages'
*/
export const formatActions = (
actions: string[],
options: { actionColor: ChalkInstance } = { actionColor: StandardColors.info }
options: { actionColor: Ansis } = { actionColor: StandardColors.info }
): string[] =>
actions.length
? [
Expand Down
4 changes: 2 additions & 2 deletions src/errorHandling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { SfError } from '@salesforce/core';
import { OclifError } from '@oclif/core/lib/interfaces/errors.js';
import { CLIError } from '@oclif/core/errors';
import { SfCommandError } from './types.js';
import { removeEmpty } from './util.js';

Expand Down Expand Up @@ -89,5 +89,5 @@ export const errorToSfCommandError = (
});

/** custom typeGuard for handling the fact the SfCommand doesn't know about oclif error structure */
const isOclifError = <T extends Error | SfError | SfCommandError>(e: T): e is T & OclifError =>
const isOclifError = <T extends Error | SfError | SfCommandError>(e: T): e is T & CLIError =>
'oclif' in e ? true : false;
4 changes: 2 additions & 2 deletions src/sfCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export abstract class SfCommand<T> extends Command {
* @param obj The JSON to log.
*/
public styledJSON(obj: AnyJson): void {
this.ux.styledJSON(obj);
this.ux.styledJSON(obj, this.config.theme?.json);
}

/**
Expand All @@ -283,7 +283,7 @@ export abstract class SfCommand<T> extends Command {
// If `--json` is enabled, then the ux instance on the class will disable output, which
// means that the logJson method will not output anything. So, we need to create a new
// instance of the ux class that does not have output disabled in order to log the json.
new Ux().styledJSON(json as AnyJson);
new Ux().styledJSON(json as AnyJson, this.config.theme?.json);
}

/**
Expand Down
12 changes: 8 additions & 4 deletions src/ux/progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as util from 'node:util';
import { ux } from '@oclif/core';
import util from 'node:util';
import { Options, SingleBar } from 'cli-progress';
import { UxBase } from './base.js';

function progress(options: Options = {}): Progress.Bar {
return new SingleBar({ noTTYOutput: Boolean(process.env.TERM === 'dumb' || !process.stdin.isTTY), ...options });
}

/**
* Class for display a progress bar to the console. Will automatically be suppressed if the --json flag is present.
*/
Expand Down Expand Up @@ -50,10 +54,10 @@ export class Progress extends UxBase {

this.maybeNoop(() => {
const { title, ...rest } = { ...Progress.DEFAULT_OPTIONS, ...options };
this.bar = ux.progress({
this.bar = progress({
...rest,
format: util.format(rest.format, title),
}) as Progress.Bar;
});

this.bar.setTotal(total);
this.bar.start(total, 0);
Expand Down
10 changes: 5 additions & 5 deletions src/ux/standardColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import chalk from 'chalk';
import ansis from 'ansis';

export const StandardColors = {
error: chalk.bold.red,
warning: chalk.bold.yellow,
info: chalk.dim,
success: chalk.bold.green,
error: ansis.bold.red,
warning: ansis.bold.yellow,
info: ansis.dim,
success: ansis.bold.green,
};
53 changes: 53 additions & 0 deletions src/ux/styledObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { inspect } from 'node:util';
import ansis from 'ansis';
import { AnyJson } from '@salesforce/ts-types';

function prettyPrint(obj: AnyJson): string {
if (!obj) return inspect(obj);
if (typeof obj === 'string') return obj;
if (typeof obj === 'number') return obj.toString();
if (typeof obj === 'boolean') return obj.toString();
if (typeof obj === 'object') {
return Object.entries(obj)
.map(([key, value]) => `${key}: ${inspect(value)}`)
.join(', ');
}

return inspect(obj);
}

export default function styledObject(obj: AnyJson, keys?: string[]): string {
if (!obj) return inspect(obj);
if (typeof obj === 'string') return obj;
if (typeof obj === 'number') return obj.toString();
if (typeof obj === 'boolean') return obj.toString();

const output: string[] = [];
const keyLengths = Object.keys(obj).map((key) => key.toString().length);
const maxKeyLength = Math.max(...keyLengths) + 2;

const logKeyValue = (key: string, value: AnyJson): string =>
`${ansis.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + prettyPrint(value);

for (const [key, value] of Object.entries(obj)) {
if (keys && !keys.includes(key)) continue;
if (Array.isArray(value)) {
if (value.length > 0) {
output.push(logKeyValue(key, value[0]));
for (const e of value.slice(1)) {
output.push(' '.repeat(maxKeyLength) + prettyPrint(e));
}
}
} else if (value !== null && value !== undefined) {
output.push(logKeyValue(key, value));
}
}

return output.join('\n');
}
Loading

0 comments on commit 97f5584

Please sign in to comment.