@oclif/table 0.2.4 → 0.3.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/table.d.ts +2 -2
- package/lib/table.js +46 -42
- package/lib/utils.d.ts +10 -0
- package/lib/utils.js +22 -0
- package/package.json +2 -2
package/lib/table.d.ts
CHANGED
|
@@ -27,8 +27,8 @@ export declare function Skeleton(props: React.PropsWithChildren & {
|
|
|
27
27
|
readonly height?: number;
|
|
28
28
|
}): React.JSX.Element;
|
|
29
29
|
/**
|
|
30
|
-
* Prints a table based on the provided options. If the data length exceeds
|
|
31
|
-
* the table is rendered in
|
|
30
|
+
* Prints a table based on the provided options. If the data length exceeds 10,000 entries,
|
|
31
|
+
* the table is rendered in a non-styled format to avoid memory issues.
|
|
32
32
|
*
|
|
33
33
|
* @template T - A generic type that extends a record with string keys and unknown values.
|
|
34
34
|
* @param {TableOptions<T>} options - The options for rendering the table, including data and other configurations.
|
package/lib/table.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import cliTruncate from 'cli-truncate';
|
|
3
3
|
import { Box, Text, render } from 'ink';
|
|
4
4
|
import { EventEmitter } from 'node:events';
|
|
5
|
+
import { env } from 'node:process';
|
|
5
6
|
import { sha1 } from 'object-hash';
|
|
6
7
|
import React from 'react';
|
|
7
8
|
import stripAnsi from 'strip-ansi';
|
|
8
9
|
import wrapAnsi from 'wrap-ansi';
|
|
9
10
|
import { BORDER_SKELETONS } from './skeletons.js';
|
|
10
|
-
import { allKeysInCollection, determineWidthOfWrappedText, getColumns, getHeadings, intersperse, maybeStripAnsi, sortData, } from './utils.js';
|
|
11
|
+
import { allKeysInCollection, determineWidthOfWrappedText, getColumns, getHeadings, intersperse, maybeStripAnsi, shouldUsePlainTable, sortData, } from './utils.js';
|
|
11
12
|
/**
|
|
12
13
|
* Determines the configured width based on the provided width value.
|
|
13
14
|
* If no width is provided, it returns the width of the current terminal.
|
|
@@ -325,63 +326,66 @@ class Output {
|
|
|
325
326
|
constructor() {
|
|
326
327
|
this.stream = createStdout();
|
|
327
328
|
}
|
|
328
|
-
|
|
329
|
+
printLastFrame() {
|
|
329
330
|
process.stdout.write(`${this.stream.lastFrame()}\n`);
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
|
-
function
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
for (const
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
333
|
+
function renderPlainTable(props) {
|
|
334
|
+
const { columns, headings, processedData, title } = setup(props);
|
|
335
|
+
if (title)
|
|
336
|
+
console.log(title);
|
|
337
|
+
const headerString = columns.reduce((acc, column) => {
|
|
338
|
+
const { horizontalAlignment, overflow, padding, width } = column;
|
|
339
|
+
const { marginLeft, marginRight, text } = formatTextWithMargins({
|
|
340
|
+
horizontalAlignment,
|
|
341
|
+
overflow,
|
|
342
|
+
padding,
|
|
343
|
+
value: column.column,
|
|
344
|
+
width,
|
|
345
|
+
});
|
|
346
|
+
const columnHeader = headings[text] ?? text;
|
|
347
|
+
return `${acc}${' '.repeat(marginLeft)}${columnHeader}${' '.repeat(marginRight)}`;
|
|
348
|
+
}, '');
|
|
349
|
+
console.log(headerString);
|
|
350
|
+
console.log('-'.repeat(headerString.length));
|
|
351
|
+
for (const row of processedData) {
|
|
352
|
+
const stringToPrint = columns.reduce((acc, column) => {
|
|
353
|
+
const { horizontalAlignment, overflow, padding, width } = column;
|
|
354
|
+
const value = row[column.column];
|
|
355
|
+
if (value === undefined || value === null) {
|
|
356
|
+
return `${acc}${' '.repeat(width)}`;
|
|
357
|
+
}
|
|
358
|
+
const { marginLeft, marginRight, text } = formatTextWithMargins({
|
|
359
|
+
horizontalAlignment,
|
|
360
|
+
overflow,
|
|
361
|
+
padding,
|
|
362
|
+
value,
|
|
363
|
+
width,
|
|
364
|
+
});
|
|
365
|
+
return `${acc}${' '.repeat(marginLeft)}${text}${' '.repeat(marginRight)}`;
|
|
366
|
+
}, '');
|
|
367
|
+
console.log(stringToPrint);
|
|
362
368
|
}
|
|
363
|
-
|
|
364
|
-
const footerInstance = render(React.createElement(Box, { flexDirection: "column", width: determineWidthToUse(columns, config.maxWidth) }, footerComponent({ columns, data: {}, key: 'footer' })), { stdout: footerOutput.stream });
|
|
365
|
-
footerInstance.unmount();
|
|
366
|
-
footerOutput.maybePrintLastFrame();
|
|
369
|
+
console.log();
|
|
367
370
|
}
|
|
368
371
|
/**
|
|
369
|
-
* Prints a table based on the provided options. If the data length exceeds
|
|
370
|
-
* the table is rendered in
|
|
372
|
+
* Prints a table based on the provided options. If the data length exceeds 10,000 entries,
|
|
373
|
+
* the table is rendered in a non-styled format to avoid memory issues.
|
|
371
374
|
*
|
|
372
375
|
* @template T - A generic type that extends a record with string keys and unknown values.
|
|
373
376
|
* @param {TableOptions<T>} options - The options for rendering the table, including data and other configurations.
|
|
374
377
|
* @returns {void}
|
|
375
378
|
*/
|
|
376
379
|
export function printTable(options) {
|
|
377
|
-
|
|
378
|
-
|
|
380
|
+
const limit = Number.parseInt(env.OCLIF_TABLE_LIMIT ?? env.SF_TABLE_LIMIT ?? '10000', 10) ?? 10_000;
|
|
381
|
+
if (options.data.length >= limit || shouldUsePlainTable()) {
|
|
382
|
+
renderPlainTable(options);
|
|
379
383
|
return;
|
|
380
384
|
}
|
|
381
385
|
const output = new Output();
|
|
382
386
|
const instance = render(React.createElement(Table, { ...options }), { stdout: output.stream });
|
|
383
387
|
instance.unmount();
|
|
384
|
-
output.
|
|
388
|
+
output.printLastFrame();
|
|
385
389
|
}
|
|
386
390
|
/**
|
|
387
391
|
* Generates a table as a string based on the provided options.
|
|
@@ -422,5 +426,5 @@ export function printTables(tables, options) {
|
|
|
422
426
|
}));
|
|
423
427
|
const instance = render(React.createElement(Container, { ...options }, processed.map((table) => (React.createElement(Table, { key: sha1(table), ...table })))), { stdout: output.stream });
|
|
424
428
|
instance.unmount();
|
|
425
|
-
output.
|
|
429
|
+
output.printLastFrame();
|
|
426
430
|
}
|
package/lib/utils.d.ts
CHANGED
|
@@ -14,3 +14,13 @@ export declare function determineWidthOfWrappedText(text: string): number;
|
|
|
14
14
|
export declare function getColumns<T extends Record<string, unknown>>(config: Config<T>, headings: Partial<T>): Column<T>[];
|
|
15
15
|
export declare function getHeadings<T extends Record<string, unknown>>(config: Config<T>): Partial<T>;
|
|
16
16
|
export declare function maybeStripAnsi<T extends Record<string, unknown>[]>(data: T, noStyle: boolean): T;
|
|
17
|
+
/**
|
|
18
|
+
* Determines whether the plain text table should be used.
|
|
19
|
+
*
|
|
20
|
+
* If the OCLIF_TABLE_SKIP_CI_CHECK environment variable is set to a truthy value, the CI check will be skipped.
|
|
21
|
+
*
|
|
22
|
+
* If the CI environment variable is set, the plain text table will be used.
|
|
23
|
+
*
|
|
24
|
+
* @returns {boolean} True if the plain text table should be used, false otherwise.
|
|
25
|
+
*/
|
|
26
|
+
export declare function shouldUsePlainTable(): boolean;
|
package/lib/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { camelCase, capitalCase, constantCase, kebabCase, pascalCase, sentenceCase, snakeCase } from 'change-case';
|
|
2
2
|
import { orderBy } from 'natural-orderby';
|
|
3
|
+
import { env } from 'node:process';
|
|
3
4
|
import stripAnsi from 'strip-ansi';
|
|
4
5
|
/**
|
|
5
6
|
* Intersperses a list of elements with another element.
|
|
@@ -144,3 +145,24 @@ export function maybeStripAnsi(data, noStyle) {
|
|
|
144
145
|
}
|
|
145
146
|
return newData;
|
|
146
147
|
}
|
|
148
|
+
function isTruthy(value) {
|
|
149
|
+
return value !== '0' && value !== 'false';
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Determines whether the plain text table should be used.
|
|
153
|
+
*
|
|
154
|
+
* If the OCLIF_TABLE_SKIP_CI_CHECK environment variable is set to a truthy value, the CI check will be skipped.
|
|
155
|
+
*
|
|
156
|
+
* If the CI environment variable is set, the plain text table will be used.
|
|
157
|
+
*
|
|
158
|
+
* @returns {boolean} True if the plain text table should be used, false otherwise.
|
|
159
|
+
*/
|
|
160
|
+
export function shouldUsePlainTable() {
|
|
161
|
+
if (env.OCLIF_TABLE_SKIP_CI_CHECK && isTruthy(env.OCLIF_TABLE_SKIP_CI_CHECK))
|
|
162
|
+
return false;
|
|
163
|
+
// Inspired by https://github.com/sindresorhus/is-in-ci
|
|
164
|
+
if (isTruthy(env.CI) &&
|
|
165
|
+
('CI' in env || 'CONTINUOUS_INTEGRATION' in env || Object.keys(env).some((key) => key.startsWith('CI_'))))
|
|
166
|
+
return true;
|
|
167
|
+
return false;
|
|
168
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oclif/table",
|
|
3
3
|
"description": "Display table in terminal",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"bugs": "https://github.com/oclif/table/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"eslint-config-prettier": "^9.1.0",
|
|
35
35
|
"eslint-config-xo": "^0.45.0",
|
|
36
36
|
"eslint-config-xo-react": "^0.27.0",
|
|
37
|
-
"eslint-plugin-react": "^7.37.
|
|
37
|
+
"eslint-plugin-react": "^7.37.2",
|
|
38
38
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
39
39
|
"husky": "^9.1.6",
|
|
40
40
|
"ink-testing-library": "^4.0.0",
|