-
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcli-support.ts
More file actions
103 lines (93 loc) · 3.03 KB
/
cli-support.ts
File metadata and controls
103 lines (93 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license.
/**
* Shared CLI support utilities for codebase scripts.
*
* Provides helpers for converting parsed CLI arguments to `CliEvent`
* and for running CLI triggers with standard exit code handling.
*
* @module
*/
import type * as cliParseArgs from "@std/cli/parse-args";
import * as results from "@eserstack/primitives/results";
import type { CliEvent } from "@eserstack/functions/triggers";
import type * as shellArgs from "@eserstack/shell/args";
import * as shellEnv from "@eserstack/shell/env";
import * as tui from "@eserstack/shell/tui";
import * as streams from "@eserstack/streams";
import * as span from "@eserstack/streams/span";
import { runtime } from "@eserstack/standards/cross-runtime";
/** Return type for {@link createCliContext}. */
export type CliContext = {
readonly ctx: tui.TuiContext;
readonly output: streams.Output;
};
/**
* Creates a `TuiContext` configured for the current environment.
*
* Detects whether stdout is a TTY (interactive terminal) or a pipe / CI
* environment and builds the context accordingly. The `output` field is
* extracted from the context for backward compatibility with call-sites
* that only need an `Output`.
*/
export const createCliContext = (): CliContext => {
const isInteractive = runtime.process.isTerminal("stdout");
const interaction: shellEnv.Interaction = isInteractive
? "interactive"
: "non-interactive";
const ctx = tui.createTuiContext({ interaction });
return { ctx, output: ctx.output };
};
/**
* Creates a standard Output wired to stdout with ANSI rendering.
*
* @deprecated Prefer {@link createCliContext} which returns a full `TuiContext`.
*/
export const createCliOutput = (): streams.Output =>
streams.output({
renderer: streams.renderers.ansi(),
sink: streams.sinks.stdout(),
});
/**
* Convert a `@std/cli/parse-args` result to a `CliEvent`.
*
* @param command - Command name
* @param parsed - Result from `parseArgs()`
* @returns A CliEvent with args and flags extracted
*/
export const toCliEvent = (
command: string,
parsed: ReturnType<typeof cliParseArgs.parseArgs>,
): CliEvent => ({
command,
args: (parsed._ ?? []) as string[],
flags: Object.fromEntries(
Object.entries(parsed).filter(([k]) => k !== "_"),
),
});
/**
* Standard `import.meta.main` handler for all CLI scripts.
*
* Matches on the `CliResult`, printing any error message and setting
* the process exit code on failure.
*
* @param result - The CliResult from a trigger invocation
* @param out - Output instance for printing errors
*/
export const runCliMain = (
result: shellArgs.CliResult<void>,
out?: streams.Output,
): void => {
results.match(result, {
ok: () => {},
fail: (error) => {
if (error.message !== undefined) {
if (out !== undefined) {
out.writeln(span.red(error.message));
} else {
console.error(error.message);
}
}
runtime.process.setExitCode(error.exitCode);
},
});
};