@throng/cli 0.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/dist/output.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Output helpers. The rule for the whole CLI: stdout carries only data a
3
+ * pipeline might consume (`token`, `api`, `org list`); every human-facing
4
+ * message goes to stderr, so `throng token | pbcopy` stays clean.
5
+ */
6
+ const MAX_MESSAGE_LENGTH = 2000;
7
+ /**
8
+ * Make text from a server, a file system or an exception safe to put in a
9
+ * terminal: control characters (escape sequences, newlines) become `?`, and the
10
+ * length is bounded. Unlike the 200-character cap `printable` applies to one
11
+ * server field, the bound here is generous enough for a whole message.
12
+ */
13
+ export function sanitise(text) {
14
+ return text.replace(/[\u0000-\u001f\u007f-\u009f]/g, "?").slice(0, MAX_MESSAGE_LENGTH);
15
+ }
16
+ /** The one-line message for an error, with the errno of its cause when that is all that says why. */
17
+ export function describeError(error) {
18
+ const message = error instanceof Error ? error.message : String(error);
19
+ const cause = error instanceof Error ? error.cause : undefined;
20
+ return typeof cause?.code === "string" ? `${message} (${cause.code})` : message;
21
+ }
22
+ /**
23
+ * A human-facing line on stderr. Takes ONE line: `sanitise` turns newlines into
24
+ * `?`, which is right for server text but corrupts a multi-line message. Call it
25
+ * once per line.
26
+ */
27
+ export function info(message) {
28
+ process.stderr.write(`${sanitise(message)}\n`);
29
+ }
30
+ /** Pretty-printed JSON on stdout. */
31
+ export function printJson(value) {
32
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
33
+ }
34
+ /**
35
+ * A plain aligned table on stdout: a header row of the upper-cased column
36
+ * names, then one row per entry. Cell text is sanitised, since it comes from
37
+ * the server. Trailing padding is trimmed so lines compare cleanly.
38
+ */
39
+ export function printTable(rows, columns) {
40
+ const cells = rows.map((row) => columns.map((column) => sanitise(row[column] ?? "")));
41
+ const header = columns.map((column) => column.toUpperCase());
42
+ const widths = columns.map((_, i) => Math.max(header[i].length, ...cells.map((row) => row[i].length)));
43
+ const line = (values) => values.map((value, i) => value.padEnd(widths[i])).join(" ").trimEnd();
44
+ const lines = [line(header), ...cells.map(line)];
45
+ process.stdout.write(`${lines.join("\n")}\n`);
46
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@throng/cli",
3
+ "version": "0.1.0",
4
+ "description": "Command-line client for Throng",
5
+ "license": "UNLICENSED",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/col/throngx.git",
9
+ "directory": "cli"
10
+ },
11
+ "homepage": "https://github.com/col/throngx/tree/main/cli#readme",
12
+ "type": "module",
13
+ "bin": {
14
+ "throng": "./dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "test": "vitest run",
26
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
27
+ "dev": "tsx src/index.ts"
28
+ },
29
+ "dependencies": {
30
+ "commander": "^14.0.3",
31
+ "open": "^11.0.4"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20",
35
+ "tsx": "^4.23.15",
36
+ "typescript": "^7.0.2",
37
+ "vitest": "^4.1.11"
38
+ }
39
+ }