@salesforce/sf-plugins-core 9.0.14-beta.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/compatibility.d.ts +7 -7
- package/lib/errorFormatting.d.ts +2 -2
- package/lib/flags/duration.d.ts +1 -1
- package/lib/flags/flags.d.ts +12 -12
- package/lib/flags/orgApiVersion.d.ts +1 -1
- package/lib/flags/orgFlags.d.ts +4 -4
- package/lib/flags/orgFlags.js +2 -1
- package/lib/flags/salesforceId.d.ts +1 -1
- package/lib/sfCommand.d.ts +1 -1
- package/lib/sfCommand.js +2 -2
- package/lib/stubUx.d.ts +3 -3
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/ux/progress.js +3 -6
- package/lib/ux/standardColors.d.ts +4 -5
- package/lib/ux/standardColors.js +5 -5
- package/lib/ux/ux.d.ts +4 -11
- package/lib/ux/ux.js +7 -30
- package/messages/messages.md +8 -0
- package/package.json +3 -10
- package/lib/ux/styledObject.d.ts +0 -3
- package/lib/ux/styledObject.js +0 -55
- package/lib/ux/table.d.ts +0 -22
- package/lib/ux/table.js +0 -257
package/lib/ux/ux.js
CHANGED
|
@@ -4,13 +4,9 @@
|
|
|
4
4
|
* Licensed under the BSD 3-Clause license.
|
|
5
5
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
6
|
*/
|
|
7
|
-
import ansis from 'ansis';
|
|
8
7
|
import { ux } from '@oclif/core';
|
|
9
|
-
import terminalLink from 'terminal-link';
|
|
10
8
|
import { UxBase } from './base.js';
|
|
11
9
|
import { Spinner } from './spinner.js';
|
|
12
|
-
import { table } from './table.js';
|
|
13
|
-
import styledObject from './styledObject.js';
|
|
14
10
|
/**
|
|
15
11
|
* UX methods for plugins. Automatically suppress console output if outputEnabled is set to false.
|
|
16
12
|
*
|
|
@@ -42,16 +38,7 @@ export class Ux extends UxBase {
|
|
|
42
38
|
* @param args Args to be used for formatting.
|
|
43
39
|
*/
|
|
44
40
|
log(message, ...args) {
|
|
45
|
-
this.maybeNoop(() => ux.
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Log a message to stderr. This will be automatically suppressed if output is disabled.
|
|
49
|
-
*
|
|
50
|
-
* @param message Message to log. Formatting is supported.
|
|
51
|
-
* @param args Args to be used for formatting.
|
|
52
|
-
*/
|
|
53
|
-
logToStderr(message, ...args) {
|
|
54
|
-
this.maybeNoop(() => ux.stderr(message, ...args));
|
|
41
|
+
this.maybeNoop(() => ux.log(message, ...args));
|
|
55
42
|
}
|
|
56
43
|
/**
|
|
57
44
|
* Log a warning message to the console. This will be automatically suppressed if output is disabled.
|
|
@@ -69,7 +56,7 @@ export class Ux extends UxBase {
|
|
|
69
56
|
* @param options Options for how the table should be displayed
|
|
70
57
|
*/
|
|
71
58
|
table(data, columns, options) {
|
|
72
|
-
this.maybeNoop(() => table(data, columns, { 'no-truncate': true, ...options }));
|
|
59
|
+
this.maybeNoop(() => ux.table(data, columns, { 'no-truncate': true, ...options }));
|
|
73
60
|
}
|
|
74
61
|
/**
|
|
75
62
|
* Display a url to the console. This will be automatically suppressed if output is disabled.
|
|
@@ -79,25 +66,15 @@ export class Ux extends UxBase {
|
|
|
79
66
|
* @param params
|
|
80
67
|
*/
|
|
81
68
|
url(text, uri, params = {}) {
|
|
82
|
-
this.maybeNoop(() => ux.
|
|
69
|
+
this.maybeNoop(() => ux.url(text, uri, params));
|
|
83
70
|
}
|
|
84
71
|
/**
|
|
85
72
|
* Display stylized JSON to the console. This will be automatically suppressed if output is disabled.
|
|
86
73
|
*
|
|
87
74
|
* @param obj JSON to display
|
|
88
75
|
*/
|
|
89
|
-
styledJSON(obj
|
|
90
|
-
|
|
91
|
-
// to ship sf-plugins-core before the theme.json is updated.
|
|
92
|
-
const defaultTheme = {
|
|
93
|
-
key: 'blueBright',
|
|
94
|
-
string: 'greenBright',
|
|
95
|
-
number: 'blue',
|
|
96
|
-
boolean: 'redBright',
|
|
97
|
-
null: 'blackBright',
|
|
98
|
-
};
|
|
99
|
-
const mergedTheme = { ...defaultTheme, ...theme };
|
|
100
|
-
this.maybeNoop(() => ux.stdout(ux.colorizeJson(obj, { theme: mergedTheme })));
|
|
76
|
+
styledJSON(obj) {
|
|
77
|
+
this.maybeNoop(() => ux.styledJSON(obj));
|
|
101
78
|
}
|
|
102
79
|
/**
|
|
103
80
|
* Display stylized object to the console. This will be automatically suppressed if output is disabled.
|
|
@@ -106,7 +83,7 @@ export class Ux extends UxBase {
|
|
|
106
83
|
* @param keys Keys of object to display
|
|
107
84
|
*/
|
|
108
85
|
styledObject(obj, keys) {
|
|
109
|
-
this.maybeNoop(() => ux.
|
|
86
|
+
this.maybeNoop(() => ux.styledObject(obj, keys));
|
|
110
87
|
}
|
|
111
88
|
/**
|
|
112
89
|
* Display stylized header to the console. This will be automatically suppressed if output is disabled.
|
|
@@ -114,7 +91,7 @@ export class Ux extends UxBase {
|
|
|
114
91
|
* @param text header to display
|
|
115
92
|
*/
|
|
116
93
|
styledHeader(text) {
|
|
117
|
-
this.maybeNoop(() => ux.
|
|
94
|
+
this.maybeNoop(() => ux.styledHeader(text));
|
|
118
95
|
}
|
|
119
96
|
}
|
|
120
97
|
//# sourceMappingURL=ux.js.map
|
package/messages/messages.md
CHANGED
|
@@ -42,10 +42,18 @@ The specified org %s is not a Dev Hub.
|
|
|
42
42
|
|
|
43
43
|
Username or alias of the target org. Not required if the `target-org` configuration variable is already set.
|
|
44
44
|
|
|
45
|
+
# flags.optionalTargetOrg.summary
|
|
46
|
+
|
|
47
|
+
Username or alias of the target org.
|
|
48
|
+
|
|
45
49
|
# flags.targetDevHubOrg.summary
|
|
46
50
|
|
|
47
51
|
Username or alias of the Dev Hub org. Not required if the `target-dev-hub` configuration variable is already set.
|
|
48
52
|
|
|
53
|
+
# flags.optionalTargetDevHubOrg.summary
|
|
54
|
+
|
|
55
|
+
Username or alias of the Dev Hub org.
|
|
56
|
+
|
|
49
57
|
# flags.apiVersion.description
|
|
50
58
|
|
|
51
59
|
Override the api version used for api requests made by this command
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sf-plugins-core",
|
|
3
|
-
"version": "9.0
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Utils for writing Salesforce CLI plugins",
|
|
5
5
|
"main": "lib/exported",
|
|
6
6
|
"types": "lib/exported.d.ts",
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"prepack": "sf-prepack",
|
|
21
21
|
"prepare": "sf-install",
|
|
22
22
|
"test": "wireit",
|
|
23
|
-
"test:integration": "mocha test/**/*.integration.ts --timeout 30000",
|
|
24
23
|
"test:only": "wireit"
|
|
25
24
|
},
|
|
26
25
|
"exports": {
|
|
@@ -46,20 +45,14 @@
|
|
|
46
45
|
"dependencies": {
|
|
47
46
|
"@inquirer/confirm": "^2.0.17",
|
|
48
47
|
"@inquirer/password": "^1.1.16",
|
|
49
|
-
"@oclif/core": "^
|
|
48
|
+
"@oclif/core": "^3.26.6",
|
|
50
49
|
"@salesforce/core": "^7.3.9",
|
|
51
50
|
"@salesforce/kit": "^3.1.2",
|
|
52
51
|
"@salesforce/ts-types": "^2.0.9",
|
|
53
|
-
"
|
|
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"
|
|
52
|
+
"chalk": "^5.3.0"
|
|
59
53
|
},
|
|
60
54
|
"devDependencies": {
|
|
61
55
|
"@inquirer/type": "^1.3.1",
|
|
62
|
-
"@types/cli-progress": "^3.11.5",
|
|
63
56
|
"@salesforce/dev-scripts": "^9.1.2",
|
|
64
57
|
"eslint-plugin-sf-plugin": "^1.18.4",
|
|
65
58
|
"ts-node": "^10.9.2",
|
package/lib/ux/styledObject.d.ts
DELETED
package/lib/ux/styledObject.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
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
|
-
function prettyPrint(obj) {
|
|
10
|
-
if (!obj)
|
|
11
|
-
return inspect(obj);
|
|
12
|
-
if (typeof obj === 'string')
|
|
13
|
-
return obj;
|
|
14
|
-
if (typeof obj === 'number')
|
|
15
|
-
return obj.toString();
|
|
16
|
-
if (typeof obj === 'boolean')
|
|
17
|
-
return obj.toString();
|
|
18
|
-
if (typeof obj === 'object') {
|
|
19
|
-
return Object.entries(obj)
|
|
20
|
-
.map(([key, value]) => `${key}: ${inspect(value)}`)
|
|
21
|
-
.join(', ');
|
|
22
|
-
}
|
|
23
|
-
return inspect(obj);
|
|
24
|
-
}
|
|
25
|
-
export default function styledObject(obj, keys) {
|
|
26
|
-
if (!obj)
|
|
27
|
-
return inspect(obj);
|
|
28
|
-
if (typeof obj === 'string')
|
|
29
|
-
return obj;
|
|
30
|
-
if (typeof obj === 'number')
|
|
31
|
-
return obj.toString();
|
|
32
|
-
if (typeof obj === 'boolean')
|
|
33
|
-
return obj.toString();
|
|
34
|
-
const output = [];
|
|
35
|
-
const keyLengths = Object.keys(obj).map((key) => key.toString().length);
|
|
36
|
-
const maxKeyLength = Math.max(...keyLengths) + 2;
|
|
37
|
-
const logKeyValue = (key, value) => `${ansis.blue(key)}:` + ' '.repeat(maxKeyLength - key.length - 1) + prettyPrint(value);
|
|
38
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
39
|
-
if (keys && !keys.includes(key))
|
|
40
|
-
continue;
|
|
41
|
-
if (Array.isArray(value)) {
|
|
42
|
-
if (value.length > 0) {
|
|
43
|
-
output.push(logKeyValue(key, value[0]));
|
|
44
|
-
for (const e of value.slice(1)) {
|
|
45
|
-
output.push(' '.repeat(maxKeyLength) + prettyPrint(e));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else if (value !== null && value !== undefined) {
|
|
50
|
-
output.push(logKeyValue(key, value));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return output.join('\n');
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=styledObject.js.map
|
package/lib/ux/table.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export declare function table<T extends Record<string, unknown>>(data: T[], columns: Columns<T>, options?: Options): void;
|
|
2
|
-
export type Column<T extends Record<string, unknown>> = {
|
|
3
|
-
extended: boolean;
|
|
4
|
-
header: string;
|
|
5
|
-
minWidth: number;
|
|
6
|
-
get(row: T): unknown;
|
|
7
|
-
};
|
|
8
|
-
export type Columns<T extends Record<string, unknown>> = {
|
|
9
|
-
[key: string]: Partial<Column<T>>;
|
|
10
|
-
};
|
|
11
|
-
export type Options = {
|
|
12
|
-
columns?: string;
|
|
13
|
-
extended?: boolean;
|
|
14
|
-
filter?: string;
|
|
15
|
-
'no-header'?: boolean;
|
|
16
|
-
'no-truncate'?: boolean;
|
|
17
|
-
rowStart?: string;
|
|
18
|
-
sort?: string;
|
|
19
|
-
title?: string;
|
|
20
|
-
printLine?(s: unknown): void;
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=table.d.ts.map
|
package/lib/ux/table.js
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
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 { orderBy } from 'natural-orderby';
|
|
10
|
-
import sliceAnsi from 'slice-ansi';
|
|
11
|
-
import sw from 'string-width';
|
|
12
|
-
import { ux } from '@oclif/core';
|
|
13
|
-
function sumBy(arr, fn) {
|
|
14
|
-
return arr.reduce((sum, i) => sum + fn(i), 0);
|
|
15
|
-
}
|
|
16
|
-
function capitalize(s) {
|
|
17
|
-
return s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '';
|
|
18
|
-
}
|
|
19
|
-
function termwidth(stream) {
|
|
20
|
-
if (!stream.isTTY) {
|
|
21
|
-
return 80;
|
|
22
|
-
}
|
|
23
|
-
const width = stream.getWindowSize()[0];
|
|
24
|
-
if (width < 1) {
|
|
25
|
-
return 80;
|
|
26
|
-
}
|
|
27
|
-
if (width < 40) {
|
|
28
|
-
return 40;
|
|
29
|
-
}
|
|
30
|
-
return width;
|
|
31
|
-
}
|
|
32
|
-
const stdtermwidth = Number.parseInt(process.env.OCLIF_COLUMNS, 10) || termwidth(process.stdout);
|
|
33
|
-
class Table {
|
|
34
|
-
columns;
|
|
35
|
-
options;
|
|
36
|
-
data;
|
|
37
|
-
constructor(data, columns, options = {}) {
|
|
38
|
-
// assign columns
|
|
39
|
-
this.columns = Object.keys(columns).map((key) => {
|
|
40
|
-
const col = columns[key];
|
|
41
|
-
const extended = col.extended ?? false;
|
|
42
|
-
// turn null and undefined into empty strings by default
|
|
43
|
-
const get = col.get ?? ((row) => row[key] ?? '');
|
|
44
|
-
const header = typeof col.header === 'string' ? col.header : capitalize(key.replaceAll('_', ' '));
|
|
45
|
-
const minWidth = Math.max(col.minWidth ?? 0, sw(header) + 1);
|
|
46
|
-
return {
|
|
47
|
-
extended,
|
|
48
|
-
get,
|
|
49
|
-
header,
|
|
50
|
-
key,
|
|
51
|
-
minWidth,
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
// assign options
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
56
|
-
const { columns: cols, extended, filter, printLine, sort, title } = options;
|
|
57
|
-
this.options = {
|
|
58
|
-
columns: cols,
|
|
59
|
-
extended,
|
|
60
|
-
filter,
|
|
61
|
-
'no-header': options['no-header'] ?? false,
|
|
62
|
-
'no-truncate': options['no-truncate'] ?? false,
|
|
63
|
-
printLine: printLine ?? ((s) => ux.stdout(s)),
|
|
64
|
-
rowStart: ' ',
|
|
65
|
-
sort,
|
|
66
|
-
title,
|
|
67
|
-
};
|
|
68
|
-
// build table rows from input array data
|
|
69
|
-
let rows = data.map((d) => Object.fromEntries(this.columns.map((col) => {
|
|
70
|
-
let val = col.get(d);
|
|
71
|
-
if (typeof val !== 'string')
|
|
72
|
-
val = inspect(val, { breakLength: Number.POSITIVE_INFINITY });
|
|
73
|
-
return [col.key, val];
|
|
74
|
-
})));
|
|
75
|
-
// filter rows
|
|
76
|
-
if (this.options.filter) {
|
|
77
|
-
// eslint-disable-next-line prefer-const
|
|
78
|
-
let [header, regex] = this.options.filter.split('=');
|
|
79
|
-
const isNot = header.startsWith('-');
|
|
80
|
-
if (isNot)
|
|
81
|
-
header = header.slice(1);
|
|
82
|
-
const col = this.findColumnFromHeader(header);
|
|
83
|
-
if (!col || !regex)
|
|
84
|
-
throw new Error('Filter flag has an invalid value');
|
|
85
|
-
rows = rows.filter((d) => {
|
|
86
|
-
const re = new RegExp(regex);
|
|
87
|
-
const val = d[col.key];
|
|
88
|
-
const match = val.match(re);
|
|
89
|
-
return isNot ? !match : match;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
// sort rows
|
|
93
|
-
if (this.options.sort) {
|
|
94
|
-
const sorters = this.options.sort.split(',');
|
|
95
|
-
const sortHeaders = sorters.map((k) => (k.startsWith('-') ? k.slice(1) : k));
|
|
96
|
-
const sortKeys = this.filterColumnsFromHeaders(sortHeaders).map((c) => (v) => v[c.key]);
|
|
97
|
-
const sortKeysOrder = sorters.map((k) => (k.startsWith('-') ? 'desc' : 'asc'));
|
|
98
|
-
rows = orderBy(rows, sortKeys, sortKeysOrder);
|
|
99
|
-
}
|
|
100
|
-
// and filter columns
|
|
101
|
-
if (this.options.columns) {
|
|
102
|
-
const filters = this.options.columns.split(',');
|
|
103
|
-
this.columns = this.filterColumnsFromHeaders(filters);
|
|
104
|
-
}
|
|
105
|
-
else if (!this.options.extended) {
|
|
106
|
-
// show extended columns/properties
|
|
107
|
-
this.columns = this.columns.filter((c) => !c.extended);
|
|
108
|
-
}
|
|
109
|
-
this.data = rows;
|
|
110
|
-
}
|
|
111
|
-
display() {
|
|
112
|
-
const { data, options } = this;
|
|
113
|
-
// column truncation
|
|
114
|
-
//
|
|
115
|
-
// find max width for each column
|
|
116
|
-
const columns = this.columns.map((c) => {
|
|
117
|
-
const maxWidth = Math.max(sw('.'.padEnd(c.minWidth - 1)), sw(c.header), getWidestColumnWith(data, c.key)) + 1;
|
|
118
|
-
return {
|
|
119
|
-
...c,
|
|
120
|
-
maxWidth,
|
|
121
|
-
width: maxWidth,
|
|
122
|
-
};
|
|
123
|
-
});
|
|
124
|
-
// terminal width
|
|
125
|
-
const maxWidth = stdtermwidth - 2;
|
|
126
|
-
// truncation logic
|
|
127
|
-
const shouldShorten = () => {
|
|
128
|
-
// don't shorten if full mode
|
|
129
|
-
if (options['no-truncate'] ?? (!process.stdout.isTTY && !process.env.CLI_UX_SKIP_TTY_CHECK))
|
|
130
|
-
return;
|
|
131
|
-
// don't shorten if there is enough screen width
|
|
132
|
-
const dataMaxWidth = sumBy(columns, (c) => c.width);
|
|
133
|
-
const overWidth = dataMaxWidth - maxWidth;
|
|
134
|
-
if (overWidth <= 0)
|
|
135
|
-
return;
|
|
136
|
-
// not enough room, short all columns to minWidth
|
|
137
|
-
for (const col of columns) {
|
|
138
|
-
col.width = col.minWidth;
|
|
139
|
-
}
|
|
140
|
-
// if sum(minWidth's) is greater than term width
|
|
141
|
-
// nothing can be done so
|
|
142
|
-
// display all as minWidth
|
|
143
|
-
const dataMinWidth = sumBy(columns, (c) => c.minWidth);
|
|
144
|
-
if (dataMinWidth >= maxWidth)
|
|
145
|
-
return;
|
|
146
|
-
// some wiggle room left, add it back to "needy" columns
|
|
147
|
-
let wiggleRoom = maxWidth - dataMinWidth;
|
|
148
|
-
const needyCols = columns
|
|
149
|
-
.map((c) => ({ key: c.key, needs: c.maxWidth - c.width }))
|
|
150
|
-
.sort((a, b) => a.needs - b.needs);
|
|
151
|
-
for (const { key, needs } of needyCols) {
|
|
152
|
-
if (!needs)
|
|
153
|
-
continue;
|
|
154
|
-
const col = columns.find((c) => key === c.key);
|
|
155
|
-
if (!col)
|
|
156
|
-
continue;
|
|
157
|
-
if (wiggleRoom > needs) {
|
|
158
|
-
col.width = col.width + needs;
|
|
159
|
-
wiggleRoom -= needs;
|
|
160
|
-
}
|
|
161
|
-
else if (wiggleRoom) {
|
|
162
|
-
col.width = col.width + wiggleRoom;
|
|
163
|
-
wiggleRoom = 0;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
shouldShorten();
|
|
168
|
-
// print table title
|
|
169
|
-
if (options.title) {
|
|
170
|
-
options.printLine(options.title);
|
|
171
|
-
// print title divider
|
|
172
|
-
options.printLine(''.padEnd(columns.reduce((sum, col) => sum + col.width, 1), '='));
|
|
173
|
-
options.rowStart = '| ';
|
|
174
|
-
}
|
|
175
|
-
// print headers
|
|
176
|
-
if (!options['no-header']) {
|
|
177
|
-
let headers = options.rowStart;
|
|
178
|
-
for (const col of columns) {
|
|
179
|
-
const header = col.header;
|
|
180
|
-
headers += header.padEnd(col.width);
|
|
181
|
-
}
|
|
182
|
-
if (headers)
|
|
183
|
-
options.printLine(ansis.bold(headers));
|
|
184
|
-
// print header dividers
|
|
185
|
-
let dividers = options.rowStart;
|
|
186
|
-
for (const col of columns) {
|
|
187
|
-
const divider = ''.padEnd(col.width - 1, '─') + ' ';
|
|
188
|
-
dividers += divider.padEnd(col.width);
|
|
189
|
-
}
|
|
190
|
-
if (dividers)
|
|
191
|
-
options.printLine(ansis.bold(dividers));
|
|
192
|
-
}
|
|
193
|
-
// print rows
|
|
194
|
-
for (const row of data) {
|
|
195
|
-
// find max number of lines
|
|
196
|
-
// for all cells in a row
|
|
197
|
-
// with multi-line strings
|
|
198
|
-
let numOfLines = 1;
|
|
199
|
-
for (const col of columns) {
|
|
200
|
-
const d = row[col.key];
|
|
201
|
-
const lines = d.split('\n').length;
|
|
202
|
-
if (lines > numOfLines)
|
|
203
|
-
numOfLines = lines;
|
|
204
|
-
}
|
|
205
|
-
// eslint-disable-next-line unicorn/no-new-array
|
|
206
|
-
const linesIndexess = [...new Array(numOfLines).keys()];
|
|
207
|
-
// print row
|
|
208
|
-
// including multi-lines
|
|
209
|
-
for (const i of linesIndexess) {
|
|
210
|
-
let l = options.rowStart;
|
|
211
|
-
for (const col of columns) {
|
|
212
|
-
const width = col.width;
|
|
213
|
-
let d = row[col.key];
|
|
214
|
-
d = d.split('\n')[i] || '';
|
|
215
|
-
const visualWidth = sw(d);
|
|
216
|
-
const colorWidth = d.length - visualWidth;
|
|
217
|
-
let cell = d.padEnd(width + colorWidth);
|
|
218
|
-
if (cell.length - colorWidth > width || visualWidth === width) {
|
|
219
|
-
// truncate the cell, preserving ANSI escape sequences, and keeping
|
|
220
|
-
// into account the width of fullwidth unicode characters
|
|
221
|
-
cell = sliceAnsi(cell, 0, width - 2) + '… ';
|
|
222
|
-
// pad with spaces; this is necessary in case the original string
|
|
223
|
-
// contained fullwidth characters which cannot be split
|
|
224
|
-
cell += ' '.repeat(width - sw(cell));
|
|
225
|
-
}
|
|
226
|
-
l += cell;
|
|
227
|
-
}
|
|
228
|
-
options.printLine(l);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
filterColumnsFromHeaders(filters) {
|
|
233
|
-
const cols = [];
|
|
234
|
-
for (const f of [...new Set(filters)]) {
|
|
235
|
-
const c = this.columns.find((i) => i.header.toLowerCase() === f.toLowerCase());
|
|
236
|
-
if (c)
|
|
237
|
-
cols.push(c);
|
|
238
|
-
}
|
|
239
|
-
return cols;
|
|
240
|
-
}
|
|
241
|
-
findColumnFromHeader(header) {
|
|
242
|
-
return this.columns.find((c) => c.header.toLowerCase() === header.toLowerCase());
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
export function table(data, columns, options = {}) {
|
|
246
|
-
new Table(data, columns, options).display();
|
|
247
|
-
}
|
|
248
|
-
const getWidestColumnWith = (data, columnKey) => data.reduce((previous, current) => {
|
|
249
|
-
const d = current[columnKey];
|
|
250
|
-
if (typeof d !== 'string')
|
|
251
|
-
return previous;
|
|
252
|
-
// convert multi-line cell to single longest line
|
|
253
|
-
// for width calculations
|
|
254
|
-
const manyLines = d.split('\n');
|
|
255
|
-
return Math.max(previous, manyLines.length > 1 ? Math.max(...manyLines.map((r) => sw(r))) : sw(d));
|
|
256
|
-
}, 0);
|
|
257
|
-
//# sourceMappingURL=table.js.map
|