Skip to content

Commit 97f5584

Browse files
mdonnalleysvc-cli-botmshanemc
authored
feat: copy oclif/core ux methods (#537)
* 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>
1 parent 7072331 commit 97f5584

18 files changed

+1212
-1174
lines changed

.github/workflows/test.yml

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@ jobs:
1717
needs: linux-unit-tests
1818
uses: salesforcecli/github-workflows/.github/workflows/unitTestsWindows.yml@main
1919

20+
integration:
21+
needs: linux-unit-tests
22+
strategy:
23+
matrix:
24+
os: [ubuntu-latest, windows-latest]
25+
node_version: [lts/*, latest]
26+
exclude:
27+
- os: windows-latest
28+
node_version: lts/*
29+
fail-fast: false
30+
runs-on: ${{ matrix.os }}
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: actions/setup-node@v4
34+
with:
35+
node-version: ${{ matrix.node_version }}
36+
cache: yarn
37+
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
38+
- run: yarn build
39+
- run: yarn test:integration
40+
2041
external-nuts-deploy-retrieve:
2142
name: external-nuts-deploy-retrieve
2243
needs: linux-unit-tests
@@ -38,7 +59,7 @@ jobs:
3859
with:
3960
packageName: '@salesforce/sf-plugins-core'
4061
externalProjectGitUrl: 'https://github.com/salesforcecli/plugin-deploy-retrieve'
41-
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'
62+
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'
4263
command: ${{ matrix.command }}
4364
os: ${{ matrix.os }}
4465
secrets: inherit
@@ -67,7 +88,7 @@ jobs:
6788
with:
6889
packageName: '@salesforce/sf-plugins-core'
6990
externalProjectGitUrl: 'https://github.com/salesforcecli/${{matrix.repo}}'
70-
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'
91+
preBuildCommands: 'shx rm -rf node_modules/@oclif/core node_modules/@salesforce/kit node_modules/@salesforce/core node_modules/@salesforce/ts-types'
7192
command: yarn test:nuts
7293
os: ${{ matrix.os }}
7394
secrets: inherit

CHANGELOG.md

Lines changed: 266 additions & 928 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@salesforce/sf-plugins-core",
3-
"version": "9.1.1",
3+
"version": "10.0.0-beta.1",
44
"description": "Utils for writing Salesforce CLI plugins",
55
"main": "lib/exported",
66
"types": "lib/exported.d.ts",
@@ -20,6 +20,7 @@
2020
"prepack": "sf-prepack",
2121
"prepare": "sf-install",
2222
"test": "wireit",
23+
"test:integration": "mocha test/**/*.integration.ts --timeout 30000",
2324
"test:only": "wireit"
2425
},
2526
"exports": {
@@ -45,15 +46,21 @@
4546
"dependencies": {
4647
"@inquirer/confirm": "^3.1.9",
4748
"@inquirer/password": "^2.1.9",
48-
"@oclif/core": "^3.26.6",
49-
"@salesforce/core": "^7.3.9",
49+
"@oclif/core": "^4",
50+
"@salesforce/core": "^7.3.10",
5051
"@salesforce/kit": "^3.1.2",
5152
"@salesforce/ts-types": "^2.0.9",
52-
"chalk": "^5.3.0"
53+
"ansis": "^3.1.1",
54+
"cli-progress": "^3.12.0",
55+
"natural-orderby": "^3.0.2",
56+
"slice-ansi": "^7.1.0",
57+
"string-width": "^7.1.0",
58+
"terminal-link": "^3.0.0"
5359
},
5460
"devDependencies": {
5561
"@inquirer/type": "^1.3.3",
5662
"@salesforce/dev-scripts": "^9.1.2",
63+
"@types/cli-progress": "^3.11.5",
5764
"eslint-plugin-sf-plugin": "^1.18.5",
5865
"ts-node": "^10.9.2",
5966
"typescript": "^5.4.5"

src/errorFormatting.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import { Mode, Messages, envVars } from '@salesforce/core';
9-
import type { ChalkInstance } from 'chalk';
9+
import type { Ansis } from 'ansis';
1010
import { StandardColors } from './ux/standardColors.js';
1111
import { SfCommandError } from './types.js';
1212

@@ -31,7 +31,7 @@ const messages = Messages.loadMessages('@salesforce/sf-plugins-core', 'messages'
3131
*/
3232
export const formatActions = (
3333
actions: string[],
34-
options: { actionColor: ChalkInstance } = { actionColor: StandardColors.info }
34+
options: { actionColor: Ansis } = { actionColor: StandardColors.info }
3535
): string[] =>
3636
actions.length
3737
? [

src/errorHandling.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import { SfError } from '@salesforce/core';
9-
import { OclifError } from '@oclif/core/lib/interfaces/errors.js';
9+
import { CLIError } from '@oclif/core/errors';
1010
import { SfCommandError } from './types.js';
1111
import { removeEmpty } from './util.js';
1212

@@ -89,5 +89,5 @@ export const errorToSfCommandError = (
8989
});
9090

9191
/** custom typeGuard for handling the fact the SfCommand doesn't know about oclif error structure */
92-
const isOclifError = <T extends Error | SfError | SfCommandError>(e: T): e is T & OclifError =>
92+
const isOclifError = <T extends Error | SfError | SfCommandError>(e: T): e is T & CLIError =>
9393
'oclif' in e ? true : false;

src/sfCommand.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ export abstract class SfCommand<T> extends Command {
256256
* @param obj The JSON to log.
257257
*/
258258
public styledJSON(obj: AnyJson): void {
259-
this.ux.styledJSON(obj);
259+
this.ux.styledJSON(obj, this.config.theme?.json);
260260
}
261261

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

289289
/**

src/ux/progress.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77

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

12+
function progress(options: Options = {}): Progress.Bar {
13+
return new SingleBar({ noTTYOutput: Boolean(process.env.TERM === 'dumb' || !process.stdin.isTTY), ...options });
14+
}
15+
1216
/**
1317
* Class for display a progress bar to the console. Will automatically be suppressed if the --json flag is present.
1418
*/
@@ -50,10 +54,10 @@ export class Progress extends UxBase {
5054

5155
this.maybeNoop(() => {
5256
const { title, ...rest } = { ...Progress.DEFAULT_OPTIONS, ...options };
53-
this.bar = ux.progress({
57+
this.bar = progress({
5458
...rest,
5559
format: util.format(rest.format, title),
56-
}) as Progress.Bar;
60+
});
5761

5862
this.bar.setTotal(total);
5963
this.bar.start(total, 0);

src/ux/standardColors.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77

8-
import chalk from 'chalk';
8+
import ansis from 'ansis';
99

1010
export const StandardColors = {
11-
error: chalk.bold.red,
12-
warning: chalk.bold.yellow,
13-
info: chalk.dim,
14-
success: chalk.bold.green,
11+
error: ansis.bold.red,
12+
warning: ansis.bold.yellow,
13+
info: ansis.dim,
14+
success: ansis.bold.green,
1515
};

src/ux/styledObject.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2023, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
import { inspect } from 'node:util';
8+
import ansis from 'ansis';
9+
import { AnyJson } from '@salesforce/ts-types';
10+
11+
function prettyPrint(obj: AnyJson): string {
12+
if (!obj) return inspect(obj);
13+
if (typeof obj === 'string') return obj;
14+
if (typeof obj === 'number') return obj.toString();
15+
if (typeof obj === 'boolean') return obj.toString();
16+
if (typeof obj === 'object') {
17+
return Object.entries(obj)
18+
.map(([key, value]) => `${key}: ${inspect(value)}`)
19+
.join(', ');
20+
}
21+
22+
return inspect(obj);
23+
}
24+
25+
export default function styledObject(obj: AnyJson, keys?: string[]): string {
26+
if (!obj) return inspect(obj);
27+
if (typeof obj === 'string') return obj;
28+
if (typeof obj === 'number') return obj.toString();
29+
if (typeof obj === 'boolean') return obj.toString();
30+
31+
const output: string[] = [];
32+
const keyLengths = Object.keys(obj).map((key) => key.toString().length);
33+
const maxKeyLength = Math.max(...keyLengths) + 2;
34+
35+
const logKeyValue = (key: string, value: AnyJson): string =>
36+
`${ansis.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + prettyPrint(value);
37+
38+
for (const [key, value] of Object.entries(obj)) {
39+
if (keys && !keys.includes(key)) continue;
40+
if (Array.isArray(value)) {
41+
if (value.length > 0) {
42+
output.push(logKeyValue(key, value[0]));
43+
for (const e of value.slice(1)) {
44+
output.push(' '.repeat(maxKeyLength) + prettyPrint(e));
45+
}
46+
}
47+
} else if (value !== null && value !== undefined) {
48+
output.push(logKeyValue(key, value));
49+
}
50+
}
51+
52+
return output.join('\n');
53+
}

0 commit comments

Comments
 (0)