Skip to content

Commit 9e07e9c

Browse files
committed
refactor: use AnyJson for styledObject
1 parent 8efcdb8 commit 9e07e9c

File tree

2 files changed

+67
-22
lines changed

2 files changed

+67
-22
lines changed

src/ux/styledObject.ts

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,42 @@
66
*/
77
import { inspect } from 'node:util';
88
import chalk from 'chalk';
9+
import { AnyJson } from '@salesforce/ts-types';
910

10-
/* eslint-disable @typescript-eslint/no-explicit-any */
11-
12-
function pp(obj: any): any {
13-
if (typeof obj === 'string' || typeof obj === 'number') return obj;
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();
1416
if (typeof obj === 'object') {
15-
return (
16-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
17-
Object.keys(obj)
18-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
19-
.map((k) => k + ': ' + inspect(obj[k]))
20-
.join(', ')
21-
);
17+
return Object.entries(obj)
18+
.map(([key, value]) => `${key}: ${inspect(value)}`)
19+
.join(', ');
2220
}
2321

2422
return inspect(obj);
2523
}
2624

27-
// @oclif/core v4 will have native support for coloring JSON so we won't need this then.
28-
export default function styledObject(obj: any, keys?: string[]): string {
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+
2931
const output: string[] = [];
30-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
3132
const keyLengths = Object.keys(obj).map((key) => key.toString().length);
3233
const maxKeyLength = Math.max(...keyLengths) + 2;
3334

34-
const logKeyValue = (key: string, value: any): string =>
35-
`${chalk.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + pp(value);
35+
const logKeyValue = (key: string, value: AnyJson): string =>
36+
`${chalk.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + prettyPrint(value);
3637

37-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
38-
for (const key of keys ?? Object.keys(obj).sort()) {
39-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
40-
const value = obj[key];
38+
for (const [key, value] of Object.entries(obj)) {
39+
if (keys && !keys.includes(key)) continue;
4140
if (Array.isArray(value)) {
4241
if (value.length > 0) {
4342
output.push(logKeyValue(key, value[0]));
4443
for (const e of value.slice(1)) {
45-
output.push(' '.repeat(maxKeyLength) + pp(e));
44+
output.push(' '.repeat(maxKeyLength) + prettyPrint(e));
4645
}
4746
}
4847
} else if (value !== null && value !== undefined) {

test/unit/ux/object.test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,27 @@ import stripAnsi from 'strip-ansi';
99
import styledObject from '../../../src/ux/styledObject.js';
1010

1111
describe('styledObject', () => {
12-
it('should show a table', () => {
12+
it('should handle simple object', () => {
13+
const result = styledObject({ foo: 1, bar: 2 });
14+
expect(stripAnsi(result)).to.equal('foo: 1\nbar: 2');
15+
});
16+
17+
it('should handle object with select keys', () => {
18+
const result = styledObject({ foo: 1, bar: 2 }, ['foo']);
19+
expect(stripAnsi(result)).to.equal('foo: 1');
20+
});
21+
22+
it('should handle deeply nested object', () => {
23+
const result = styledObject({ foo: { bar: { baz: 1 } } });
24+
expect(stripAnsi(result)).to.equal('foo: bar: { baz: 1 }');
25+
});
26+
27+
it('should handle deeply nested objects with arrays', () => {
28+
const result = styledObject({ foo: { bar: [{ baz: 1 }, { baz: 2 }] } });
29+
expect(stripAnsi(result)).to.equal('foo: bar: [ { baz: 1 }, { baz: 2 } ]');
30+
});
31+
32+
it('should show array input as table', () => {
1333
const result = styledObject([
1434
{ foo: 1, bar: 1 },
1535
{ foo: 2, bar: 2 },
@@ -19,4 +39,30 @@ describe('styledObject', () => {
1939
1: foo: 2, bar: 2
2040
2: foo: 3, bar: 3`);
2141
});
42+
43+
it('should handle nulls', () => {
44+
const result = styledObject([{ foo: 1, bar: 1 }, null, { foo: 3, bar: 3 }]);
45+
expect(stripAnsi(result)).to.equal(`0: foo: 1, bar: 1
46+
2: foo: 3, bar: 3`);
47+
});
48+
49+
it('should handle null input', () => {
50+
const result = styledObject(null);
51+
expect(stripAnsi(result)).to.equal('null');
52+
});
53+
54+
it('should handle string input', () => {
55+
const result = styledObject('foo');
56+
expect(stripAnsi(result)).to.equal('foo');
57+
});
58+
59+
it('should handle number input', () => {
60+
const result = styledObject(1);
61+
expect(stripAnsi(result)).to.equal('1');
62+
});
63+
64+
it('should handle boolean input', () => {
65+
const result = styledObject(true);
66+
expect(stripAnsi(result)).to.equal('true');
67+
});
2268
});

0 commit comments

Comments
 (0)