@hardfin/cli 0.1.0-dev.29 → 0.1.0-dev.30
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/README.md +17 -0
- package/dist/cli.js +11 -5
- package/dist/{program-CnXYN9xS.js → program-BZW_50HP.js} +276 -179
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,6 +87,23 @@ Three things fail locally with exit code 2, before any request is made: a value
|
|
|
87
87
|
enum, a required field that is missing, and `--unset` on a field the API will not take null
|
|
88
88
|
for.
|
|
89
89
|
|
|
90
|
+
### When a command fails
|
|
91
|
+
|
|
92
|
+
A person at a terminal reads one plain line on stderr. Anything else reads JSON, also on
|
|
93
|
+
stderr, so a pipe still carries only the result.
|
|
94
|
+
|
|
95
|
+
| Field | Holds |
|
|
96
|
+
| ----------- | ------------------------------------------------------------------------ |
|
|
97
|
+
| `code` | A fixed name for the failure, such as `not_found` or `missing_flag` |
|
|
98
|
+
| `message` | The same plain sentence a person reads |
|
|
99
|
+
| `errors` | Every error the API's envelope named, with its own numeric `statusCode` |
|
|
100
|
+
| `requestId` | The API's request ID, or null when the request never reached it |
|
|
101
|
+
| `status` | The HTTP status, or null for a failure caught before any request is made |
|
|
102
|
+
|
|
103
|
+
An agent branches on `code`. A code is never renamed and never changes meaning, while the
|
|
104
|
+
message may be reworded at any time. `hardfin agent-guide` lists every code with what it
|
|
105
|
+
means, and `src/output/failure.ts` defines them.
|
|
106
|
+
|
|
90
107
|
### Overrides
|
|
91
108
|
|
|
92
109
|
Two endpoints sometimes want one name. `DELETE /asset/{assetKey}/ownership` and
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="29560915-e7ae-5a74-b5f6-f4a6988e1b43")}catch(e){}}();
|
|
4
4
|
import module from "node:module";
|
|
5
5
|
//#region src/cli.ts
|
|
6
6
|
module.enableCompileCache?.();
|
|
@@ -14,8 +14,14 @@ process.on("unhandledRejection", (error) => void toCrash(error));
|
|
|
14
14
|
try {
|
|
15
15
|
const answer = await toQuickAnswer(process.argv.slice(2));
|
|
16
16
|
if (answer === void 0) {
|
|
17
|
-
const { toCli, wasReportAttempted } = await import("./program-
|
|
18
|
-
|
|
17
|
+
const { toCli, toParseExitCode, wasReportAttempted } = await import("./program-BZW_50HP.js");
|
|
18
|
+
try {
|
|
19
|
+
await toCli().parseAsync(process.argv);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
const code = toParseExitCode(error, process.argv.slice(2));
|
|
22
|
+
if (code === void 0) throw error;
|
|
23
|
+
process.exitCode = code;
|
|
24
|
+
}
|
|
19
25
|
if (wasReportAttempted()) process.exit();
|
|
20
26
|
} else process.stdout.write(`${answer}\n`);
|
|
21
27
|
} catch (error) {
|
|
@@ -27,7 +33,7 @@ async function toCrash(error) {
|
|
|
27
33
|
isCrashing = true;
|
|
28
34
|
process.stderr.write(`error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
29
35
|
try {
|
|
30
|
-
const { toReported } = await import("./program-
|
|
36
|
+
const { toReported } = await import("./program-BZW_50HP.js");
|
|
31
37
|
await toReported(error, false, void 0, "fatal");
|
|
32
38
|
} finally {
|
|
33
39
|
process.exit(1);
|
|
@@ -45,4 +51,4 @@ async function toQuickAnswer(args) {
|
|
|
45
51
|
export {};
|
|
46
52
|
|
|
47
53
|
//# sourceMappingURL=cli.js.map
|
|
48
|
-
//# debugId=
|
|
54
|
+
//# debugId=29560915-e7ae-5a74-b5f6-f4a6988e1b43
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5c189832-33ce-5032-b0e0-fc3a33cf5b1d")}catch(e){}}();
|
|
4
4
|
import { a as defineCommand, i as GLOBAL_FLAGS, r as ExitCode, t as toInvocation } from "./scrub-VtQmxap1.js";
|
|
5
5
|
import { n as toCompletion, t as toAnswer$1 } from "./completion-tree-rR_Rmeij.js";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
|
-
import { Command, Option } from "commander";
|
|
7
|
+
import { Command, CommanderError, Option } from "commander";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { accessSync, chmodSync, closeSync, constants, existsSync, mkdirSync, openAsBlob, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
|
|
10
10
|
import { basename, delimiter, dirname, join, resolve } from "node:path";
|
|
@@ -144,152 +144,6 @@ function toOrigin(apiUrl) {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
//#endregion
|
|
147
|
-
//#region src/output/writer.ts
|
|
148
|
-
/**
|
|
149
|
-
* toText reads a value a caller supplied, which arrives typed as unknown. An object would
|
|
150
|
-
* otherwise reach a request as the text "[object Object]".
|
|
151
|
-
*/
|
|
152
|
-
function toText(value) {
|
|
153
|
-
if (typeof value === "string") return value;
|
|
154
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
155
|
-
if (value === void 0 || value === null) return "";
|
|
156
|
-
return JSON.stringify(value);
|
|
157
|
-
}
|
|
158
|
-
/** writeData prints a command's result on stdout. */
|
|
159
|
-
function writeData(value) {
|
|
160
|
-
if (typeof value === "string") {
|
|
161
|
-
process.stdout.write(value.endsWith("\n") ? value : `${value}\n`);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
process.stdout.write(`${JSON.stringify(value ?? null, null, 2)}\n`);
|
|
165
|
-
}
|
|
166
|
-
/** writeFailure prints why a command failed on stderr, as text or as JSON. */
|
|
167
|
-
function writeFailure(message, isJSON, errors, requestId, status) {
|
|
168
|
-
if (!isJSON) {
|
|
169
|
-
process.stderr.write(`error: ${message}${status === void 0 ? "" : ` (HTTP ${status})`}\n`);
|
|
170
|
-
for (const entry of errors?.slice(1) ?? []) process.stderr.write(` ${entry.error} (${entry.statusCode})\n`);
|
|
171
|
-
if (requestId) process.stderr.write(` request ${requestId}\n`);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const payload = {
|
|
175
|
-
errors: errors ?? [{
|
|
176
|
-
error: message,
|
|
177
|
-
statusCode: 0
|
|
178
|
-
}],
|
|
179
|
-
requestId: requestId ?? null,
|
|
180
|
-
status: status ?? null
|
|
181
|
-
};
|
|
182
|
-
process.stderr.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
183
|
-
}
|
|
184
|
-
/** isJSONOutput decides whether this invocation prints machine-readable output. */
|
|
185
|
-
function isJSONOutput(flags) {
|
|
186
|
-
if (flags["json"] === true) return true;
|
|
187
|
-
return !process.stdout.isTTY;
|
|
188
|
-
}
|
|
189
|
-
/** version is what this build reports, read from the published package manifest. */
|
|
190
|
-
const version$1 = createRequire(import.meta.url)("../package.json").version;
|
|
191
|
-
//#endregion
|
|
192
|
-
//#region src/command/agent-guide.ts
|
|
193
|
-
const agentGuideCommand = defineCommand({
|
|
194
|
-
name: "agent-guide",
|
|
195
|
-
summary: "Print instructions an agent can follow to use this CLI",
|
|
196
|
-
description: "Writes Markdown describing every command, its flags, and its exit codes. Save it as a skill file, an AGENTS.md section, or paste it into a system prompt.",
|
|
197
|
-
arguments: [],
|
|
198
|
-
flags: [{
|
|
199
|
-
name: "json",
|
|
200
|
-
description: "Print the command registry as JSON instead of Markdown",
|
|
201
|
-
schema: z.boolean().optional()
|
|
202
|
-
}],
|
|
203
|
-
examples: [{
|
|
204
|
-
description: "Write a skill file",
|
|
205
|
-
command: "hardfin agent-guide > SKILL.md"
|
|
206
|
-
}, {
|
|
207
|
-
description: "Inspect the registry",
|
|
208
|
-
command: "hardfin agent-guide --json"
|
|
209
|
-
}],
|
|
210
|
-
run: runAgentGuide
|
|
211
|
-
});
|
|
212
|
-
/** toGuide renders the registry as the Markdown an agent reads. */
|
|
213
|
-
function toGuide(commands, version) {
|
|
214
|
-
const lines = [
|
|
215
|
-
"# Hardfin CLI",
|
|
216
|
-
"",
|
|
217
|
-
`The \`hardfin\` command calls the Hardfin API. This guide describes version ${version} of the CLI, which speaks API version ${API_VERSION}.`,
|
|
218
|
-
"",
|
|
219
|
-
"## Before calling",
|
|
220
|
-
"",
|
|
221
|
-
"- Authenticate by setting `HARDFIN_API_KEY`, or by running `hardfin login`",
|
|
222
|
-
"- Every command prints JSON on stdout and diagnostics on stderr",
|
|
223
|
-
"- Output is JSON whenever stdout is not a terminal, so no flag is needed when calling from code",
|
|
224
|
-
"",
|
|
225
|
-
"## Exit codes",
|
|
226
|
-
"",
|
|
227
|
-
"| Code | Means |",
|
|
228
|
-
"| --- | --- |",
|
|
229
|
-
"| 0 | The command succeeded |",
|
|
230
|
-
"| 1 | The command failed |",
|
|
231
|
-
"| 2 | The command was called wrongly |",
|
|
232
|
-
"| 4 | No usable credential |",
|
|
233
|
-
"| 130 | The person pressed Ctrl-C |",
|
|
234
|
-
"",
|
|
235
|
-
"## Commands",
|
|
236
|
-
""
|
|
237
|
-
];
|
|
238
|
-
for (const command of commands.filter((command) => !command.hidden)) lines.push(...toCommandLines(command, []));
|
|
239
|
-
return lines.join("\n");
|
|
240
|
-
}
|
|
241
|
-
/** toCommandLines describes one command and everything nested under it. */
|
|
242
|
-
function toCommandLines(command, parents) {
|
|
243
|
-
const path = [...parents, command.name];
|
|
244
|
-
const lines = [
|
|
245
|
-
`### \`hardfin ${path.join(" ")}\``,
|
|
246
|
-
"",
|
|
247
|
-
command.description ?? command.summary,
|
|
248
|
-
""
|
|
249
|
-
];
|
|
250
|
-
if (command.arguments.length > 0) {
|
|
251
|
-
lines.push("| Argument | Required | Holds |", "| --- | --- | --- |");
|
|
252
|
-
for (const argument of command.arguments) lines.push(`| \`${argument.name}\` | ${argument.required ? "yes" : "no"} | ${argument.description} |`);
|
|
253
|
-
lines.push("");
|
|
254
|
-
}
|
|
255
|
-
if (command.flags.length > 0) {
|
|
256
|
-
lines.push("| Flag | Takes | Does |", "| --- | --- | --- |");
|
|
257
|
-
for (const flag of command.flags) {
|
|
258
|
-
const name = flag.short ? `-${flag.short}, --${flag.name}` : `--${flag.name}`;
|
|
259
|
-
lines.push(`| \`${name}\` | ${flag.valueName ?? "nothing"} | ${flag.description} |`);
|
|
260
|
-
}
|
|
261
|
-
lines.push("");
|
|
262
|
-
}
|
|
263
|
-
for (const example of command.examples) lines.push(`${example.description}:`, "", "```sh", example.command, "```", "");
|
|
264
|
-
for (const subcommand of command.subcommands ?? []) lines.push(...toCommandLines(subcommand, path));
|
|
265
|
-
return lines;
|
|
266
|
-
}
|
|
267
|
-
async function runAgentGuide(input) {
|
|
268
|
-
if (input.flags["json"] === true) {
|
|
269
|
-
writeData(input.commands.map(toSummary));
|
|
270
|
-
return ExitCode.OK;
|
|
271
|
-
}
|
|
272
|
-
writeData(toGuide(input.commands, version$1));
|
|
273
|
-
return ExitCode.OK;
|
|
274
|
-
}
|
|
275
|
-
function toSummary(command) {
|
|
276
|
-
return {
|
|
277
|
-
name: command.name,
|
|
278
|
-
summary: command.summary,
|
|
279
|
-
description: command.description ?? command.summary,
|
|
280
|
-
arguments: command.arguments,
|
|
281
|
-
flags: command.flags.map((flag) => ({
|
|
282
|
-
name: flag.name,
|
|
283
|
-
short: flag.short ?? null,
|
|
284
|
-
description: flag.description,
|
|
285
|
-
valueName: flag.valueName ?? null,
|
|
286
|
-
repeatable: flag.repeatable ?? false
|
|
287
|
-
})),
|
|
288
|
-
examples: command.examples,
|
|
289
|
-
subcommands: command.subcommands?.filter((entry) => !entry.hidden).map(toSummary)
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
//#endregion
|
|
293
147
|
//#region src/auth/jwt.ts
|
|
294
148
|
/**
|
|
295
149
|
* toClaims reads an access token's payload for display. Nothing here verifies the
|
|
@@ -620,6 +474,51 @@ function keep(issuer, document) {
|
|
|
620
474
|
} catch {}
|
|
621
475
|
}
|
|
622
476
|
//#endregion
|
|
477
|
+
//#region src/output/writer.ts
|
|
478
|
+
/**
|
|
479
|
+
* toText reads a value a caller supplied, which arrives typed as unknown. An object would
|
|
480
|
+
* otherwise reach a request as the text "[object Object]".
|
|
481
|
+
*/
|
|
482
|
+
function toText(value) {
|
|
483
|
+
if (typeof value === "string") return value;
|
|
484
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
485
|
+
if (value === void 0 || value === null) return "";
|
|
486
|
+
return JSON.stringify(value);
|
|
487
|
+
}
|
|
488
|
+
/** writeData prints a command's result on stdout. */
|
|
489
|
+
function writeData(value) {
|
|
490
|
+
if (typeof value === "string") {
|
|
491
|
+
process.stdout.write(value.endsWith("\n") ? value : `${value}\n`);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
process.stdout.write(`${JSON.stringify(value ?? null, null, 2)}\n`);
|
|
495
|
+
}
|
|
496
|
+
/** writeFailure prints why a command failed on stderr, with a code only a machine reading JSON sees. */
|
|
497
|
+
function writeFailure(code, message, isJSON, errors, requestId, status) {
|
|
498
|
+
if (!isJSON) {
|
|
499
|
+
process.stderr.write(`error: ${message}${status === void 0 ? "" : ` (HTTP ${status})`}\n`);
|
|
500
|
+
for (const entry of errors?.slice(1) ?? []) process.stderr.write(` ${entry.error} (${entry.statusCode})\n`);
|
|
501
|
+
if (requestId) process.stderr.write(` request ${requestId}\n`);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const payload = {
|
|
505
|
+
code,
|
|
506
|
+
message,
|
|
507
|
+
errors: errors ?? [{
|
|
508
|
+
error: message,
|
|
509
|
+
statusCode: 0
|
|
510
|
+
}],
|
|
511
|
+
requestId: requestId ?? null,
|
|
512
|
+
status: status ?? null
|
|
513
|
+
};
|
|
514
|
+
process.stderr.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
515
|
+
}
|
|
516
|
+
/** isJSONOutput decides whether this invocation prints machine-readable output. */
|
|
517
|
+
function isJSONOutput(flags) {
|
|
518
|
+
if (flags["json"] === true) return true;
|
|
519
|
+
return !process.stdout.isTTY;
|
|
520
|
+
}
|
|
521
|
+
//#endregion
|
|
623
522
|
//#region src/auth/grant.ts
|
|
624
523
|
const TokenResponse = z.looseObject({
|
|
625
524
|
access_token: z.string(),
|
|
@@ -980,6 +879,172 @@ function toStatusMessage(status) {
|
|
|
980
879
|
if (status === 403) return "the organization is deactivated, or its access has ended";
|
|
981
880
|
return `the request failed with status ${status}`;
|
|
982
881
|
}
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/output/failure.ts
|
|
884
|
+
/** FAILURE_CODES is every code a failure can carry, and none is ever renamed or given a new meaning. */
|
|
885
|
+
const FAILURE_CODES = {
|
|
886
|
+
unknown_command: "No command has that name. Run hardfin --help for the list",
|
|
887
|
+
invalid_arguments: "The command was given the wrong positional arguments",
|
|
888
|
+
missing_flag: "A flag the command needs was not given",
|
|
889
|
+
invalid_flag: "A flag was given a value it does not take",
|
|
890
|
+
invalid_input: "A file the command was given cannot be read, or does not hold JSON",
|
|
891
|
+
empty_request: "The command would change nothing, because no field was given",
|
|
892
|
+
output_required: "The answer is a file, and needs --output or a pipe",
|
|
893
|
+
not_confirmed: "The change was not confirmed. Pass --yes to confirm it without a terminal",
|
|
894
|
+
shell_unavailable: "The shell did not say where its startup file is",
|
|
895
|
+
invalid_config: "A config file or setting cannot be read",
|
|
896
|
+
not_signed_in: "No usable credential. Run hardfin login, or set HARDFIN_API_KEY",
|
|
897
|
+
sign_in_failed: "Signing in did not finish",
|
|
898
|
+
unreachable: "The CLI could not connect to the server",
|
|
899
|
+
timed_out: "Something the CLI waited on took too long",
|
|
900
|
+
busy: "Another hardfin command is holding the credential lock",
|
|
901
|
+
bad_request: "The API refused the request as written (HTTP 400)",
|
|
902
|
+
unauthorized: "The API did not accept the credential (HTTP 401)",
|
|
903
|
+
forbidden: "The credential may not do this (HTTP 403)",
|
|
904
|
+
not_found: "The record or path does not exist (HTTP 404)",
|
|
905
|
+
conflict: "The request conflicts with the record's current state (HTTP 409)",
|
|
906
|
+
too_large: "The request is larger than the API accepts (HTTP 413)",
|
|
907
|
+
invalid_request: "The API could not process the request (HTTP 422)",
|
|
908
|
+
rate_limited: "Too many requests. Wait, then try again (HTTP 429)",
|
|
909
|
+
server_error: "The API failed to answer (HTTP 5xx)",
|
|
910
|
+
api_error: "The API refused the request with another status",
|
|
911
|
+
internal_error: "A problem in hardfin itself, which has been reported"
|
|
912
|
+
};
|
|
913
|
+
/** toStatusCode names a refusal by the HTTP status the API answered with. */
|
|
914
|
+
function toStatusCode(status) {
|
|
915
|
+
switch (status) {
|
|
916
|
+
case 400: return "bad_request";
|
|
917
|
+
case 401: return "unauthorized";
|
|
918
|
+
case 403: return "forbidden";
|
|
919
|
+
case 404: return "not_found";
|
|
920
|
+
case 409: return "conflict";
|
|
921
|
+
case 413: return "too_large";
|
|
922
|
+
case 422: return "invalid_request";
|
|
923
|
+
case 429: return "rate_limited";
|
|
924
|
+
default: return status >= 500 ? "server_error" : "api_error";
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
/** toErrorCode names a failure nothing handled closer to where it happened. */
|
|
928
|
+
function toErrorCode(error) {
|
|
929
|
+
if (error instanceof RequestFailure) return toStatusCode(error.status);
|
|
930
|
+
if (error instanceof NoCredential) return "not_signed_in";
|
|
931
|
+
if (error instanceof ConfigFailure) return "invalid_config";
|
|
932
|
+
if (error instanceof Unreachable) return "unreachable";
|
|
933
|
+
if (error instanceof TimedOut) return "timed_out";
|
|
934
|
+
if (error instanceof LockHeld) return "busy";
|
|
935
|
+
return "internal_error";
|
|
936
|
+
}
|
|
937
|
+
/** version is what this build reports, read from the published package manifest. */
|
|
938
|
+
const version$1 = createRequire(import.meta.url)("../package.json").version;
|
|
939
|
+
//#endregion
|
|
940
|
+
//#region src/command/agent-guide.ts
|
|
941
|
+
const agentGuideCommand = defineCommand({
|
|
942
|
+
name: "agent-guide",
|
|
943
|
+
summary: "Print instructions an agent can follow to use this CLI",
|
|
944
|
+
description: "Writes Markdown describing every command, its flags, and its exit codes. Save it as a skill file, an AGENTS.md section, or paste it into a system prompt.",
|
|
945
|
+
arguments: [],
|
|
946
|
+
flags: [{
|
|
947
|
+
name: "json",
|
|
948
|
+
description: "Print the command registry as JSON instead of Markdown",
|
|
949
|
+
schema: z.boolean().optional()
|
|
950
|
+
}],
|
|
951
|
+
examples: [{
|
|
952
|
+
description: "Write a skill file",
|
|
953
|
+
command: "hardfin agent-guide > SKILL.md"
|
|
954
|
+
}, {
|
|
955
|
+
description: "Inspect the registry",
|
|
956
|
+
command: "hardfin agent-guide --json"
|
|
957
|
+
}],
|
|
958
|
+
run: runAgentGuide
|
|
959
|
+
});
|
|
960
|
+
/** toGuide renders the registry as the Markdown an agent reads. */
|
|
961
|
+
function toGuide(commands, version) {
|
|
962
|
+
const lines = [
|
|
963
|
+
"# Hardfin CLI",
|
|
964
|
+
"",
|
|
965
|
+
`The \`hardfin\` command calls the Hardfin API. This guide describes version ${version} of the CLI, which speaks API version ${API_VERSION}.`,
|
|
966
|
+
"",
|
|
967
|
+
"## Before calling",
|
|
968
|
+
"",
|
|
969
|
+
"- Authenticate by setting `HARDFIN_API_KEY`, or by running `hardfin login`",
|
|
970
|
+
"- Every command prints JSON on stdout and diagnostics on stderr",
|
|
971
|
+
"- Output is JSON whenever stdout is not a terminal, so no flag is needed when calling from code",
|
|
972
|
+
"",
|
|
973
|
+
"## Exit codes",
|
|
974
|
+
"",
|
|
975
|
+
"| Code | Means |",
|
|
976
|
+
"| --- | --- |",
|
|
977
|
+
"| 0 | The command succeeded |",
|
|
978
|
+
"| 1 | The command failed |",
|
|
979
|
+
"| 2 | The command was called wrongly |",
|
|
980
|
+
"| 4 | No usable credential |",
|
|
981
|
+
"| 130 | The person pressed Ctrl-C |",
|
|
982
|
+
"",
|
|
983
|
+
"## Error codes",
|
|
984
|
+
"",
|
|
985
|
+
"A failed command prints JSON on stderr with a `code`, a `message`, the API's `errors`, its `requestId` and the HTTP `status`. Branch on `code`, which never changes meaning. The message is for a person.",
|
|
986
|
+
"",
|
|
987
|
+
"| Code | Means |",
|
|
988
|
+
"| --- | --- |",
|
|
989
|
+
...Object.entries(FAILURE_CODES).map(([code, meaning]) => `| \`${code}\` | ${meaning} |`),
|
|
990
|
+
"",
|
|
991
|
+
"## Commands",
|
|
992
|
+
""
|
|
993
|
+
];
|
|
994
|
+
for (const command of commands.filter((command) => !command.hidden)) lines.push(...toCommandLines(command, []));
|
|
995
|
+
return lines.join("\n");
|
|
996
|
+
}
|
|
997
|
+
/** toCommandLines describes one command and everything nested under it. */
|
|
998
|
+
function toCommandLines(command, parents) {
|
|
999
|
+
const path = [...parents, command.name];
|
|
1000
|
+
const lines = [
|
|
1001
|
+
`### \`hardfin ${path.join(" ")}\``,
|
|
1002
|
+
"",
|
|
1003
|
+
command.description ?? command.summary,
|
|
1004
|
+
""
|
|
1005
|
+
];
|
|
1006
|
+
if (command.arguments.length > 0) {
|
|
1007
|
+
lines.push("| Argument | Required | Holds |", "| --- | --- | --- |");
|
|
1008
|
+
for (const argument of command.arguments) lines.push(`| \`${argument.name}\` | ${argument.required ? "yes" : "no"} | ${argument.description} |`);
|
|
1009
|
+
lines.push("");
|
|
1010
|
+
}
|
|
1011
|
+
if (command.flags.length > 0) {
|
|
1012
|
+
lines.push("| Flag | Takes | Does |", "| --- | --- | --- |");
|
|
1013
|
+
for (const flag of command.flags) {
|
|
1014
|
+
const name = flag.short ? `-${flag.short}, --${flag.name}` : `--${flag.name}`;
|
|
1015
|
+
lines.push(`| \`${name}\` | ${flag.valueName ?? "nothing"} | ${flag.description} |`);
|
|
1016
|
+
}
|
|
1017
|
+
lines.push("");
|
|
1018
|
+
}
|
|
1019
|
+
for (const example of command.examples) lines.push(`${example.description}:`, "", "```sh", example.command, "```", "");
|
|
1020
|
+
for (const subcommand of command.subcommands ?? []) lines.push(...toCommandLines(subcommand, path));
|
|
1021
|
+
return lines;
|
|
1022
|
+
}
|
|
1023
|
+
async function runAgentGuide(input) {
|
|
1024
|
+
if (input.flags["json"] === true) {
|
|
1025
|
+
writeData(input.commands.map(toSummary));
|
|
1026
|
+
return ExitCode.OK;
|
|
1027
|
+
}
|
|
1028
|
+
writeData(toGuide(input.commands, version$1));
|
|
1029
|
+
return ExitCode.OK;
|
|
1030
|
+
}
|
|
1031
|
+
function toSummary(command) {
|
|
1032
|
+
return {
|
|
1033
|
+
name: command.name,
|
|
1034
|
+
summary: command.summary,
|
|
1035
|
+
description: command.description ?? command.summary,
|
|
1036
|
+
arguments: command.arguments,
|
|
1037
|
+
flags: command.flags.map((flag) => ({
|
|
1038
|
+
name: flag.name,
|
|
1039
|
+
short: flag.short ?? null,
|
|
1040
|
+
description: flag.description,
|
|
1041
|
+
valueName: flag.valueName ?? null,
|
|
1042
|
+
repeatable: flag.repeatable ?? false
|
|
1043
|
+
})),
|
|
1044
|
+
examples: command.examples,
|
|
1045
|
+
subcommands: command.subcommands?.filter((entry) => !entry.hidden).map(toSummary)
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
983
1048
|
const apiCommand = defineCommand({
|
|
984
1049
|
name: "api",
|
|
985
1050
|
summary: "Call a Hardfin API endpoint and print what it answers",
|
|
@@ -1043,23 +1108,23 @@ const apiCommand = defineCommand({
|
|
|
1043
1108
|
async function runApi(input) {
|
|
1044
1109
|
const path = input.args[0];
|
|
1045
1110
|
if (!path) {
|
|
1046
|
-
writeFailure("a path is required, such as /customer", input.isJSON);
|
|
1111
|
+
writeFailure("invalid_arguments", "a path is required, such as /customer", input.isJSON);
|
|
1047
1112
|
return ExitCode.USAGE;
|
|
1048
1113
|
}
|
|
1049
1114
|
if (path.split("/").includes("..")) {
|
|
1050
|
-
writeFailure("a path stays inside the API, so it cannot contain ..", input.isJSON);
|
|
1115
|
+
writeFailure("invalid_arguments", "a path stays inside the API, so it cannot contain ..", input.isJSON);
|
|
1051
1116
|
return ExitCode.USAGE;
|
|
1052
1117
|
}
|
|
1053
1118
|
const query = toQuery$1(input.flags["field"]);
|
|
1054
1119
|
if (query === void 0) {
|
|
1055
|
-
writeFailure("each --field is key=value, such as -f limit=50", input.isJSON);
|
|
1120
|
+
writeFailure("invalid_flag", "each --field is key=value, such as -f limit=50", input.isJSON);
|
|
1056
1121
|
return ExitCode.USAGE;
|
|
1057
1122
|
}
|
|
1058
1123
|
let body;
|
|
1059
1124
|
if (typeof input.flags["input"] === "string") {
|
|
1060
1125
|
body = toBody$1(input.flags["input"]);
|
|
1061
1126
|
if (body === void 0) {
|
|
1062
|
-
writeFailure(`${input.flags["input"]} does not hold JSON`, input.isJSON);
|
|
1127
|
+
writeFailure("invalid_input", `${input.flags["input"]} does not hold JSON`, input.isJSON);
|
|
1063
1128
|
return ExitCode.USAGE;
|
|
1064
1129
|
}
|
|
1065
1130
|
}
|
|
@@ -1075,11 +1140,11 @@ async function runApi(input) {
|
|
|
1075
1140
|
return ExitCode.OK;
|
|
1076
1141
|
} catch (error) {
|
|
1077
1142
|
if (error instanceof NoCredential) {
|
|
1078
|
-
writeFailure(error.message, input.isJSON);
|
|
1143
|
+
writeFailure("not_signed_in", error.message, input.isJSON);
|
|
1079
1144
|
return ExitCode.NOT_AUTHENTICATED;
|
|
1080
1145
|
}
|
|
1081
1146
|
if (error instanceof RequestFailure) {
|
|
1082
|
-
writeFailure(error.message, input.isJSON, error.errors, error.requestId, error.status);
|
|
1147
|
+
writeFailure(toStatusCode(error.status), error.message, input.isJSON, error.errors, error.requestId, error.status);
|
|
1083
1148
|
return error.status === 401 ? ExitCode.NOT_AUTHENTICATED : ExitCode.ERROR;
|
|
1084
1149
|
}
|
|
1085
1150
|
throw error;
|
|
@@ -1485,17 +1550,17 @@ async function runChange(input, change) {
|
|
|
1485
1550
|
const place = toPlace();
|
|
1486
1551
|
const shell = input.args[0] ?? toShell(place);
|
|
1487
1552
|
if (!shell || !SHELLS.includes(shell)) {
|
|
1488
|
-
writeFailure(`name the shell to ${change} for: ${SHELLS.join(", ")}`, input.isJSON);
|
|
1553
|
+
writeFailure("invalid_arguments", `name the shell to ${change} for: ${SHELLS.join(", ")}`, input.isJSON);
|
|
1489
1554
|
return ExitCode.USAGE;
|
|
1490
1555
|
}
|
|
1491
1556
|
const plan = toPlan(shell, place);
|
|
1492
1557
|
if (change === "install" && shell === "powershell" && !plan.startup) {
|
|
1493
|
-
writeFailure("PowerShell did not report its profile, so there is nowhere to load the script from", input.isJSON);
|
|
1558
|
+
writeFailure("shell_unavailable", "PowerShell did not report its profile, so there is nowhere to load the script from", input.isJSON);
|
|
1494
1559
|
return ExitCode.ERROR;
|
|
1495
1560
|
}
|
|
1496
1561
|
process.stderr.write(toDescription(plan, change));
|
|
1497
1562
|
if (!await isConfirmed(input.flags["yes"] === true)) {
|
|
1498
|
-
writeFailure(process.stdin.isTTY ? "nothing was changed" : "nothing was changed. Pass --yes to change it without a terminal", input.isJSON);
|
|
1563
|
+
writeFailure("not_confirmed", process.stdin.isTTY ? "nothing was changed" : "nothing was changed. Pass --yes to change it without a terminal", input.isJSON);
|
|
1499
1564
|
return ExitCode.USAGE;
|
|
1500
1565
|
}
|
|
1501
1566
|
if (change === "install") {
|
|
@@ -1658,7 +1723,7 @@ function toSchemaValues(schema) {
|
|
|
1658
1723
|
async function runCompletion(input) {
|
|
1659
1724
|
const shell = input.args[0] ?? "";
|
|
1660
1725
|
if (!SHELLS.includes(shell)) {
|
|
1661
|
-
writeFailure(`${shell || "no shell"} is not one this CLI writes for. Choose ${SHELLS.join(", ")}`, input.isJSON);
|
|
1726
|
+
writeFailure("invalid_arguments", `${shell || "no shell"} is not one this CLI writes for. Choose ${SHELLS.join(", ")}`, input.isJSON);
|
|
1662
1727
|
return ExitCode.USAGE;
|
|
1663
1728
|
}
|
|
1664
1729
|
writeData(toScript(shell));
|
|
@@ -2064,25 +2129,25 @@ async function runLogin(input) {
|
|
|
2064
2129
|
}
|
|
2065
2130
|
process.stderr.write(callback.error ? "\n" : "\nApproved, finishing the sign in\n");
|
|
2066
2131
|
if (callback.error) {
|
|
2067
|
-
writeFailure(`sign in was refused: ${callback.error}${callback.errorDescription ? `, ${callback.errorDescription}` : ""}`, input.isJSON);
|
|
2132
|
+
writeFailure("sign_in_failed", `sign in was refused: ${callback.error}${callback.errorDescription ? `, ${callback.errorDescription}` : ""}`, input.isJSON);
|
|
2068
2133
|
return ExitCode.ERROR;
|
|
2069
2134
|
}
|
|
2070
2135
|
if (callback.source === "listener" ? callback.state !== state : callback.state !== void 0 && callback.state !== state) {
|
|
2071
|
-
writeFailure("the browser came back with a state this sign in did not send", input.isJSON);
|
|
2136
|
+
writeFailure("sign_in_failed", "the browser came back with a state this sign in did not send", input.isJSON);
|
|
2072
2137
|
return ExitCode.ERROR;
|
|
2073
2138
|
}
|
|
2074
2139
|
if (callback.issuer !== void 0 && callback.issuer.replace(/\/+$/, "") !== metadata.issuer.replace(/\/+$/, "")) {
|
|
2075
|
-
writeFailure(`the browser came back from ${callback.issuer}, which is not ${metadata.issuer}`, input.isJSON);
|
|
2140
|
+
writeFailure("sign_in_failed", `the browser came back from ${callback.issuer}, which is not ${metadata.issuer}`, input.isJSON);
|
|
2076
2141
|
return ExitCode.ERROR;
|
|
2077
2142
|
}
|
|
2078
2143
|
if (!callback.code) {
|
|
2079
|
-
writeFailure("the browser came back without an authorization code", input.isJSON);
|
|
2144
|
+
writeFailure("sign_in_failed", "the browser came back without an authorization code", input.isJSON);
|
|
2080
2145
|
return ExitCode.ERROR;
|
|
2081
2146
|
}
|
|
2082
2147
|
return await toSignedIn(input, metadata, await toTokensFromCode(metadata.token_endpoint, clientId, callback.code, listener.redirectUri, pkce));
|
|
2083
2148
|
} catch (error) {
|
|
2084
2149
|
if (error instanceof DiscoveryFailure || error instanceof GrantFailure) {
|
|
2085
|
-
writeFailure(error.message, input.isJSON);
|
|
2150
|
+
writeFailure("sign_in_failed", error.message, input.isJSON);
|
|
2086
2151
|
return ExitCode.ERROR;
|
|
2087
2152
|
}
|
|
2088
2153
|
throw error;
|
|
@@ -2092,7 +2157,7 @@ async function runLogin(input) {
|
|
|
2092
2157
|
async function runDeviceLogin(input, metadata, scope) {
|
|
2093
2158
|
const settings = input.resolved.settings;
|
|
2094
2159
|
if (!metadata.device_authorization_endpoint) {
|
|
2095
|
-
writeFailure(`${metadata.issuer} does not offer the device grant, so sign in without --device`, input.isJSON);
|
|
2160
|
+
writeFailure("sign_in_failed", `${metadata.issuer} does not offer the device grant, so sign in without --device`, input.isJSON);
|
|
2096
2161
|
return ExitCode.ERROR;
|
|
2097
2162
|
}
|
|
2098
2163
|
const device = await toDeviceAuthorization(metadata.device_authorization_endpoint, settings.clientId, scope);
|
|
@@ -2126,7 +2191,7 @@ async function toDeviceTokens(approved, typed) {
|
|
|
2126
2191
|
async function toSignedIn(input, metadata, tokens) {
|
|
2127
2192
|
const refreshToken = tokens.refreshToken;
|
|
2128
2193
|
if (!refreshToken) {
|
|
2129
|
-
writeFailure("the authorization server issued no refresh token, so this sign in cannot be kept", input.isJSON);
|
|
2194
|
+
writeFailure("sign_in_failed", "the authorization server issued no refresh token, so this sign in cannot be kept", input.isJSON);
|
|
2130
2195
|
return ExitCode.ERROR;
|
|
2131
2196
|
}
|
|
2132
2197
|
const backend = await withLock(() => keep$1(input.resolved.settings.issuerUrl, refreshToken, tokens.refreshExpiresAt));
|
|
@@ -3059,28 +3124,28 @@ function defineOperation(operation) {
|
|
|
3059
3124
|
async function runOperation(operation, input) {
|
|
3060
3125
|
const path = toPath(operation, input.args);
|
|
3061
3126
|
if (path === void 0) {
|
|
3062
|
-
writeFailure(`this command takes ${operation.pathParameters.length} argument(s)`, input.isJSON);
|
|
3127
|
+
writeFailure("invalid_arguments", `this command takes ${operation.pathParameters.length} argument(s)`, input.isJSON);
|
|
3063
3128
|
return ExitCode.USAGE;
|
|
3064
3129
|
}
|
|
3065
3130
|
const missing = operation.bodyFlags.concat(operation.upload?.fields ?? []).filter((flag) => flag.required && input.flags[toOptionKey(flag.name)] === void 0);
|
|
3066
3131
|
if (missing.length > 0) {
|
|
3067
|
-
writeFailure(`this command needs ${missing.map((flag) => `--${flag.name}`).join(", ")}`, input.isJSON);
|
|
3132
|
+
writeFailure("missing_flag", `this command needs ${missing.map((flag) => `--${flag.name}`).join(", ")}`, input.isJSON);
|
|
3068
3133
|
return ExitCode.USAGE;
|
|
3069
3134
|
}
|
|
3070
3135
|
const body = toBody(operation, input.flags);
|
|
3071
3136
|
if (body instanceof Error) {
|
|
3072
|
-
writeFailure(body.message, input.isJSON);
|
|
3137
|
+
writeFailure("invalid_flag", body.message, input.isJSON);
|
|
3073
3138
|
return ExitCode.USAGE;
|
|
3074
3139
|
}
|
|
3075
3140
|
if (operation.bodyFlags.length > 0 && body === void 0) {
|
|
3076
|
-
writeFailure(`this command changes nothing unless a flag is given, such as ${operation.bodyFlags.slice(0, 3).map((flag) => `--${flag.name}`).join(", ")}. Run it with --help for the rest`, input.isJSON);
|
|
3141
|
+
writeFailure("empty_request", `this command changes nothing unless a flag is given, such as ${operation.bodyFlags.slice(0, 3).map((flag) => `--${flag.name}`).join(", ")}. Run it with --help for the rest`, input.isJSON);
|
|
3077
3142
|
return ExitCode.USAGE;
|
|
3078
3143
|
}
|
|
3079
3144
|
let form;
|
|
3080
3145
|
if (operation.upload) {
|
|
3081
3146
|
const built = await toForm(operation.upload, input.flags);
|
|
3082
3147
|
if (built instanceof Error) {
|
|
3083
|
-
writeFailure(built.message, input.isJSON);
|
|
3148
|
+
writeFailure("invalid_input", built.message, input.isJSON);
|
|
3084
3149
|
return ExitCode.USAGE;
|
|
3085
3150
|
}
|
|
3086
3151
|
form = built;
|
|
@@ -3101,11 +3166,11 @@ async function runOperation(operation, input) {
|
|
|
3101
3166
|
return ExitCode.OK;
|
|
3102
3167
|
} catch (error) {
|
|
3103
3168
|
if (error instanceof NoCredential) {
|
|
3104
|
-
writeFailure(error.message, input.isJSON);
|
|
3169
|
+
writeFailure("not_signed_in", error.message, input.isJSON);
|
|
3105
3170
|
return ExitCode.NOT_AUTHENTICATED;
|
|
3106
3171
|
}
|
|
3107
3172
|
if (error instanceof RequestFailure) {
|
|
3108
|
-
writeFailure(error.message, input.isJSON, error.errors, error.requestId, error.status);
|
|
3173
|
+
writeFailure(toStatusCode(error.status), error.message, input.isJSON, error.errors, error.requestId, error.status);
|
|
3109
3174
|
return error.status === 401 ? ExitCode.NOT_AUTHENTICATED : ExitCode.ERROR;
|
|
3110
3175
|
}
|
|
3111
3176
|
throw error;
|
|
@@ -3120,7 +3185,7 @@ function toWritten(download, input) {
|
|
|
3120
3185
|
const path = typeof asked === "string" ? asked : download.fileName ?? "-";
|
|
3121
3186
|
if (path === "-") {
|
|
3122
3187
|
if (process.stdout.isTTY) {
|
|
3123
|
-
writeFailure("this answer is a file, so name where to write it with --output, or send it on with a pipe", input.isJSON);
|
|
3188
|
+
writeFailure("output_required", "this answer is a file, so name where to write it with --output, or send it on with a pipe", input.isJSON);
|
|
3124
3189
|
return ExitCode.USAGE;
|
|
3125
3190
|
}
|
|
3126
3191
|
process.stdout.write(download.bytes);
|
|
@@ -5921,7 +5986,8 @@ function toRejectedFlag(command, flags) {
|
|
|
5921
5986
|
/** toCli builds the parser from the registry, which is what every surface reads. */
|
|
5922
5987
|
function toCli(entries = commands) {
|
|
5923
5988
|
const program = new Command();
|
|
5924
|
-
program.name("hardfin").description("Call the Hardfin API from a terminal or an agent").version(version$1, "-v, --version").
|
|
5989
|
+
program.name("hardfin").description("Call the Hardfin API from a terminal or an agent").version(version$1, "-v, --version").enablePositionalOptions();
|
|
5990
|
+
toQuietParser(program);
|
|
5925
5991
|
for (const flag of GLOBAL_FLAGS) program.option(`--${flag.name} <${flag.valueName}>`, flag.description);
|
|
5926
5992
|
for (const command of entries) program.addCommand(toProgram(program, command), { hidden: command.hidden });
|
|
5927
5993
|
return program;
|
|
@@ -5929,6 +5995,7 @@ function toCli(entries = commands) {
|
|
|
5929
5995
|
/** toProgram wires one registry command into the parser. */
|
|
5930
5996
|
function toProgram(root, command) {
|
|
5931
5997
|
const program = new Command(command.name).summary(command.summary).description(command.description ?? command.summary);
|
|
5998
|
+
toQuietParser(program);
|
|
5932
5999
|
for (const argument of command.arguments) {
|
|
5933
6000
|
const name = argument.variadic ? `${argument.name}...` : argument.name;
|
|
5934
6001
|
program.argument(argument.required ? `<${name}>` : `[${name}]`, argument.description);
|
|
@@ -5952,11 +6019,41 @@ function toProgram(root, command) {
|
|
|
5952
6019
|
});
|
|
5953
6020
|
return program;
|
|
5954
6021
|
}
|
|
6022
|
+
/** toQuietParser has the parser hand back its mistakes, so they are answered like any other failure. */
|
|
6023
|
+
function toQuietParser(program) {
|
|
6024
|
+
program.exitOverride().configureOutput({ outputError: () => void 0 });
|
|
6025
|
+
}
|
|
6026
|
+
/** The parser's codes for a run that only showed help or the version, which is not a failure. */
|
|
6027
|
+
const SHOWN = /* @__PURE__ */ new Set([
|
|
6028
|
+
"commander.helpDisplayed",
|
|
6029
|
+
"commander.help",
|
|
6030
|
+
"commander.version"
|
|
6031
|
+
]);
|
|
6032
|
+
/** toParseExitCode answers a mistake the parser caught before any command ran. */
|
|
6033
|
+
function toParseExitCode(error, args) {
|
|
6034
|
+
if (!(error instanceof CommanderError)) return;
|
|
6035
|
+
if (SHOWN.has(error.code)) return error.exitCode;
|
|
6036
|
+
const isJSON = args.includes("--json") || !process.stdout.isTTY;
|
|
6037
|
+
writeFailure(toParseCode(error.code), error.message.replace(/^error: /, ""), isJSON);
|
|
6038
|
+
if (!isJSON) process.stderr.write(" Run the command with --help to see what it takes\n");
|
|
6039
|
+
return ExitCode.USAGE;
|
|
6040
|
+
}
|
|
6041
|
+
function toParseCode(code) {
|
|
6042
|
+
switch (code) {
|
|
6043
|
+
case "commander.unknownCommand": return "unknown_command";
|
|
6044
|
+
case "commander.unknownOption":
|
|
6045
|
+
case "commander.optionMissingArgument":
|
|
6046
|
+
case "commander.missingMandatoryOptionValue":
|
|
6047
|
+
case "commander.conflictingOption":
|
|
6048
|
+
case "commander.invalidArgument": return "invalid_flag";
|
|
6049
|
+
default: return "invalid_arguments";
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
5955
6052
|
async function toExitCode(root, command, args, flags) {
|
|
5956
6053
|
const isJSON = isJSONOutput(flags);
|
|
5957
6054
|
const rejected = toRejectedFlag(command, flags);
|
|
5958
6055
|
if (rejected) {
|
|
5959
|
-
writeFailure(rejected, isJSON);
|
|
6056
|
+
writeFailure("invalid_flag", rejected, isJSON);
|
|
5960
6057
|
return ExitCode.USAGE;
|
|
5961
6058
|
}
|
|
5962
6059
|
let resolved;
|
|
@@ -5977,7 +6074,7 @@ async function toExitCode(root, command, args, flags) {
|
|
|
5977
6074
|
process.stderr.write("\n");
|
|
5978
6075
|
return ExitCode.INTERRUPTED;
|
|
5979
6076
|
}
|
|
5980
|
-
writeFailure(error instanceof Error ? error.message : String(error), isJSON);
|
|
6077
|
+
writeFailure(toErrorCode(error), error instanceof Error ? error.message : String(error), isJSON);
|
|
5981
6078
|
await toReported(error, isJSON, resolved);
|
|
5982
6079
|
return error instanceof ConfigFailure ? ExitCode.USAGE : ExitCode.ERROR;
|
|
5983
6080
|
}
|
|
@@ -6002,7 +6099,7 @@ async function toReported(error, isJSON, resolved, level = "error") {
|
|
|
6002
6099
|
if (id && !isJSON) process.stderr.write(`This looks like a problem in hardfin itself, and it has been reported to the Hardfin team. Reference: ${id}\n`);
|
|
6003
6100
|
}
|
|
6004
6101
|
//#endregion
|
|
6005
|
-
export { toCli, toReported, wasReportAttempted };
|
|
6102
|
+
export { toCli, toParseExitCode, toReported, wasReportAttempted };
|
|
6006
6103
|
|
|
6007
|
-
//# sourceMappingURL=program-
|
|
6008
|
-
//# debugId=
|
|
6104
|
+
//# sourceMappingURL=program-BZW_50HP.js.map
|
|
6105
|
+
//# debugId=5c189832-33ce-5032-b0e0-fc3a33cf5b1d
|