@oclif/table 0.2.4 → 0.3.1
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 -43
- 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,65 @@ 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
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
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: headings[column.column] ?? column.column,
|
|
344
|
+
width,
|
|
345
|
+
});
|
|
346
|
+
return `${acc}${' '.repeat(marginLeft)}${text}${' '.repeat(marginRight)}`;
|
|
347
|
+
}, '');
|
|
348
|
+
console.log(headerString);
|
|
349
|
+
console.log('-'.repeat(headerString.length));
|
|
350
|
+
for (const row of processedData) {
|
|
351
|
+
const stringToPrint = columns.reduce((acc, column) => {
|
|
352
|
+
const { horizontalAlignment, overflow, padding, width } = column;
|
|
353
|
+
const value = row[column.column];
|
|
354
|
+
if (value === undefined || value === null) {
|
|
355
|
+
return `${acc}${' '.repeat(width)}`;
|
|
356
|
+
}
|
|
357
|
+
const { marginLeft, marginRight, text } = formatTextWithMargins({
|
|
358
|
+
horizontalAlignment,
|
|
359
|
+
overflow,
|
|
360
|
+
padding,
|
|
361
|
+
value,
|
|
362
|
+
width,
|
|
363
|
+
});
|
|
364
|
+
return `${acc}${' '.repeat(marginLeft)}${text}${' '.repeat(marginRight)}`;
|
|
365
|
+
}, '');
|
|
366
|
+
console.log(stringToPrint);
|
|
362
367
|
}
|
|
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();
|
|
368
|
+
console.log();
|
|
367
369
|
}
|
|
368
370
|
/**
|
|
369
|
-
* Prints a table based on the provided options. If the data length exceeds
|
|
370
|
-
* the table is rendered in
|
|
371
|
+
* Prints a table based on the provided options. If the data length exceeds 10,000 entries,
|
|
372
|
+
* the table is rendered in a non-styled format to avoid memory issues.
|
|
371
373
|
*
|
|
372
374
|
* @template T - A generic type that extends a record with string keys and unknown values.
|
|
373
375
|
* @param {TableOptions<T>} options - The options for rendering the table, including data and other configurations.
|
|
374
376
|
* @returns {void}
|
|
375
377
|
*/
|
|
376
378
|
export function printTable(options) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
+
const limit = Number.parseInt(env.OCLIF_TABLE_LIMIT ?? env.SF_TABLE_LIMIT ?? '10000', 10) ?? 10_000;
|
|
380
|
+
if (options.data.length >= limit || shouldUsePlainTable()) {
|
|
381
|
+
renderPlainTable(options);
|
|
379
382
|
return;
|
|
380
383
|
}
|
|
381
384
|
const output = new Output();
|
|
382
385
|
const instance = render(React.createElement(Table, { ...options }), { stdout: output.stream });
|
|
383
386
|
instance.unmount();
|
|
384
|
-
output.
|
|
387
|
+
output.printLastFrame();
|
|
385
388
|
}
|
|
386
389
|
/**
|
|
387
390
|
* Generates a table as a string based on the provided options.
|
|
@@ -408,7 +411,7 @@ function Container(props) {
|
|
|
408
411
|
* @throws {Error} Throws an error if the total number of rows across all tables exceeds 30,000.
|
|
409
412
|
*/
|
|
410
413
|
export function printTables(tables, options) {
|
|
411
|
-
if (tables.reduce((acc, table) => acc + table.data.length, 0) >
|
|
414
|
+
if (tables.reduce((acc, table) => acc + table.data.length, 0) > 10_000) {
|
|
412
415
|
throw new Error('The data is too large to print multiple tables. Please use `printTable` instead.');
|
|
413
416
|
}
|
|
414
417
|
const output = new Output();
|
|
@@ -422,5 +425,5 @@ export function printTables(tables, options) {
|
|
|
422
425
|
}));
|
|
423
426
|
const instance = render(React.createElement(Container, { ...options }, processed.map((table) => (React.createElement(Table, { key: sha1(table), ...table })))), { stdout: output.stream });
|
|
424
427
|
instance.unmount();
|
|
425
|
-
output.
|
|
428
|
+
output.printLastFrame();
|
|
426
429
|
}
|
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.1",
|
|
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",
|