ardent-cli-beta 0.0.14 → 0.0.15
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/dist/commands/branch/list.js +10 -4
- package/dist/commands/connector/list.js +15 -4
- package/dist/commands/member/list.js +14 -9
- package/dist/commands/project/list.js +18 -5
- package/dist/table.d.ts +8 -0
- package/dist/table.js +53 -0
- package/oclif.manifest.json +1 -1
- package/package.json +3 -2
|
@@ -2,7 +2,7 @@ import { ArdentCommand } from '../../command.js';
|
|
|
2
2
|
import { listBranches } from '../../branches/client.js';
|
|
3
3
|
import { replaceBranchCache } from '../../branches/context.js';
|
|
4
4
|
import { requireConnector } from '../../connectors/context.js';
|
|
5
|
-
import {
|
|
5
|
+
import { renderTable } from '../../table.js';
|
|
6
6
|
export default class BranchList extends ArdentCommand {
|
|
7
7
|
static description = 'List branches in the selected connector';
|
|
8
8
|
static helpGroup = 'Branches';
|
|
@@ -13,9 +13,15 @@ export default class BranchList extends ArdentCommand {
|
|
|
13
13
|
if (!this.jsonEnabled()) {
|
|
14
14
|
if (branches.length === 0)
|
|
15
15
|
this.log('No branches found.');
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
else {
|
|
17
|
+
const lines = renderTable(branches, [
|
|
18
|
+
{ header: 'Selected', value: ({ id }) => id === updated.selectedBranch?.id ? '●' : '' },
|
|
19
|
+
{ header: 'Title', maxWidth: 30, shrinkPriority: 0, value: ({ name }) => name },
|
|
20
|
+
{ header: 'Status', shrinkPriority: 1, value: ({ state }) => state },
|
|
21
|
+
], process.stdout.columns ?? 120);
|
|
22
|
+
for (const line of lines)
|
|
23
|
+
this.log(line);
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
26
|
return { branches };
|
|
21
27
|
}
|
|
@@ -2,7 +2,7 @@ import { loadSession } from '../../auth/credentials.js';
|
|
|
2
2
|
import { ArdentCommand } from '../../command.js';
|
|
3
3
|
import { listConnectors } from '../../connectors/client.js';
|
|
4
4
|
import { replaceConnectorCache } from '../../connectors/context.js';
|
|
5
|
-
import {
|
|
5
|
+
import { renderTable } from '../../table.js';
|
|
6
6
|
export default class ConnectorList extends ArdentCommand {
|
|
7
7
|
static description = 'List connectors in the selected project';
|
|
8
8
|
static helpGroup = 'Connectors';
|
|
@@ -17,9 +17,20 @@ export default class ConnectorList extends ArdentCommand {
|
|
|
17
17
|
if (!this.jsonEnabled()) {
|
|
18
18
|
if (connectors.length === 0)
|
|
19
19
|
this.log('No connectors found.');
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
else {
|
|
21
|
+
const lines = renderTable(connectors, [
|
|
22
|
+
{ header: 'Title', maxWidth: 30, shrinkPriority: 1, value: ({ name }) => name },
|
|
23
|
+
{ header: 'Status', shrinkPriority: 2, value: ({ status }) => status },
|
|
24
|
+
{
|
|
25
|
+
header: 'Source',
|
|
26
|
+
maxWidth: 50,
|
|
27
|
+
minWidth: 20,
|
|
28
|
+
shrinkPriority: 0,
|
|
29
|
+
value: ({ source }) => `${source.host}:${source.port}/${source.database}`,
|
|
30
|
+
},
|
|
31
|
+
], process.stdout.columns ?? 120);
|
|
32
|
+
for (const line of lines)
|
|
33
|
+
this.log(line);
|
|
23
34
|
}
|
|
24
35
|
}
|
|
25
36
|
return { connectors };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { loadSession } from '../../auth/credentials.js';
|
|
2
2
|
import { ArdentCommand } from '../../command.js';
|
|
3
3
|
import { listMemberships, listReadableInvitations } from '../../members/client.js';
|
|
4
|
-
import {
|
|
4
|
+
import { renderTable } from '../../table.js';
|
|
5
5
|
export default class MemberList extends ArdentCommand {
|
|
6
6
|
static description = 'List organization members and pending invitations';
|
|
7
7
|
static helpGroup = 'Members';
|
|
@@ -17,22 +17,27 @@ export default class MemberList extends ArdentCommand {
|
|
|
17
17
|
if (!this.jsonEnabled()) {
|
|
18
18
|
const rows = [
|
|
19
19
|
...memberships.map((membership) => ({
|
|
20
|
-
email:
|
|
21
|
-
role:
|
|
20
|
+
email: membership.email,
|
|
21
|
+
role: membership.role_display_name,
|
|
22
22
|
status: 'Active',
|
|
23
23
|
})),
|
|
24
24
|
...readableInvitations.map((invitation) => ({
|
|
25
|
-
email:
|
|
26
|
-
role:
|
|
25
|
+
email: invitation.email,
|
|
26
|
+
role: invitation.role_display_name,
|
|
27
27
|
status: 'Pending',
|
|
28
28
|
})),
|
|
29
29
|
];
|
|
30
30
|
if (rows.length === 0)
|
|
31
31
|
this.log('No members found.');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
else {
|
|
33
|
+
const lines = renderTable(rows, [
|
|
34
|
+
{ header: 'Email', maxWidth: 40, minWidth: 12, shrinkPriority: 0, value: ({ email }) => email },
|
|
35
|
+
{ header: 'Role', maxWidth: 20, shrinkPriority: 1, value: ({ role }) => role },
|
|
36
|
+
{ header: 'Status', shrinkPriority: 2, value: ({ status }) => status },
|
|
37
|
+
], process.stdout.columns ?? 120);
|
|
38
|
+
for (const line of lines)
|
|
39
|
+
this.log(line);
|
|
40
|
+
}
|
|
36
41
|
if (invitations === undefined)
|
|
37
42
|
this.log('Pending invitations are not visible with this login.');
|
|
38
43
|
}
|
|
@@ -3,7 +3,7 @@ import { loadSession } from '../../auth/credentials.js';
|
|
|
3
3
|
import { ArdentCommand } from '../../command.js';
|
|
4
4
|
import { listProjects } from '../../projects/client.js';
|
|
5
5
|
import { replaceProjectCache } from '../../projects/context.js';
|
|
6
|
-
import {
|
|
6
|
+
import { renderTable } from '../../table.js';
|
|
7
7
|
export default class ProjectList extends ArdentCommand {
|
|
8
8
|
static description = 'List projects';
|
|
9
9
|
static helpGroup = 'Projects';
|
|
@@ -18,10 +18,23 @@ export default class ProjectList extends ArdentCommand {
|
|
|
18
18
|
if (!this.jsonEnabled()) {
|
|
19
19
|
if (projects.length === 0)
|
|
20
20
|
this.log('No projects found.');
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
else {
|
|
22
|
+
const lines = renderTable(projects, [
|
|
23
|
+
{
|
|
24
|
+
header: 'Title',
|
|
25
|
+
maxWidth: 30,
|
|
26
|
+
shrinkPriority: 0,
|
|
27
|
+
value: ({ id, name }) => `${id === refreshedSession.selectedProject?.id ? '●' : ' '} ${name}`,
|
|
28
|
+
},
|
|
29
|
+
], process.stdout.columns ?? 120);
|
|
30
|
+
const selectedIndex = projects.findIndex(({ id }) => id === refreshedSession.selectedProject?.id);
|
|
31
|
+
if (selectedIndex >= 0) {
|
|
32
|
+
const lineIndex = selectedIndex + 3;
|
|
33
|
+
const value = lines[lineIndex].slice(2, -2).trimEnd();
|
|
34
|
+
lines[lineIndex] = `${lines[lineIndex].slice(0, 2)}${ux.colorize('green', value)}${lines[lineIndex].slice(value.length + 2)}`;
|
|
35
|
+
}
|
|
36
|
+
for (const line of lines)
|
|
37
|
+
this.log(line);
|
|
25
38
|
}
|
|
26
39
|
}
|
|
27
40
|
return { projects };
|
package/dist/table.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TableColumn<Row> {
|
|
2
|
+
header: string;
|
|
3
|
+
maxWidth?: number;
|
|
4
|
+
minWidth?: number;
|
|
5
|
+
shrinkPriority?: number;
|
|
6
|
+
value: (row: Row) => string;
|
|
7
|
+
}
|
|
8
|
+
export declare function renderTable<Row>(rows: Row[], columns: TableColumn<Row>[], terminalWidth?: number): string[];
|
package/dist/table.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import stringWidth from 'string-width';
|
|
2
|
+
import { terminalText } from './terminal.js';
|
|
3
|
+
const graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
4
|
+
export function renderTable(rows, columns, terminalWidth = 120) {
|
|
5
|
+
const headers = columns.map(({ header }) => terminalText(header));
|
|
6
|
+
const values = rows.map((row) => columns.map(({ value }) => terminalText(value(row))));
|
|
7
|
+
const widths = columns.map((column, index) => {
|
|
8
|
+
const headerWidth = stringWidth(headers[index]);
|
|
9
|
+
const naturalWidth = Math.max(headerWidth, ...values.map((row) => stringWidth(row[index])));
|
|
10
|
+
return Math.min(naturalWidth, Math.max(headerWidth, column.maxWidth ?? naturalWidth));
|
|
11
|
+
});
|
|
12
|
+
const preferredMinimumWidths = columns.map((column, index) => Math.min(widths[index], Math.max(stringWidth(headers[index]), column.minWidth ?? stringWidth(headers[index]))));
|
|
13
|
+
const frameWidth = columns.length * 3 + 1;
|
|
14
|
+
const availableWidth = Number.isFinite(terminalWidth) ? Math.floor(terminalWidth) : 120;
|
|
15
|
+
const narrowestTableWidth = frameWidth + columns.length;
|
|
16
|
+
let overflow = widths.reduce((total, width) => total + width, frameWidth) - Math.max(narrowestTableWidth, availableWidth);
|
|
17
|
+
const shrinkOrder = columns
|
|
18
|
+
.map((column, index) => ({ index, priority: column.shrinkPriority ?? index }))
|
|
19
|
+
.sort((left, right) => left.priority - right.priority);
|
|
20
|
+
for (const minimumWidths of [preferredMinimumWidths, columns.map(() => 1)]) {
|
|
21
|
+
for (const { index } of shrinkOrder) {
|
|
22
|
+
const reduction = Math.min(Math.max(0, overflow), widths[index] - minimumWidths[index]);
|
|
23
|
+
widths[index] -= reduction;
|
|
24
|
+
overflow -= reduction;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const border = (left, divider, right) => `${left}${widths.map((width) => '─'.repeat(width + 2)).join(divider)}${right}`;
|
|
28
|
+
const cell = (value, width) => {
|
|
29
|
+
let display = value;
|
|
30
|
+
if (stringWidth(value) > width) {
|
|
31
|
+
const contentWidth = width - stringWidth('…');
|
|
32
|
+
let truncatedWidth = 0;
|
|
33
|
+
display = '';
|
|
34
|
+
for (const { segment } of graphemeSegmenter.segment(value)) {
|
|
35
|
+
const segmentWidth = stringWidth(segment);
|
|
36
|
+
if (truncatedWidth + segmentWidth > contentWidth)
|
|
37
|
+
break;
|
|
38
|
+
display += segment;
|
|
39
|
+
truncatedWidth += segmentWidth;
|
|
40
|
+
}
|
|
41
|
+
display += '…';
|
|
42
|
+
}
|
|
43
|
+
return display + ' '.repeat(width - stringWidth(display));
|
|
44
|
+
};
|
|
45
|
+
const line = (row) => `│ ${row.map((value, index) => cell(value, widths[index])).join(' │ ')} │`;
|
|
46
|
+
return [
|
|
47
|
+
border('┌', '┬', '┐'),
|
|
48
|
+
line(headers),
|
|
49
|
+
border('├', '┼', '┤'),
|
|
50
|
+
...values.map(line),
|
|
51
|
+
border('└', '┴', '┘'),
|
|
52
|
+
];
|
|
53
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ardent-cli-beta",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "The Ardent command-line interface",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@oclif/core": "^5.0.0",
|
|
44
|
-
"@oclif/plugin-autocomplete": "^4.0.0"
|
|
44
|
+
"@oclif/plugin-autocomplete": "^4.0.0",
|
|
45
|
+
"string-width": "^4.2.3"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/node": "^22.0.0",
|