@hardfin/cli 0.0.2-dev.10 → 0.0.2-dev.12

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.
Files changed (3) hide show
  1. package/README.md +69 -3
  2. package/dist/cli.js +1794 -102
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2,12 +2,13 @@
2
2
  import { createRequire } from "node:module";
3
3
  import { Command, Option } from "commander";
4
4
  import { z } from "zod";
5
- import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
6
- import { dirname, join, resolve } from "node:path";
5
+ import { chmodSync, closeSync, existsSync, mkdirSync, openAsBlob, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
6
+ import { basename, dirname, join, resolve } from "node:path";
7
7
  import { arch, cpus, homedir, release, totalmem, type, version } from "node:os";
8
- import { spawnSync } from "node:child_process";
8
+ import { spawn, spawnSync } from "node:child_process";
9
9
  import { createServer } from "node:http";
10
10
  import { createHash, randomBytes } from "node:crypto";
11
+ import { createInterface } from "node:readline";
11
12
  //#region src/command/registry.ts
12
13
  /** ExitCode is what the process returns, and what an agent branches on. */
13
14
  const ExitCode = {
@@ -197,24 +198,34 @@ function toGuide(commands, version) {
197
198
  "## Commands",
198
199
  ""
199
200
  ];
200
- for (const command of commands) {
201
- lines.push(`### \`hardfin ${command.name}\``, "", command.description ?? command.summary, "");
202
- if (command.arguments.length > 0) {
203
- lines.push("| Argument | Required | Holds |", "| --- | --- | --- |");
204
- for (const argument of command.arguments) lines.push(`| \`${argument.name}\` | ${argument.required ? "yes" : "no"} | ${argument.description} |`);
205
- lines.push("");
206
- }
207
- if (command.flags.length > 0) {
208
- lines.push("| Flag | Takes | Does |", "| --- | --- | --- |");
209
- for (const flag of command.flags) {
210
- const name = flag.short ? `-${flag.short}, --${flag.name}` : `--${flag.name}`;
211
- lines.push(`| \`${name}\` | ${flag.valueName ?? "nothing"} | ${flag.description} |`);
212
- }
213
- lines.push("");
201
+ for (const command of commands.filter((command) => !command.hidden)) lines.push(...toCommandLines(command, []));
202
+ return lines.join("\n");
203
+ }
204
+ /** toCommandLines describes one command and everything nested under it. */
205
+ function toCommandLines(command, parents) {
206
+ const path = [...parents, command.name];
207
+ const lines = [
208
+ `### \`hardfin ${path.join(" ")}\``,
209
+ "",
210
+ command.description ?? command.summary,
211
+ ""
212
+ ];
213
+ if (command.arguments.length > 0) {
214
+ lines.push("| Argument | Required | Holds |", "| --- | --- | --- |");
215
+ for (const argument of command.arguments) lines.push(`| \`${argument.name}\` | ${argument.required ? "yes" : "no"} | ${argument.description} |`);
216
+ lines.push("");
217
+ }
218
+ if (command.flags.length > 0) {
219
+ lines.push("| Flag | Takes | Does |", "| --- | --- | --- |");
220
+ for (const flag of command.flags) {
221
+ const name = flag.short ? `-${flag.short}, --${flag.name}` : `--${flag.name}`;
222
+ lines.push(`| \`${name}\` | ${flag.valueName ?? "nothing"} | ${flag.description} |`);
214
223
  }
215
- for (const example of command.examples) lines.push(`${example.description}:`, "", "```sh", example.command, "```", "");
224
+ lines.push("");
216
225
  }
217
- return lines.join("\n");
226
+ for (const example of command.examples) lines.push(`${example.description}:`, "", "```sh", example.command, "```", "");
227
+ for (const subcommand of command.subcommands ?? []) lines.push(...toCommandLines(subcommand, path));
228
+ return lines;
218
229
  }
219
230
  async function runAgentGuide(input) {
220
231
  if (input.flags["json"] === true) {
@@ -603,11 +614,11 @@ async function request(options) {
603
614
  "X-API-Version": API_VERSION,
604
615
  Accept: "application/json"
605
616
  };
606
- if (options.body !== void 0) headers["Content-Type"] = "application/json";
617
+ if (options.body !== void 0 && options.form === void 0) headers["Content-Type"] = "application/json";
607
618
  const response = await fetch(url, {
608
619
  method: options.method,
609
620
  headers,
610
- body: options.body === void 0 ? void 0 : JSON.stringify(options.body)
621
+ body: options.form ?? (options.body === void 0 ? void 0 : JSON.stringify(options.body))
611
622
  });
612
623
  const envelope = toEnvelope(await response.text());
613
624
  if (!response.ok && envelope === void 0) throw new RequestFailure(response.status, [{
@@ -760,6 +771,132 @@ function toBody$1(source) {
760
771
  }
761
772
  }
762
773
  //#endregion
774
+ //#region src/command/completion.ts
775
+ const SHELLS = [
776
+ "bash",
777
+ "zsh",
778
+ "fish",
779
+ "powershell"
780
+ ];
781
+ const completionCommand = defineCommand({
782
+ name: "completion",
783
+ summary: "Print the shell script that completes hardfin commands",
784
+ description: "Writes a script for your shell. The script asks this CLI what may follow what you have typed, so completions never fall behind the commands.",
785
+ arguments: [{
786
+ name: "shell",
787
+ description: `The shell to write for: ${SHELLS.join(", ")}`,
788
+ required: true
789
+ }],
790
+ flags: [],
791
+ examples: [
792
+ {
793
+ description: "Complete in this shell, now",
794
+ command: "source <(hardfin completion zsh)"
795
+ },
796
+ {
797
+ description: "Complete in every new shell",
798
+ command: "hardfin completion zsh > ~/.hardfin-completion.zsh"
799
+ },
800
+ {
801
+ description: "Complete in bash",
802
+ command: "source <(hardfin completion bash)"
803
+ }
804
+ ],
805
+ run: runCompletion
806
+ });
807
+ /** The hidden command a completion script asks, which keeps one implementation for every shell. */
808
+ const completeCommand = defineCommand({
809
+ name: "__complete",
810
+ summary: "Answer what may follow the words typed so far",
811
+ hidden: true,
812
+ arguments: [{
813
+ name: "words",
814
+ description: "The words typed so far",
815
+ required: false,
816
+ variadic: true
817
+ }],
818
+ flags: [{
819
+ name: "json",
820
+ description: "Accepted for consistency, and ignored",
821
+ schema: z.boolean()
822
+ }],
823
+ examples: [],
824
+ run: async (input) => {
825
+ writeData(toCandidates(input.commands, input.args).join("\n"));
826
+ return ExitCode.OK;
827
+ }
828
+ });
829
+ /**
830
+ * toCandidates answers what may follow the words typed so far. A word starting with a dash
831
+ * asks for the current command's flags, and anything else asks for its subcommands.
832
+ */
833
+ function toCandidates(commands, words) {
834
+ const partial = words[words.length - 1] ?? "";
835
+ const walked = toWalked(commands, words.slice(0, -1));
836
+ if (partial.startsWith("-")) return toFlagNames(walked.command).filter((name) => name.startsWith(partial));
837
+ if (walked.isUnknown) return [];
838
+ return (walked.command?.subcommands ?? walked.remaining).map((command) => command.name).filter((name) => !name.startsWith("__")).filter((name) => name.startsWith(partial));
839
+ }
840
+ function toWalked(commands, words) {
841
+ let remaining = commands;
842
+ let command;
843
+ for (const word of words) {
844
+ if (word.startsWith("-") || command?.arguments.length) continue;
845
+ const found = remaining.find((entry) => entry.name === word);
846
+ if (!found) return {
847
+ command,
848
+ remaining,
849
+ isUnknown: true
850
+ };
851
+ command = found;
852
+ remaining = found.subcommands ?? [];
853
+ }
854
+ return {
855
+ command,
856
+ remaining,
857
+ isUnknown: false
858
+ };
859
+ }
860
+ function toFlagNames(command) {
861
+ return [...(command?.flags ?? []).map((flag) => `--${flag.name}`), "--help"];
862
+ }
863
+ async function runCompletion(input) {
864
+ const shell = String(input.args[0] ?? "");
865
+ if (!SHELLS.includes(shell)) {
866
+ writeFailure(`${shell || "no shell"} is not one this CLI writes for. Choose ${SHELLS.join(", ")}`, input.isJSON);
867
+ return ExitCode.USAGE;
868
+ }
869
+ writeData(toScript(shell));
870
+ return ExitCode.OK;
871
+ }
872
+ /** toScript writes a shell's completion, each one asking __complete for the candidates. */
873
+ function toScript(shell) {
874
+ if (shell === "bash") return `# hardfin completion for bash
875
+ _hardfin_complete() {
876
+ local words
877
+ words=("\${COMP_WORDS[@]:1}")
878
+ COMPREPLY=($(hardfin __complete -- "\${words[@]}" 2>/dev/null))
879
+ }
880
+ complete -F _hardfin_complete hardfin`;
881
+ if (shell === "zsh") return `# hardfin completion for zsh
882
+ _hardfin_complete() {
883
+ local -a candidates
884
+ candidates=(\${(f)"$(hardfin __complete -- \${words[2,-1]} 2>/dev/null)"})
885
+ compadd -a candidates
886
+ }
887
+ compdef _hardfin_complete hardfin`;
888
+ if (shell === "fish") return `# hardfin completion for fish
889
+ complete -c hardfin -f -a "(hardfin __complete -- (commandline -opc)[2..-1] 2>/dev/null)"`;
890
+ return `# hardfin completion for PowerShell
891
+ Register-ArgumentCompleter -Native -CommandName hardfin -ScriptBlock {
892
+ param($wordToComplete, $commandAst, $cursorPosition)
893
+ $words = $commandAst.CommandElements | Select-Object -Skip 1 | ForEach-Object { $_.ToString() }
894
+ hardfin __complete -- @words 2>$null | ForEach-Object {
895
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
896
+ }
897
+ }`;
898
+ }
899
+ //#endregion
763
900
  //#region src/command/config.ts
764
901
  const configCommand = defineCommand({
765
902
  name: "config",
@@ -1310,11 +1447,195 @@ async function runLogout(input) {
1310
1447
  return ExitCode.OK;
1311
1448
  }
1312
1449
  //#endregion
1450
+ //#region src/mcp/server.ts
1451
+ const PROTOCOL_VERSION = "2025-06-18";
1452
+ const GUIDE_URI = "hardfin://guide";
1453
+ const COMMANDS_URI = "hardfin://commands";
1454
+ /**
1455
+ * One tool, because every tool a server lists sits in the agent's context for the whole
1456
+ * session. The commands themselves are resources, which cost nothing until one is read.
1457
+ */
1458
+ const TOOL = {
1459
+ name: "hardfin",
1460
+ description: "Run a Hardfin CLI command against the Hardfin API. Pass the arguments as a list, such as [\"asset\", \"list\", \"--limit\", \"5\"]. Run [\"--help\"] for the commands, or read the hardfin://guide resource.",
1461
+ inputSchema: {
1462
+ type: "object",
1463
+ properties: { args: {
1464
+ type: "array",
1465
+ items: { type: "string" },
1466
+ description: "The arguments to hardfin, without the program name"
1467
+ } },
1468
+ required: ["args"]
1469
+ }
1470
+ };
1471
+ /** toResponse answers one request, and answers nothing to a notification. */
1472
+ async function toResponse(request, commands, run) {
1473
+ const answer = (result) => ({
1474
+ jsonrpc: "2.0",
1475
+ id: request.id ?? null,
1476
+ result
1477
+ });
1478
+ switch (request.method) {
1479
+ case "initialize": return answer({
1480
+ protocolVersion: toProtocolVersion(request.params),
1481
+ capabilities: {
1482
+ tools: {},
1483
+ resources: {}
1484
+ },
1485
+ serverInfo: {
1486
+ name: "hardfin",
1487
+ version: version$1
1488
+ }
1489
+ });
1490
+ case "tools/list": return answer({ tools: [TOOL] });
1491
+ case "resources/list": return answer({ resources: [{
1492
+ uri: GUIDE_URI,
1493
+ name: "Hardfin CLI guide",
1494
+ description: "Every command, its flags, and the exit codes",
1495
+ mimeType: "text/markdown"
1496
+ }, {
1497
+ uri: COMMANDS_URI,
1498
+ name: "Hardfin CLI commands",
1499
+ description: "The command tree as JSON",
1500
+ mimeType: "application/json"
1501
+ }] });
1502
+ case "resources/read": return answer(toResource(String(request.params?.["uri"] ?? ""), commands));
1503
+ case "tools/call": return answer(await toToolResult(request.params, run));
1504
+ case "ping": return answer({});
1505
+ default:
1506
+ if (request.id === void 0 || request.id === null) return;
1507
+ return {
1508
+ jsonrpc: "2.0",
1509
+ id: request.id,
1510
+ error: {
1511
+ code: -32601,
1512
+ message: `${request.method} is not a method this server offers`
1513
+ }
1514
+ };
1515
+ }
1516
+ }
1517
+ function toProtocolVersion(params) {
1518
+ const asked = params?.["protocolVersion"];
1519
+ return typeof asked === "string" ? asked : PROTOCOL_VERSION;
1520
+ }
1521
+ function toResource(uri, commands) {
1522
+ if (uri === GUIDE_URI) return { contents: [{
1523
+ uri,
1524
+ mimeType: "text/markdown",
1525
+ text: toGuide(commands, version$1)
1526
+ }] };
1527
+ if (uri === COMMANDS_URI) return { contents: [{
1528
+ uri,
1529
+ mimeType: "application/json",
1530
+ text: JSON.stringify(toTree(commands), null, 2)
1531
+ }] };
1532
+ return {
1533
+ contents: [],
1534
+ isError: true
1535
+ };
1536
+ }
1537
+ /** toTree names every command and what it takes, without the schemas a tool list would carry. */
1538
+ function toTree(commands) {
1539
+ return commands.map((command) => ({
1540
+ name: command.name,
1541
+ summary: command.summary,
1542
+ arguments: command.arguments.map((argument) => argument.name),
1543
+ flags: command.flags.map((flag) => flag.valueName ? `--${flag.name} <${flag.valueName}>` : `--${flag.name}`),
1544
+ subcommands: command.subcommands ? toTree(command.subcommands) : void 0
1545
+ }));
1546
+ }
1547
+ async function toToolResult(params, run) {
1548
+ const args = (params?.["arguments"])?.args;
1549
+ if (!Array.isArray(args) || args.some((entry) => typeof entry !== "string")) return {
1550
+ content: [{
1551
+ type: "text",
1552
+ text: "args must be a list of strings, such as [\"asset\", \"list\"]"
1553
+ }],
1554
+ isError: true
1555
+ };
1556
+ const outcome = await run(args);
1557
+ return {
1558
+ content: [{
1559
+ type: "text",
1560
+ text: [outcome.stdout, outcome.stderr].filter((part) => part.trim() !== "").join("\n") || `hardfin exited ${outcome.code}`
1561
+ }],
1562
+ isError: outcome.code !== 0
1563
+ };
1564
+ }
1565
+ /** toCliRunner runs the CLI itself, so a tool call parses exactly as a terminal would. */
1566
+ function toCliRunner() {
1567
+ return (args) => new Promise((resolve) => {
1568
+ const child = spawn(process.execPath, [process.argv[1] ?? "", ...args], { env: {
1569
+ ...process.env,
1570
+ HARDFIN_NO_BROWSER: "1"
1571
+ } });
1572
+ let stdout = "";
1573
+ let stderr = "";
1574
+ child.stdout.on("data", (chunk) => {
1575
+ stdout += chunk.toString();
1576
+ });
1577
+ child.stderr.on("data", (chunk) => {
1578
+ stderr += chunk.toString();
1579
+ });
1580
+ child.on("close", (code) => resolve({
1581
+ stdout,
1582
+ stderr,
1583
+ code: code ?? 1
1584
+ }));
1585
+ });
1586
+ }
1587
+ /** serve answers requests on stdin until the client closes it. */
1588
+ async function serve(commands, run = toCliRunner()) {
1589
+ const lines = createInterface({ input: process.stdin });
1590
+ for await (const line of lines) {
1591
+ if (line.trim() === "") continue;
1592
+ let response;
1593
+ try {
1594
+ response = await toResponse(JSON.parse(line), commands, run);
1595
+ } catch (error) {
1596
+ response = {
1597
+ jsonrpc: "2.0",
1598
+ id: null,
1599
+ error: {
1600
+ code: -32700,
1601
+ message: error instanceof Error ? error.message : String(error)
1602
+ }
1603
+ };
1604
+ }
1605
+ if (response) process.stdout.write(`${JSON.stringify(response)}\n`);
1606
+ }
1607
+ }
1608
+ //#endregion
1609
+ //#region src/command/mcp.ts
1610
+ const mcpCommand = defineCommand({
1611
+ name: "mcp",
1612
+ summary: "Serve this CLI to an agent over the Model Context Protocol",
1613
+ description: "Speaks the Model Context Protocol on standard input and output. It offers one tool, because every tool an agent is told about occupies its context for the whole session, and serves the commands as resources the agent reads only when it needs them.",
1614
+ arguments: [],
1615
+ flags: [{
1616
+ name: "json",
1617
+ description: "Accepted for consistency, and ignored, because the protocol decides the output",
1618
+ schema: z.boolean()
1619
+ }],
1620
+ examples: [{
1621
+ description: "Register with an agent",
1622
+ command: "hardfin mcp"
1623
+ }, {
1624
+ description: "Add it to Claude Code",
1625
+ command: "claude mcp add hardfin -- hardfin mcp"
1626
+ }],
1627
+ run: runMcp
1628
+ });
1629
+ async function runMcp(input) {
1630
+ await serve(input.commands);
1631
+ return ExitCode.OK;
1632
+ }
1633
+ //#endregion
1313
1634
  //#region src/command/operation.ts
1314
- const INPUT_FLAG = {
1315
- name: "input",
1316
- description: "A file holding the JSON request body, or - for stdin",
1317
- valueName: "file",
1635
+ const FILE_FLAG = {
1636
+ name: "file",
1637
+ description: "The file to upload",
1638
+ valueName: "path",
1318
1639
  schema: z.string()
1319
1640
  };
1320
1641
  const JSON_FLAG = {
@@ -1324,15 +1645,22 @@ const JSON_FLAG = {
1324
1645
  };
1325
1646
  /** defineOperation turns one endpoint into the command that calls it. */
1326
1647
  function defineOperation(operation) {
1327
- const flags = [...operation.queryFlags, JSON_FLAG];
1328
- if (operation.takesBody) flags.splice(flags.length - 1, 0, INPUT_FLAG);
1648
+ const flags = [
1649
+ ...operation.queryFlags,
1650
+ ...operation.bodyFlags,
1651
+ ...operation.upload ? [...operation.upload.fields, FILE_FLAG] : [],
1652
+ JSON_FLAG
1653
+ ];
1329
1654
  return {
1330
1655
  name: operation.name,
1331
1656
  summary: operation.summary,
1332
1657
  description: operation.description ?? operation.summary,
1333
1658
  arguments: operation.pathParameters,
1334
1659
  flags,
1335
- examples: [],
1660
+ examples: operation.example ? [{
1661
+ description: operation.summary,
1662
+ command: operation.example
1663
+ }] : [],
1336
1664
  run: (input) => runOperation(operation, input)
1337
1665
  };
1338
1666
  }
@@ -1342,13 +1670,24 @@ async function runOperation(operation, input) {
1342
1670
  writeFailure(`this command takes ${operation.pathParameters.length} argument(s)`, input.isJSON);
1343
1671
  return ExitCode.USAGE;
1344
1672
  }
1345
- let body;
1346
- if (typeof input.flags["input"] === "string") {
1347
- body = toBody(input.flags["input"]);
1348
- if (body === void 0) {
1349
- writeFailure(`${input.flags["input"]} does not hold JSON`, input.isJSON);
1673
+ const missing = operation.bodyFlags.concat(operation.upload?.fields ?? []).filter((flag) => flag.required && input.flags[toOptionKey(flag.name)] === void 0);
1674
+ if (missing.length > 0) {
1675
+ writeFailure(`this command needs ${missing.map((flag) => `--${flag.name}`).join(", ")}`, input.isJSON);
1676
+ return ExitCode.USAGE;
1677
+ }
1678
+ const body = toBody(operation, input.flags);
1679
+ if (body instanceof Error) {
1680
+ writeFailure(body.message, input.isJSON);
1681
+ return ExitCode.USAGE;
1682
+ }
1683
+ let form;
1684
+ if (operation.upload) {
1685
+ const built = await toForm(operation.upload, input.flags);
1686
+ if (built instanceof Error) {
1687
+ writeFailure(built.message, input.isJSON);
1350
1688
  return ExitCode.USAGE;
1351
1689
  }
1690
+ form = built;
1352
1691
  }
1353
1692
  try {
1354
1693
  writeData((await request({
@@ -1357,7 +1696,8 @@ async function runOperation(operation, input) {
1357
1696
  method: operation.method,
1358
1697
  path,
1359
1698
  query: toQuery(operation, input.flags),
1360
- body
1699
+ body,
1700
+ form
1361
1701
  })).data);
1362
1702
  return ExitCode.OK;
1363
1703
  } catch (error) {
@@ -1394,13 +1734,65 @@ function toQuery(operation, flags) {
1394
1734
  function toOptionKey(name) {
1395
1735
  return name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
1396
1736
  }
1397
- function toBody(source) {
1398
- const text = source === "-" ? readFileSync(0, "utf8") : readFileSync(source, "utf8");
1737
+ /** toForm builds the file part and its fields, which an upload endpoint takes. */
1738
+ async function toForm(upload, flags) {
1739
+ const path = flags["file"];
1740
+ if (typeof path !== "string") return /* @__PURE__ */ new Error("this command needs --file, the file to upload");
1741
+ const form = new FormData();
1399
1742
  try {
1400
- return JSON.parse(text);
1743
+ form.append(upload.filePart, await openAsBlob(path), basename(path));
1401
1744
  } catch {
1402
- return;
1745
+ return /* @__PURE__ */ new Error(`${path} cannot be read`);
1746
+ }
1747
+ for (const field of upload.fields) {
1748
+ const value = flags[toOptionKey(field.name)];
1749
+ if (value !== void 0) form.append(field.jsonPath[0] ?? field.name, String(value));
1750
+ }
1751
+ return form;
1752
+ }
1753
+ /** toBody builds the request body from the flags, one field at a time. */
1754
+ function toBody(operation, flags) {
1755
+ const body = {};
1756
+ let hasField = false;
1757
+ for (const flag of operation.bodyFlags) {
1758
+ const value = flags[toOptionKey(flag.name)];
1759
+ if (value === void 0) continue;
1760
+ if (flag.element) {
1761
+ const elements = toElements(flag, Array.isArray(value) ? value.map(String) : [String(value)]);
1762
+ if (elements instanceof Error) return elements;
1763
+ set(body, flag.jsonPath, elements);
1764
+ hasField = true;
1765
+ continue;
1766
+ }
1767
+ set(body, flag.jsonPath, value);
1768
+ hasField = true;
1769
+ }
1770
+ return hasField ? body : void 0;
1771
+ }
1772
+ /** toElements reads the key=value pairs a repeated flag carries for one array element. */
1773
+ function toElements(flag, values) {
1774
+ const elements = [];
1775
+ for (const value of values) {
1776
+ const element = {};
1777
+ for (const pair of value.split(",")) {
1778
+ const split = pair.indexOf("=");
1779
+ if (split < 1) return /* @__PURE__ */ new Error(`--${flag.name} takes ${flag.element?.join("=, ")}=, such as --${flag.name} ${flag.element?.[0]}=value`);
1780
+ const key = pair.slice(0, split);
1781
+ if (flag.element && !flag.element.includes(key)) return /* @__PURE__ */ new Error(`--${flag.name} has no field ${key}. It takes ${flag.element.join(", ")}`);
1782
+ element[key] = pair.slice(split + 1);
1783
+ }
1784
+ elements.push(element);
1785
+ }
1786
+ return elements;
1787
+ }
1788
+ /** set writes a value at its path, building the objects a nested field needs. */
1789
+ function set(body, path, value) {
1790
+ let holder = body;
1791
+ for (const name of path.slice(0, -1)) {
1792
+ holder[name] = holder[name] ?? {};
1793
+ holder = holder[name];
1403
1794
  }
1795
+ holder[path[path.length - 1] ?? ""] = value;
1404
1796
  }
1405
1797
  //#endregion
1406
1798
  //#region src/command/surface.generated.ts
@@ -1415,6 +1807,7 @@ const surfaceCommands = [
1415
1807
  defineOperation({
1416
1808
  name: "list",
1417
1809
  summary: "Get asset listing",
1810
+ example: "hardfin asset list --limit 10",
1418
1811
  method: "GET",
1419
1812
  path: "/asset",
1420
1813
  pathParameters: [],
@@ -1598,16 +1991,170 @@ const surfaceCommands = [
1598
1991
  ])
1599
1992
  }
1600
1993
  ],
1601
- takesBody: false
1994
+ bodyFlags: []
1602
1995
  }),
1603
1996
  defineOperation({
1604
1997
  name: "create",
1605
1998
  summary: "Create asset",
1999
+ example: "hardfin asset create --item-id <value> --serial <value>",
1606
2000
  method: "POST",
1607
2001
  path: "/asset",
1608
2002
  pathParameters: [],
1609
2003
  queryFlags: [],
1610
- takesBody: true
2004
+ bodyFlags: [
2005
+ {
2006
+ name: "allocated-indirect",
2007
+ jsonPath: ["allocatedIndirect"],
2008
+ description: "One unit's share of overhead, a cost component",
2009
+ valueName: "value",
2010
+ schema: z.string()
2011
+ },
2012
+ {
2013
+ name: "bill-of-materials",
2014
+ jsonPath: ["billOfMaterials"],
2015
+ description: "The parts cost of one unit, a cost component",
2016
+ valueName: "value",
2017
+ schema: z.string()
2018
+ },
2019
+ {
2020
+ name: "depreciation-model",
2021
+ jsonPath: ["depreciationModel"],
2022
+ description: "The method one unit is depreciated by, or null to clear it",
2023
+ valueName: "value",
2024
+ schema: z.enum([
2025
+ "DOUBLE_DECLINING",
2026
+ "STRAIGHT_LINE",
2027
+ "SUM_YEAR",
2028
+ "UNIT_OF_PRODUCTION"
2029
+ ])
2030
+ },
2031
+ {
2032
+ name: "description",
2033
+ jsonPath: ["description"],
2034
+ description: "A free-form description of the asset",
2035
+ valueName: "value",
2036
+ schema: z.string()
2037
+ },
2038
+ {
2039
+ name: "direct-labor",
2040
+ jsonPath: ["directLabor"],
2041
+ description: "The labor cost to build one unit, a cost component",
2042
+ valueName: "value",
2043
+ schema: z.string()
2044
+ },
2045
+ {
2046
+ name: "freight-inbound",
2047
+ jsonPath: ["freightInbound"],
2048
+ description: "The shipping cost to receive one unit, a cost component",
2049
+ valueName: "value",
2050
+ schema: z.string()
2051
+ },
2052
+ {
2053
+ name: "freight-outbound",
2054
+ jsonPath: ["freightOutbound"],
2055
+ description: "The shipping cost to deploy one unit, a deployment cost component",
2056
+ valueName: "value",
2057
+ schema: z.string()
2058
+ },
2059
+ {
2060
+ name: "functional-status",
2061
+ jsonPath: ["functionalStatus"],
2062
+ description: "The asset's starting functional status, FUNCTIONAL when absent, which cannot be SCRAPPED",
2063
+ valueName: "value",
2064
+ schema: z.enum([
2065
+ "FUNCTIONAL",
2066
+ "NEEDS_REVIEW",
2067
+ "NON-FUNCTIONAL",
2068
+ "SCRAPPED"
2069
+ ])
2070
+ },
2071
+ {
2072
+ name: "in-inventory-date",
2073
+ jsonPath: ["inInventoryDate"],
2074
+ description: "The day the asset entered inventory, which cannot be in the future",
2075
+ valueName: "value",
2076
+ schema: z.string()
2077
+ },
2078
+ {
2079
+ name: "in-service-date",
2080
+ jsonPath: ["inServiceDate"],
2081
+ description: "The day the asset was put into service, which Hardfin sets itself when absent",
2082
+ valueName: "value",
2083
+ schema: z.string()
2084
+ },
2085
+ {
2086
+ name: "installation",
2087
+ jsonPath: ["installation"],
2088
+ description: "The cost to install one unit, a deployment cost component",
2089
+ valueName: "value",
2090
+ schema: z.string()
2091
+ },
2092
+ {
2093
+ name: "interest",
2094
+ jsonPath: ["interest"],
2095
+ description: "The financing cost of one unit, a cost component",
2096
+ valueName: "value",
2097
+ schema: z.string()
2098
+ },
2099
+ {
2100
+ name: "item-id",
2101
+ jsonPath: ["itemId"],
2102
+ description: "The ID of the catalog item the asset is a unit of",
2103
+ valueName: "value",
2104
+ required: true,
2105
+ schema: z.string()
2106
+ },
2107
+ {
2108
+ name: "location-id",
2109
+ jsonPath: ["locationId"],
2110
+ description: "The ID of the location the asset enters inventory at",
2111
+ valueName: "value",
2112
+ schema: z.string()
2113
+ },
2114
+ {
2115
+ name: "salvage-value",
2116
+ jsonPath: ["salvageValue"],
2117
+ description: "The value one unit keeps at the end of its useful life, or null to clear it",
2118
+ valueName: "value",
2119
+ schema: z.string()
2120
+ },
2121
+ {
2122
+ name: "serial",
2123
+ jsonPath: ["serial"],
2124
+ description: "The asset's serial number, unique within its item",
2125
+ valueName: "value",
2126
+ required: true,
2127
+ schema: z.string()
2128
+ },
2129
+ {
2130
+ name: "simple-cost-basis",
2131
+ jsonPath: ["simpleCostBasis"],
2132
+ description: "A single cost for one unit, which cannot be sent together with the cost components",
2133
+ valueName: "value",
2134
+ schema: z.string()
2135
+ },
2136
+ {
2137
+ name: "tariffs",
2138
+ jsonPath: ["tariffs"],
2139
+ description: "The import duty paid on one unit, a cost component",
2140
+ valueName: "value",
2141
+ schema: z.string()
2142
+ },
2143
+ {
2144
+ name: "tax",
2145
+ jsonPath: ["tax"],
2146
+ description: "The tax paid on one unit, a cost component",
2147
+ valueName: "value",
2148
+ schema: z.string()
2149
+ },
2150
+ {
2151
+ name: "useful-life",
2152
+ jsonPath: ["usefulLife"],
2153
+ description: "The number of months one unit is depreciated over, or null to clear it",
2154
+ valueName: "number",
2155
+ schema: z.coerce.number()
2156
+ }
2157
+ ]
1611
2158
  }),
1612
2159
  {
1613
2160
  name: "move",
@@ -1624,11 +2171,28 @@ const surfaceCommands = [
1624
2171
  subcommands: [defineOperation({
1625
2172
  name: "create",
1626
2173
  summary: "Execute asset move",
2174
+ example: "hardfin asset move execute create",
1627
2175
  method: "POST",
1628
2176
  path: "/asset/move/execute",
1629
2177
  pathParameters: [],
1630
2178
  queryFlags: [],
1631
- takesBody: true
2179
+ bodyFlags: [{
2180
+ name: "move",
2181
+ jsonPath: ["moves"],
2182
+ description: "The moves to carry out",
2183
+ valueName: "assetId=,deliverAt=",
2184
+ repeatable: true,
2185
+ element: [
2186
+ "assetId",
2187
+ "deliverAt",
2188
+ "deliverAtTimezone",
2189
+ "destinationId",
2190
+ "originId",
2191
+ "shipAt",
2192
+ "shipAtTimezone"
2193
+ ],
2194
+ schema: z.array(z.string())
2195
+ }]
1632
2196
  })]
1633
2197
  }, {
1634
2198
  name: "plan",
@@ -1639,17 +2203,32 @@ const surfaceCommands = [
1639
2203
  subcommands: [defineOperation({
1640
2204
  name: "create",
1641
2205
  summary: "Plan asset move",
2206
+ example: "hardfin asset move plan create",
1642
2207
  method: "POST",
1643
2208
  path: "/asset/move/plan",
1644
2209
  pathParameters: [],
1645
2210
  queryFlags: [],
1646
- takesBody: true
2211
+ bodyFlags: [{
2212
+ name: "move",
2213
+ jsonPath: ["moves"],
2214
+ description: "The moves to plan",
2215
+ valueName: "assetId=,deliverAt=",
2216
+ repeatable: true,
2217
+ element: [
2218
+ "assetId",
2219
+ "deliverAt",
2220
+ "id",
2221
+ "shipAt"
2222
+ ],
2223
+ schema: z.array(z.string())
2224
+ }]
1647
2225
  })]
1648
2226
  }]
1649
2227
  },
1650
2228
  defineOperation({
1651
2229
  name: "get",
1652
2230
  summary: "Get asset",
2231
+ example: "hardfin asset get ast_4f9xk2mq7plr8stz",
1653
2232
  method: "GET",
1654
2233
  path: "/asset/{assetKey}",
1655
2234
  pathParameters: [{
@@ -1658,11 +2237,12 @@ const surfaceCommands = [
1658
2237
  required: true
1659
2238
  }],
1660
2239
  queryFlags: [],
1661
- takesBody: false
2240
+ bodyFlags: []
1662
2241
  }),
1663
2242
  defineOperation({
1664
2243
  name: "update",
1665
2244
  summary: "Patch asset",
2245
+ example: "hardfin asset update ast_4f9xk2mq7plr8stz",
1666
2246
  method: "PATCH",
1667
2247
  path: "/asset/{assetKey}",
1668
2248
  pathParameters: [{
@@ -1671,7 +2251,57 @@ const surfaceCommands = [
1671
2251
  required: true
1672
2252
  }],
1673
2253
  queryFlags: [],
1674
- takesBody: true
2254
+ bodyFlags: [
2255
+ {
2256
+ name: "description",
2257
+ jsonPath: ["description"],
2258
+ description: "The asset's new description, or null to clear it",
2259
+ valueName: "value",
2260
+ schema: z.string()
2261
+ },
2262
+ {
2263
+ name: "functional-status",
2264
+ jsonPath: ["functionalStatus"],
2265
+ description: "The asset's new functional status, which cannot be SCRAPPED because scrapping has its own endpoint",
2266
+ valueName: "value",
2267
+ schema: z.enum([
2268
+ "FUNCTIONAL",
2269
+ "NEEDS_REVIEW",
2270
+ "NON-FUNCTIONAL",
2271
+ "SCRAPPED"
2272
+ ])
2273
+ },
2274
+ {
2275
+ name: "in-inventory-date",
2276
+ jsonPath: ["inInventoryDate"],
2277
+ description: "The day the asset entered inventory, which cannot be in the future",
2278
+ valueName: "value",
2279
+ schema: z.string()
2280
+ },
2281
+ {
2282
+ name: "initial-location-id",
2283
+ jsonPath: ["initialLocationId"],
2284
+ description: "The ID of the location the asset entered inventory at",
2285
+ valueName: "value",
2286
+ schema: z.string()
2287
+ },
2288
+ {
2289
+ name: "metadata",
2290
+ jsonPath: ["metadata"],
2291
+ description: "New values for the asset's custom fields, each naming its field",
2292
+ valueName: "fieldId=,value=",
2293
+ repeatable: true,
2294
+ element: ["fieldId", "value"],
2295
+ schema: z.array(z.string())
2296
+ },
2297
+ {
2298
+ name: "serial",
2299
+ jsonPath: ["serial"],
2300
+ description: "The asset's new serial number, which cannot be empty",
2301
+ valueName: "value",
2302
+ schema: z.string()
2303
+ }
2304
+ ]
1675
2305
  }),
1676
2306
  {
1677
2307
  name: "accounting",
@@ -1682,6 +2312,7 @@ const surfaceCommands = [
1682
2312
  subcommands: [defineOperation({
1683
2313
  name: "update",
1684
2314
  summary: "Update asset accounting",
2315
+ example: "hardfin asset accounting update ast_4f9xk2mq7plr8stz",
1685
2316
  method: "PATCH",
1686
2317
  path: "/asset/{assetKey}/accounting",
1687
2318
  pathParameters: [{
@@ -1690,7 +2321,117 @@ const surfaceCommands = [
1690
2321
  required: true
1691
2322
  }],
1692
2323
  queryFlags: [],
1693
- takesBody: true
2324
+ bodyFlags: [
2325
+ {
2326
+ name: "allocated-indirect",
2327
+ jsonPath: ["allocatedIndirect"],
2328
+ description: "One unit's share of overhead, a cost component",
2329
+ valueName: "value",
2330
+ schema: z.string()
2331
+ },
2332
+ {
2333
+ name: "bill-of-materials",
2334
+ jsonPath: ["billOfMaterials"],
2335
+ description: "The parts cost of one unit, a cost component",
2336
+ valueName: "value",
2337
+ schema: z.string()
2338
+ },
2339
+ {
2340
+ name: "depreciation-model",
2341
+ jsonPath: ["depreciationModel"],
2342
+ description: "The method one unit is depreciated by, or null to clear it",
2343
+ valueName: "value",
2344
+ schema: z.enum([
2345
+ "DOUBLE_DECLINING",
2346
+ "STRAIGHT_LINE",
2347
+ "SUM_YEAR",
2348
+ "UNIT_OF_PRODUCTION"
2349
+ ])
2350
+ },
2351
+ {
2352
+ name: "direct-labor",
2353
+ jsonPath: ["directLabor"],
2354
+ description: "The labor cost to build one unit, a cost component",
2355
+ valueName: "value",
2356
+ schema: z.string()
2357
+ },
2358
+ {
2359
+ name: "freight-inbound",
2360
+ jsonPath: ["freightInbound"],
2361
+ description: "The shipping cost to receive one unit, a cost component",
2362
+ valueName: "value",
2363
+ schema: z.string()
2364
+ },
2365
+ {
2366
+ name: "freight-outbound",
2367
+ jsonPath: ["freightOutbound"],
2368
+ description: "The shipping cost to deploy one unit, a deployment cost component",
2369
+ valueName: "value",
2370
+ schema: z.string()
2371
+ },
2372
+ {
2373
+ name: "in-service-date",
2374
+ jsonPath: ["inServiceDate"],
2375
+ description: "The day the asset was put into service and began depreciating, or null to clear it",
2376
+ valueName: "value",
2377
+ schema: z.string()
2378
+ },
2379
+ {
2380
+ name: "installation",
2381
+ jsonPath: ["installation"],
2382
+ description: "The cost to install one unit, a deployment cost component",
2383
+ valueName: "value",
2384
+ schema: z.string()
2385
+ },
2386
+ {
2387
+ name: "interest",
2388
+ jsonPath: ["interest"],
2389
+ description: "The financing cost of one unit, a cost component",
2390
+ valueName: "value",
2391
+ schema: z.string()
2392
+ },
2393
+ {
2394
+ name: "is-in-service-date-managed-automatically",
2395
+ jsonPath: ["isInServiceDateManagedAutomatically"],
2396
+ description: "Whether Hardfin sets the in-service date itself, which sending an in-service date turns off",
2397
+ schema: z.boolean()
2398
+ },
2399
+ {
2400
+ name: "salvage-value",
2401
+ jsonPath: ["salvageValue"],
2402
+ description: "The value one unit keeps at the end of its useful life, or null to clear it",
2403
+ valueName: "value",
2404
+ schema: z.string()
2405
+ },
2406
+ {
2407
+ name: "simple-cost-basis",
2408
+ jsonPath: ["simpleCostBasis"],
2409
+ description: "A single cost for one unit, which cannot be sent together with the cost components",
2410
+ valueName: "value",
2411
+ schema: z.string()
2412
+ },
2413
+ {
2414
+ name: "tariffs",
2415
+ jsonPath: ["tariffs"],
2416
+ description: "The import duty paid on one unit, a cost component",
2417
+ valueName: "value",
2418
+ schema: z.string()
2419
+ },
2420
+ {
2421
+ name: "tax",
2422
+ jsonPath: ["tax"],
2423
+ description: "The tax paid on one unit, a cost component",
2424
+ valueName: "value",
2425
+ schema: z.string()
2426
+ },
2427
+ {
2428
+ name: "useful-life",
2429
+ jsonPath: ["usefulLife"],
2430
+ description: "The number of months one unit is depreciated over, or null to clear it",
2431
+ valueName: "number",
2432
+ schema: z.coerce.number()
2433
+ }
2434
+ ]
1694
2435
  }), {
1695
2436
  name: "in-service-management",
1696
2437
  summary: "In service management commands",
@@ -1700,6 +2441,7 @@ const surfaceCommands = [
1700
2441
  subcommands: [defineOperation({
1701
2442
  name: "update",
1702
2443
  summary: "Toggle in service date management",
2444
+ example: "hardfin asset accounting in-service-management update ast_4f9xk2mq7plr8stz --automatic <value>",
1703
2445
  method: "PATCH",
1704
2446
  path: "/asset/{assetKey}/accounting/in-service-management",
1705
2447
  pathParameters: [{
@@ -1708,7 +2450,13 @@ const surfaceCommands = [
1708
2450
  required: true
1709
2451
  }],
1710
2452
  queryFlags: [],
1711
- takesBody: true
2453
+ bodyFlags: [{
2454
+ name: "automatic",
2455
+ jsonPath: ["automatic"],
2456
+ description: "Whether Hardfin sets the asset's in-service date itself",
2457
+ required: true,
2458
+ schema: z.boolean()
2459
+ }]
1712
2460
  })]
1713
2461
  }]
1714
2462
  },
@@ -1721,6 +2469,7 @@ const surfaceCommands = [
1721
2469
  subcommands: [defineOperation({
1722
2470
  name: "create",
1723
2471
  summary: "Create asset cost adjustment",
2472
+ example: "hardfin asset cost-adjustment create ast_4f9xk2mq7plr8stz --adjustment-type <value> --amount <value> --effective-date <value>",
1724
2473
  method: "POST",
1725
2474
  path: "/asset/{assetKey}/cost-adjustment",
1726
2475
  pathParameters: [{
@@ -1729,7 +2478,57 @@ const surfaceCommands = [
1729
2478
  required: true
1730
2479
  }],
1731
2480
  queryFlags: [],
1732
- takesBody: true
2481
+ bodyFlags: [
2482
+ {
2483
+ name: "adjustment-type",
2484
+ jsonPath: ["adjustmentType"],
2485
+ description: "Whether the adjustment adds to the asset's cost basis or writes it down",
2486
+ valueName: "value",
2487
+ required: true,
2488
+ schema: z.enum(["CAPITALIZATION", "IMPAIRMENT"])
2489
+ },
2490
+ {
2491
+ name: "amount",
2492
+ jsonPath: ["amount"],
2493
+ description: "How much the adjustment changes the cost basis by, which must be greater than zero",
2494
+ valueName: "value",
2495
+ required: true,
2496
+ schema: z.string()
2497
+ },
2498
+ {
2499
+ name: "effective-date",
2500
+ jsonPath: ["effectiveDate"],
2501
+ description: "The day the adjustment takes effect, which cannot be in the future",
2502
+ valueName: "value",
2503
+ required: true,
2504
+ schema: z.string()
2505
+ },
2506
+ {
2507
+ name: "notes",
2508
+ jsonPath: ["notes"],
2509
+ description: "Free-form detail about the adjustment, which a reason of OTHER requires",
2510
+ valueName: "value",
2511
+ schema: z.string()
2512
+ },
2513
+ {
2514
+ name: "reason",
2515
+ jsonPath: ["reason"],
2516
+ description: "Why the adjustment was made, which must be one its adjustment type allows",
2517
+ valueName: "value",
2518
+ required: true,
2519
+ schema: z.enum([
2520
+ "ADDITION",
2521
+ "BETTERMENT",
2522
+ "DAMAGE",
2523
+ "INSTALLATION",
2524
+ "LIFE_EXTENSION",
2525
+ "MARKET_DECLINE",
2526
+ "OBSOLESCENCE",
2527
+ "OTHER",
2528
+ "REGULATORY"
2529
+ ])
2530
+ }
2531
+ ]
1733
2532
  })]
1734
2533
  },
1735
2534
  {
@@ -1741,6 +2540,7 @@ const surfaceCommands = [
1741
2540
  subcommands: [defineOperation({
1742
2541
  name: "list",
1743
2542
  summary: "Get asset event list",
2543
+ example: "hardfin asset event list ast_4f9xk2mq7plr8stz",
1744
2544
  method: "GET",
1745
2545
  path: "/asset/{assetKey}/event",
1746
2546
  pathParameters: [{
@@ -1749,7 +2549,7 @@ const surfaceCommands = [
1749
2549
  required: true
1750
2550
  }],
1751
2551
  queryFlags: [],
1752
- takesBody: false
2552
+ bodyFlags: []
1753
2553
  })]
1754
2554
  },
1755
2555
  {
@@ -1761,6 +2561,7 @@ const surfaceCommands = [
1761
2561
  subcommands: [defineOperation({
1762
2562
  name: "list",
1763
2563
  summary: "Get asset event group listing",
2564
+ example: "hardfin asset event-group list ast_4f9xk2mq7plr8stz",
1764
2565
  method: "GET",
1765
2566
  path: "/asset/{assetKey}/event-group",
1766
2567
  pathParameters: [{
@@ -1781,10 +2582,11 @@ const surfaceCommands = [
1781
2582
  valueName: "value",
1782
2583
  schema: z.string()
1783
2584
  }],
1784
- takesBody: false
2585
+ bodyFlags: []
1785
2586
  }), defineOperation({
1786
2587
  name: "get",
1787
2588
  summary: "Get asset event group",
2589
+ example: "hardfin asset event-group get ast_4f9xk2mq7plr8stz aeg_3mx8kq2plr7stz4w",
1788
2590
  method: "GET",
1789
2591
  path: "/asset/{assetKey}/event-group/{eventGroupKey}",
1790
2592
  pathParameters: [{
@@ -1797,7 +2599,7 @@ const surfaceCommands = [
1797
2599
  required: true
1798
2600
  }],
1799
2601
  queryFlags: [],
1800
- takesBody: false
2602
+ bodyFlags: []
1801
2603
  })]
1802
2604
  },
1803
2605
  {
@@ -1809,6 +2611,7 @@ const surfaceCommands = [
1809
2611
  subcommands: [defineOperation({
1810
2612
  name: "list",
1811
2613
  summary: "Get asset files",
2614
+ example: "hardfin asset file list ast_4f9xk2mq7plr8stz",
1812
2615
  method: "GET",
1813
2616
  path: "/asset/{assetKey}/file",
1814
2617
  pathParameters: [{
@@ -1817,10 +2620,11 @@ const surfaceCommands = [
1817
2620
  required: true
1818
2621
  }],
1819
2622
  queryFlags: [],
1820
- takesBody: false
2623
+ bodyFlags: []
1821
2624
  }), defineOperation({
1822
2625
  name: "delete",
1823
2626
  summary: "Delete asset file",
2627
+ example: "hardfin asset file delete ast_4f9xk2mq7plr8stz file_7hq2mx9pkr4stz8w",
1824
2628
  method: "DELETE",
1825
2629
  path: "/asset/{assetKey}/file/{fileKey}",
1826
2630
  pathParameters: [{
@@ -1833,7 +2637,7 @@ const surfaceCommands = [
1833
2637
  required: true
1834
2638
  }],
1835
2639
  queryFlags: [],
1836
- takesBody: false
2640
+ bodyFlags: []
1837
2641
  })]
1838
2642
  },
1839
2643
  {
@@ -1845,6 +2649,7 @@ const surfaceCommands = [
1845
2649
  subcommands: [defineOperation({
1846
2650
  name: "list",
1847
2651
  summary: "Get asset functional status history",
2652
+ example: "hardfin asset functional-status list ast_4f9xk2mq7plr8stz",
1848
2653
  method: "GET",
1849
2654
  path: "/asset/{assetKey}/functional-status",
1850
2655
  pathParameters: [{
@@ -1853,7 +2658,7 @@ const surfaceCommands = [
1853
2658
  required: true
1854
2659
  }],
1855
2660
  queryFlags: [],
1856
- takesBody: false
2661
+ bodyFlags: []
1857
2662
  })]
1858
2663
  },
1859
2664
  {
@@ -1866,6 +2671,7 @@ const surfaceCommands = [
1866
2671
  defineOperation({
1867
2672
  name: "list",
1868
2673
  summary: "Get asset ownership history",
2674
+ example: "hardfin asset ownership list ast_4f9xk2mq7plr8stz",
1869
2675
  method: "GET",
1870
2676
  path: "/asset/{assetKey}/ownership",
1871
2677
  pathParameters: [{
@@ -1874,11 +2680,12 @@ const surfaceCommands = [
1874
2680
  required: true
1875
2681
  }],
1876
2682
  queryFlags: [],
1877
- takesBody: false
2683
+ bodyFlags: []
1878
2684
  }),
1879
2685
  defineOperation({
1880
2686
  name: "create",
1881
2687
  summary: "Create asset ownership",
2688
+ example: "hardfin asset ownership create ast_4f9xk2mq7plr8stz --customer-id <value> --date <value>",
1882
2689
  method: "POST",
1883
2690
  path: "/asset/{assetKey}/ownership",
1884
2691
  pathParameters: [{
@@ -1887,11 +2694,36 @@ const surfaceCommands = [
1887
2694
  required: true
1888
2695
  }],
1889
2696
  queryFlags: [],
1890
- takesBody: true
2697
+ bodyFlags: [
2698
+ {
2699
+ name: "customer-id",
2700
+ jsonPath: ["customerId"],
2701
+ description: "The ID of the customer that takes ownership of the asset",
2702
+ valueName: "value",
2703
+ required: true,
2704
+ schema: z.string()
2705
+ },
2706
+ {
2707
+ name: "date",
2708
+ jsonPath: ["date"],
2709
+ description: "The day the customer takes ownership, which cannot be in the future",
2710
+ valueName: "value",
2711
+ required: true,
2712
+ schema: z.string()
2713
+ },
2714
+ {
2715
+ name: "sale-price",
2716
+ jsonPath: ["salePrice"],
2717
+ description: "What the customer paid for the asset, which cannot be negative",
2718
+ valueName: "value",
2719
+ schema: z.string()
2720
+ }
2721
+ ]
1891
2722
  }),
1892
2723
  defineOperation({
1893
2724
  name: "clear",
1894
2725
  summary: "Clear the ownership an asset holds today",
2726
+ example: "hardfin asset ownership clear ast_4f9xk2mq7plr8stz --date <value>",
1895
2727
  method: "DELETE",
1896
2728
  path: "/asset/{assetKey}/ownership",
1897
2729
  pathParameters: [{
@@ -1900,11 +2732,19 @@ const surfaceCommands = [
1900
2732
  required: true
1901
2733
  }],
1902
2734
  queryFlags: [],
1903
- takesBody: true
2735
+ bodyFlags: [{
2736
+ name: "date",
2737
+ jsonPath: ["date"],
2738
+ description: "The day your organization takes the asset back, which cannot be in the future",
2739
+ valueName: "value",
2740
+ required: true,
2741
+ schema: z.string()
2742
+ }]
1904
2743
  }),
1905
2744
  defineOperation({
1906
2745
  name: "get",
1907
2746
  summary: "Get asset ownership segment",
2747
+ example: "hardfin asset ownership get ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
1908
2748
  method: "GET",
1909
2749
  path: "/asset/{assetKey}/ownership/{segmentKey}",
1910
2750
  pathParameters: [{
@@ -1917,11 +2757,12 @@ const surfaceCommands = [
1917
2757
  required: true
1918
2758
  }],
1919
2759
  queryFlags: [],
1920
- takesBody: false
2760
+ bodyFlags: []
1921
2761
  }),
1922
2762
  defineOperation({
1923
2763
  name: "update",
1924
2764
  summary: "Patch asset ownership segment",
2765
+ example: "hardfin asset ownership update ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
1925
2766
  method: "PATCH",
1926
2767
  path: "/asset/{assetKey}/ownership/{segmentKey}",
1927
2768
  pathParameters: [{
@@ -1934,11 +2775,34 @@ const surfaceCommands = [
1934
2775
  required: true
1935
2776
  }],
1936
2777
  queryFlags: [],
1937
- takesBody: true
2778
+ bodyFlags: [
2779
+ {
2780
+ name: "customer-id",
2781
+ jsonPath: ["customerId"],
2782
+ description: "The ID of the customer that owned the asset during the segment",
2783
+ valueName: "value",
2784
+ schema: z.string()
2785
+ },
2786
+ {
2787
+ name: "date",
2788
+ jsonPath: ["date"],
2789
+ description: "The day the segment's owner took ownership, which cannot be in the future",
2790
+ valueName: "value",
2791
+ schema: z.string()
2792
+ },
2793
+ {
2794
+ name: "sale-price",
2795
+ jsonPath: ["salePrice"],
2796
+ description: "What the owner paid for the asset, which cannot be negative",
2797
+ valueName: "value",
2798
+ schema: z.string()
2799
+ }
2800
+ ]
1938
2801
  }),
1939
2802
  defineOperation({
1940
2803
  name: "delete",
1941
2804
  summary: "Delete asset ownership segment",
2805
+ example: "hardfin asset ownership delete ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
1942
2806
  method: "DELETE",
1943
2807
  path: "/asset/{assetKey}/ownership/{segmentKey}",
1944
2808
  pathParameters: [{
@@ -1951,7 +2815,7 @@ const surfaceCommands = [
1951
2815
  required: true
1952
2816
  }],
1953
2817
  queryFlags: [],
1954
- takesBody: false
2818
+ bodyFlags: []
1955
2819
  })
1956
2820
  ]
1957
2821
  },
@@ -1964,6 +2828,7 @@ const surfaceCommands = [
1964
2828
  subcommands: [defineOperation({
1965
2829
  name: "create",
1966
2830
  summary: "Scrap asset",
2831
+ example: "hardfin asset scrap create ast_4f9xk2mq7plr8stz --disposal-date <value>",
1967
2832
  method: "POST",
1968
2833
  path: "/asset/{assetKey}/scrap",
1969
2834
  pathParameters: [{
@@ -1972,7 +2837,30 @@ const surfaceCommands = [
1972
2837
  required: true
1973
2838
  }],
1974
2839
  queryFlags: [],
1975
- takesBody: true
2840
+ bodyFlags: [
2841
+ {
2842
+ name: "disposal-date",
2843
+ jsonPath: ["disposalDate"],
2844
+ description: "The day the asset was scrapped",
2845
+ valueName: "value",
2846
+ required: true,
2847
+ schema: z.string()
2848
+ },
2849
+ {
2850
+ name: "disposal-price",
2851
+ jsonPath: ["disposalPrice"],
2852
+ description: "What the scrapped asset was sold for, or null when it was not sold",
2853
+ valueName: "value",
2854
+ schema: z.string()
2855
+ },
2856
+ {
2857
+ name: "disposal-reason",
2858
+ jsonPath: ["disposalReason"],
2859
+ description: "Why the asset was scrapped",
2860
+ valueName: "value",
2861
+ schema: z.string()
2862
+ }
2863
+ ]
1976
2864
  })]
1977
2865
  },
1978
2866
  {
@@ -1984,6 +2872,7 @@ const surfaceCommands = [
1984
2872
  subcommands: [defineOperation({
1985
2873
  name: "create",
1986
2874
  summary: "Unscrap asset",
2875
+ example: "hardfin asset unscrap create ast_4f9xk2mq7plr8stz",
1987
2876
  method: "POST",
1988
2877
  path: "/asset/{assetKey}/unscrap",
1989
2878
  pathParameters: [{
@@ -1992,7 +2881,7 @@ const surfaceCommands = [
1992
2881
  required: true
1993
2882
  }],
1994
2883
  queryFlags: [],
1995
- takesBody: false
2884
+ bodyFlags: []
1996
2885
  })]
1997
2886
  },
1998
2887
  {
@@ -2004,6 +2893,7 @@ const surfaceCommands = [
2004
2893
  subcommands: [defineOperation({
2005
2894
  name: "list",
2006
2895
  summary: "Get asset URL links",
2896
+ example: "hardfin asset url-link list ast_4f9xk2mq7plr8stz",
2007
2897
  method: "GET",
2008
2898
  path: "/asset/{assetKey}/url-link",
2009
2899
  pathParameters: [{
@@ -2012,10 +2902,11 @@ const surfaceCommands = [
2012
2902
  required: true
2013
2903
  }],
2014
2904
  queryFlags: [],
2015
- takesBody: false
2905
+ bodyFlags: []
2016
2906
  }), defineOperation({
2017
2907
  name: "create",
2018
2908
  summary: "Create asset URL link",
2909
+ example: "hardfin asset url-link create ast_4f9xk2mq7plr8stz --url <value>",
2019
2910
  method: "POST",
2020
2911
  path: "/asset/{assetKey}/url-link",
2021
2912
  pathParameters: [{
@@ -2024,7 +2915,20 @@ const surfaceCommands = [
2024
2915
  required: true
2025
2916
  }],
2026
2917
  queryFlags: [],
2027
- takesBody: true
2918
+ bodyFlags: [{
2919
+ name: "name",
2920
+ jsonPath: ["name"],
2921
+ description: "The link's display name, or null to show the address instead",
2922
+ valueName: "value",
2923
+ schema: z.string()
2924
+ }, {
2925
+ name: "url",
2926
+ jsonPath: ["url"],
2927
+ description: "The address the link points to",
2928
+ valueName: "value",
2929
+ required: true,
2930
+ schema: z.string()
2931
+ }]
2028
2932
  })]
2029
2933
  },
2030
2934
  {
@@ -2036,6 +2940,7 @@ const surfaceCommands = [
2036
2940
  subcommands: [defineOperation({
2037
2941
  name: "create",
2038
2942
  summary: "Create asset useful life revision",
2943
+ example: "hardfin asset useful-life-revision create ast_4f9xk2mq7plr8stz --effective-date <value> --reason <value> --useful-life-months <number>",
2039
2944
  method: "POST",
2040
2945
  path: "/asset/{assetKey}/useful-life-revision",
2041
2946
  pathParameters: [{
@@ -2044,7 +2949,47 @@ const surfaceCommands = [
2044
2949
  required: true
2045
2950
  }],
2046
2951
  queryFlags: [],
2047
- takesBody: true
2952
+ bodyFlags: [
2953
+ {
2954
+ name: "effective-date",
2955
+ jsonPath: ["effectiveDate"],
2956
+ description: "The day the revised useful life takes effect, which cannot be in the future",
2957
+ valueName: "value",
2958
+ required: true,
2959
+ schema: z.string()
2960
+ },
2961
+ {
2962
+ name: "notes",
2963
+ jsonPath: ["notes"],
2964
+ description: "Free-form detail about the revision, which a reason of OTHER requires",
2965
+ valueName: "value",
2966
+ schema: z.string()
2967
+ },
2968
+ {
2969
+ name: "reason",
2970
+ jsonPath: ["reason"],
2971
+ description: "Why the useful life was revised",
2972
+ valueName: "value",
2973
+ required: true,
2974
+ schema: z.enum([
2975
+ "CHANGE_IN_USE",
2976
+ "DAMAGE",
2977
+ "OBSOLESCENCE",
2978
+ "OTHER",
2979
+ "REASSESSMENT",
2980
+ "REFURBISHMENT",
2981
+ "REGULATORY"
2982
+ ])
2983
+ },
2984
+ {
2985
+ name: "useful-life-months",
2986
+ jsonPath: ["usefulLifeMonths"],
2987
+ description: "The asset's revised useful life in months",
2988
+ valueName: "number",
2989
+ required: true,
2990
+ schema: z.coerce.number()
2991
+ }
2992
+ ]
2048
2993
  })]
2049
2994
  }
2050
2995
  ]
@@ -2059,6 +3004,7 @@ const surfaceCommands = [
2059
3004
  defineOperation({
2060
3005
  name: "list",
2061
3006
  summary: "Get customers",
3007
+ example: "hardfin customer list --limit 10",
2062
3008
  method: "GET",
2063
3009
  path: "/customer",
2064
3010
  pathParameters: [],
@@ -2130,33 +3076,106 @@ const surfaceCommands = [
2130
3076
  schema: z.string()
2131
3077
  }
2132
3078
  ],
2133
- takesBody: false
3079
+ bodyFlags: []
2134
3080
  }),
2135
3081
  defineOperation({
2136
3082
  name: "create",
2137
3083
  summary: "Create customer",
3084
+ example: "hardfin customer create --name <value>",
2138
3085
  method: "POST",
2139
3086
  path: "/customer",
2140
3087
  pathParameters: [],
2141
3088
  queryFlags: [],
2142
- takesBody: true
2143
- }),
2144
- defineOperation({
2145
- name: "get",
2146
- summary: "Get customer",
2147
- method: "GET",
2148
- path: "/customer/{customerKey}",
2149
- pathParameters: [{
2150
- name: "customerKey",
2151
- description: "The customer's key",
2152
- required: true
2153
- }],
2154
- queryFlags: [],
2155
- takesBody: false
2156
- }),
3089
+ bodyFlags: [
3090
+ {
3091
+ name: "billing-address",
3092
+ jsonPath: ["billingAddress"],
3093
+ description: "The address invoices are sent to",
3094
+ valueName: "value",
3095
+ schema: z.string()
3096
+ },
3097
+ {
3098
+ name: "billing-contact-email",
3099
+ jsonPath: ["billingContact", "email"],
3100
+ description: "The billing contact's email address",
3101
+ valueName: "value",
3102
+ schema: z.string()
3103
+ },
3104
+ {
3105
+ name: "billing-contact-name",
3106
+ jsonPath: ["billingContact", "name"],
3107
+ description: "The billing contact's name",
3108
+ valueName: "value",
3109
+ schema: z.string()
3110
+ },
3111
+ {
3112
+ name: "billing-contact-phone",
3113
+ jsonPath: ["billingContact", "phone"],
3114
+ description: "The billing contact's phone number",
3115
+ valueName: "value",
3116
+ schema: z.string()
3117
+ },
3118
+ {
3119
+ name: "comment",
3120
+ jsonPath: ["comment"],
3121
+ description: "A free-form note about the customer",
3122
+ valueName: "value",
3123
+ schema: z.string()
3124
+ },
3125
+ {
3126
+ name: "domain",
3127
+ jsonPath: ["domain"],
3128
+ description: "The customer's web domain, used to look up its logo",
3129
+ valueName: "value",
3130
+ schema: z.string()
3131
+ },
3132
+ {
3133
+ name: "external-id",
3134
+ jsonPath: ["externalId"],
3135
+ description: "The customer's identifier in another system",
3136
+ valueName: "value",
3137
+ schema: z.string()
3138
+ },
3139
+ {
3140
+ name: "is-customer",
3141
+ jsonPath: ["isCustomer"],
3142
+ description: "Whether the company is a customer",
3143
+ schema: z.boolean()
3144
+ },
3145
+ {
3146
+ name: "is-supplier",
3147
+ jsonPath: ["isSupplier"],
3148
+ description: "Whether the company is a supplier",
3149
+ schema: z.boolean()
3150
+ },
3151
+ {
3152
+ name: "name",
3153
+ jsonPath: ["name"],
3154
+ description: "The customer's display name",
3155
+ valueName: "value",
3156
+ required: true,
3157
+ schema: z.string()
3158
+ }
3159
+ ]
3160
+ }),
3161
+ defineOperation({
3162
+ name: "get",
3163
+ summary: "Get customer",
3164
+ example: "hardfin customer get cust_V1StGXR8Z5jdHi6B",
3165
+ method: "GET",
3166
+ path: "/customer/{customerKey}",
3167
+ pathParameters: [{
3168
+ name: "customerKey",
3169
+ description: "The customer's key",
3170
+ required: true
3171
+ }],
3172
+ queryFlags: [],
3173
+ bodyFlags: []
3174
+ }),
2157
3175
  defineOperation({
2158
3176
  name: "update",
2159
3177
  summary: "Patch customer",
3178
+ example: "hardfin customer update cust_V1StGXR8Z5jdHi6B",
2160
3179
  method: "PATCH",
2161
3180
  path: "/customer/{customerKey}",
2162
3181
  pathParameters: [{
@@ -2165,7 +3184,82 @@ const surfaceCommands = [
2165
3184
  required: true
2166
3185
  }],
2167
3186
  queryFlags: [],
2168
- takesBody: true
3187
+ bodyFlags: [
3188
+ {
3189
+ name: "billing-address",
3190
+ jsonPath: ["billingAddress"],
3191
+ description: "The address invoices are sent to",
3192
+ valueName: "value",
3193
+ schema: z.string()
3194
+ },
3195
+ {
3196
+ name: "billing-contact-email",
3197
+ jsonPath: ["billingContact", "email"],
3198
+ description: "The billing contact's email address",
3199
+ valueName: "value",
3200
+ schema: z.string()
3201
+ },
3202
+ {
3203
+ name: "billing-contact-name",
3204
+ jsonPath: ["billingContact", "name"],
3205
+ description: "The billing contact's name",
3206
+ valueName: "value",
3207
+ schema: z.string()
3208
+ },
3209
+ {
3210
+ name: "billing-contact-phone",
3211
+ jsonPath: ["billingContact", "phone"],
3212
+ description: "The billing contact's phone number",
3213
+ valueName: "value",
3214
+ schema: z.string()
3215
+ },
3216
+ {
3217
+ name: "comment",
3218
+ jsonPath: ["comment"],
3219
+ description: "A free-form note about the customer",
3220
+ valueName: "value",
3221
+ schema: z.string()
3222
+ },
3223
+ {
3224
+ name: "domain",
3225
+ jsonPath: ["domain"],
3226
+ description: "The customer's web domain, used to look up its logo",
3227
+ valueName: "value",
3228
+ schema: z.string()
3229
+ },
3230
+ {
3231
+ name: "external-id",
3232
+ jsonPath: ["externalId"],
3233
+ description: "The customer's identifier in another system",
3234
+ valueName: "value",
3235
+ schema: z.string()
3236
+ },
3237
+ {
3238
+ name: "is-archived",
3239
+ jsonPath: ["isArchived"],
3240
+ description: "Whether the customer is archived",
3241
+ schema: z.boolean()
3242
+ },
3243
+ {
3244
+ name: "is-customer",
3245
+ jsonPath: ["isCustomer"],
3246
+ description: "Whether the company is a customer",
3247
+ schema: z.boolean()
3248
+ },
3249
+ {
3250
+ name: "is-supplier",
3251
+ jsonPath: ["isSupplier"],
3252
+ description: "Whether the company is a supplier",
3253
+ schema: z.boolean()
3254
+ },
3255
+ {
3256
+ name: "name",
3257
+ jsonPath: ["name"],
3258
+ description: "The customer's display name",
3259
+ valueName: "value",
3260
+ schema: z.string()
3261
+ }
3262
+ ]
2169
3263
  })
2170
3264
  ]
2171
3265
  },
@@ -2178,14 +3272,44 @@ const surfaceCommands = [
2178
3272
  subcommands: [defineOperation({
2179
3273
  name: "create",
2180
3274
  summary: "Upload file",
3275
+ example: "hardfin file create --file-type <value> --for-entity <value> --file photo.jpg",
2181
3276
  method: "POST",
2182
3277
  path: "/file",
2183
3278
  pathParameters: [],
2184
3279
  queryFlags: [],
2185
- takesBody: true
3280
+ bodyFlags: [],
3281
+ upload: {
3282
+ filePart: "data",
3283
+ fields: [
3284
+ {
3285
+ name: "file-type",
3286
+ jsonPath: ["fileType"],
3287
+ description: "The kind of file uploaded, which is ASSET_FILE, the only kind the API uploads",
3288
+ valueName: "value",
3289
+ required: true,
3290
+ schema: z.string()
3291
+ },
3292
+ {
3293
+ name: "for-entity",
3294
+ jsonPath: ["forEntity"],
3295
+ description: "The ID of the asset the file is attached to",
3296
+ valueName: "value",
3297
+ required: true,
3298
+ schema: z.string()
3299
+ },
3300
+ {
3301
+ name: "is-public",
3302
+ jsonPath: ["isPublic"],
3303
+ description: "Whether any organization's API key may download the file, which is false unless sent as true",
3304
+ valueName: "value",
3305
+ schema: z.string()
3306
+ }
3307
+ ]
3308
+ }
2186
3309
  }), defineOperation({
2187
3310
  name: "get",
2188
3311
  summary: "Get file",
3312
+ example: "hardfin file get file_7hq2mx9pkr4stz8w",
2189
3313
  method: "GET",
2190
3314
  path: "/file/{fileKey}",
2191
3315
  pathParameters: [{
@@ -2199,7 +3323,7 @@ const surfaceCommands = [
2199
3323
  description: "True when the file downloads as an attachment rather than opening inline",
2200
3324
  schema: z.boolean()
2201
3325
  }],
2202
- takesBody: false
3326
+ bodyFlags: []
2203
3327
  })]
2204
3328
  },
2205
3329
  {
@@ -2212,6 +3336,7 @@ const surfaceCommands = [
2212
3336
  defineOperation({
2213
3337
  name: "list",
2214
3338
  summary: "Get items",
3339
+ example: "hardfin item list --limit 10",
2215
3340
  method: "GET",
2216
3341
  path: "/item",
2217
3342
  pathParameters: [],
@@ -2286,20 +3411,129 @@ const surfaceCommands = [
2286
3411
  schema: z.string()
2287
3412
  }
2288
3413
  ],
2289
- takesBody: false
3414
+ bodyFlags: []
2290
3415
  }),
2291
3416
  defineOperation({
2292
3417
  name: "create",
2293
3418
  summary: "Create item",
3419
+ example: "hardfin item create --name <value> --sku <value> --type <value>",
2294
3420
  method: "POST",
2295
3421
  path: "/item",
2296
3422
  pathParameters: [],
2297
3423
  queryFlags: [],
2298
- takesBody: true
3424
+ bodyFlags: [
3425
+ {
3426
+ name: "accepts-bulk-serials",
3427
+ jsonPath: ["acceptsBulkSerials"],
3428
+ description: "Whether a BULK item records serial numbers on its units, which SERVICE and DEVICE items ignore",
3429
+ schema: z.boolean()
3430
+ },
3431
+ {
3432
+ name: "description",
3433
+ jsonPath: ["description"],
3434
+ description: "A free-form description of the item",
3435
+ valueName: "value",
3436
+ schema: z.string()
3437
+ },
3438
+ {
3439
+ name: "name",
3440
+ jsonPath: ["name"],
3441
+ description: "The item's display name",
3442
+ valueName: "value",
3443
+ required: true,
3444
+ schema: z.string()
3445
+ },
3446
+ {
3447
+ name: "sku",
3448
+ jsonPath: ["sku"],
3449
+ description: "The item's stock keeping unit, unique within your organization",
3450
+ valueName: "value",
3451
+ required: true,
3452
+ schema: z.string()
3453
+ },
3454
+ {
3455
+ name: "type",
3456
+ jsonPath: ["type"],
3457
+ description: "SERVICE for a non-physical item, DEVICE for a physical item tracked by serial number, or BULK for a part tracked by quantity",
3458
+ valueName: "value",
3459
+ required: true,
3460
+ schema: z.enum([
3461
+ "BULK",
3462
+ "DEVICE",
3463
+ "SERVICE"
3464
+ ])
3465
+ },
3466
+ {
3467
+ name: "unit-of-measure",
3468
+ jsonPath: ["unitOfMeasure"],
3469
+ description: "The unit a BULK item's quantities are counted in, which SERVICE and DEVICE items ignore",
3470
+ valueName: "value",
3471
+ schema: z.enum([
3472
+ "BG",
3473
+ "BO",
3474
+ "BX",
3475
+ "C62",
3476
+ "CMK",
3477
+ "CMT",
3478
+ "CR",
3479
+ "CS",
3480
+ "CT",
3481
+ "DMQ",
3482
+ "DR",
3483
+ "DZN",
3484
+ "EA",
3485
+ "EN",
3486
+ "FOT",
3487
+ "FTK",
3488
+ "FTQ",
3489
+ "GLL",
3490
+ "GRM",
3491
+ "GRO",
3492
+ "H87",
3493
+ "INH",
3494
+ "INK",
3495
+ "INQ",
3496
+ "KG",
3497
+ "KGM",
3498
+ "KMT",
3499
+ "KT",
3500
+ "LBR",
3501
+ "LO",
3502
+ "LTR",
3503
+ "MGM",
3504
+ "MLT",
3505
+ "MMK",
3506
+ "MMT",
3507
+ "MTK",
3508
+ "MTQ",
3509
+ "MTR",
3510
+ "ONZ",
3511
+ "OZA",
3512
+ "PK",
3513
+ "PR",
3514
+ "PTI",
3515
+ "PX",
3516
+ "QTI",
3517
+ "RL",
3518
+ "RO",
3519
+ "SET",
3520
+ "SMI",
3521
+ "ST",
3522
+ "STN",
3523
+ "SV",
3524
+ "TNE",
3525
+ "TU",
3526
+ "YDK",
3527
+ "YDQ",
3528
+ "YRD"
3529
+ ])
3530
+ }
3531
+ ]
2299
3532
  }),
2300
3533
  defineOperation({
2301
3534
  name: "get",
2302
3535
  summary: "Get item",
3536
+ example: "hardfin item get item_7Hq2Lm9XcR4tWz8K",
2303
3537
  method: "GET",
2304
3538
  path: "/item/{itemKey}",
2305
3539
  pathParameters: [{
@@ -2308,11 +3542,12 @@ const surfaceCommands = [
2308
3542
  required: true
2309
3543
  }],
2310
3544
  queryFlags: [],
2311
- takesBody: false
3545
+ bodyFlags: []
2312
3546
  }),
2313
3547
  defineOperation({
2314
3548
  name: "update",
2315
3549
  summary: "Update item",
3550
+ example: "hardfin item update item_7Hq2Lm9XcR4tWz8K",
2316
3551
  method: "PATCH",
2317
3552
  path: "/item/{itemKey}",
2318
3553
  pathParameters: [{
@@ -2321,7 +3556,65 @@ const surfaceCommands = [
2321
3556
  required: true
2322
3557
  }],
2323
3558
  queryFlags: [],
2324
- takesBody: true
3559
+ bodyFlags: [
3560
+ {
3561
+ name: "accepts-bulk-serials",
3562
+ jsonPath: ["acceptsBulkSerials"],
3563
+ description: "Whether a BULK item records serial numbers on its units, read only beside type",
3564
+ schema: z.boolean()
3565
+ },
3566
+ {
3567
+ name: "description",
3568
+ jsonPath: ["description"],
3569
+ description: "The item's new description, or null to clear it",
3570
+ valueName: "value",
3571
+ schema: z.string()
3572
+ },
3573
+ {
3574
+ name: "field",
3575
+ jsonPath: ["fields"],
3576
+ description: "New positions for a DEVICE item's fields",
3577
+ valueName: "fieldId=,order=",
3578
+ repeatable: true,
3579
+ element: [
3580
+ "fieldId",
3581
+ "order",
3582
+ "section"
3583
+ ],
3584
+ schema: z.array(z.string())
3585
+ },
3586
+ {
3587
+ name: "is-archived",
3588
+ jsonPath: ["isArchived"],
3589
+ description: "Whether the item is archived, which cannot be null",
3590
+ schema: z.boolean()
3591
+ },
3592
+ {
3593
+ name: "name",
3594
+ jsonPath: ["name"],
3595
+ description: "The item's new display name, which cannot be empty",
3596
+ valueName: "value",
3597
+ schema: z.string()
3598
+ },
3599
+ {
3600
+ name: "sku",
3601
+ jsonPath: ["sku"],
3602
+ description: "The item's new stock keeping unit, which cannot be empty and must be unique within your organization",
3603
+ valueName: "value",
3604
+ schema: z.string()
3605
+ },
3606
+ {
3607
+ name: "type",
3608
+ jsonPath: ["type"],
3609
+ description: "The type to convert the item to, when the item's assets and inventory history allow the conversion",
3610
+ valueName: "value",
3611
+ schema: z.enum([
3612
+ "BULK",
3613
+ "DEVICE",
3614
+ "SERVICE"
3615
+ ])
3616
+ }
3617
+ ]
2325
3618
  }),
2326
3619
  {
2327
3620
  name: "accounting",
@@ -2332,6 +3625,7 @@ const surfaceCommands = [
2332
3625
  subcommands: [defineOperation({
2333
3626
  name: "update",
2334
3627
  summary: "Update item accounting",
3628
+ example: "hardfin item accounting update item_7Hq2Lm9XcR4tWz8K",
2335
3629
  method: "PATCH",
2336
3630
  path: "/item/{itemKey}/accounting",
2337
3631
  pathParameters: [{
@@ -2340,7 +3634,104 @@ const surfaceCommands = [
2340
3634
  required: true
2341
3635
  }],
2342
3636
  queryFlags: [],
2343
- takesBody: true
3637
+ bodyFlags: [
3638
+ {
3639
+ name: "allocated-indirect",
3640
+ jsonPath: ["allocatedIndirect"],
3641
+ description: "One unit's share of overhead, a cost component",
3642
+ valueName: "value",
3643
+ schema: z.string()
3644
+ },
3645
+ {
3646
+ name: "bill-of-materials",
3647
+ jsonPath: ["billOfMaterials"],
3648
+ description: "The parts cost of one unit, a cost component",
3649
+ valueName: "value",
3650
+ schema: z.string()
3651
+ },
3652
+ {
3653
+ name: "depreciation-model",
3654
+ jsonPath: ["depreciationModel"],
3655
+ description: "The method one unit is depreciated by, or null to clear it",
3656
+ valueName: "value",
3657
+ schema: z.enum([
3658
+ "DOUBLE_DECLINING",
3659
+ "STRAIGHT_LINE",
3660
+ "SUM_YEAR",
3661
+ "UNIT_OF_PRODUCTION"
3662
+ ])
3663
+ },
3664
+ {
3665
+ name: "direct-labor",
3666
+ jsonPath: ["directLabor"],
3667
+ description: "The labor cost to build one unit, a cost component",
3668
+ valueName: "value",
3669
+ schema: z.string()
3670
+ },
3671
+ {
3672
+ name: "freight-inbound",
3673
+ jsonPath: ["freightInbound"],
3674
+ description: "The shipping cost to receive one unit, a cost component",
3675
+ valueName: "value",
3676
+ schema: z.string()
3677
+ },
3678
+ {
3679
+ name: "freight-outbound",
3680
+ jsonPath: ["freightOutbound"],
3681
+ description: "The shipping cost to deploy one unit, a deployment cost component",
3682
+ valueName: "value",
3683
+ schema: z.string()
3684
+ },
3685
+ {
3686
+ name: "installation",
3687
+ jsonPath: ["installation"],
3688
+ description: "The cost to install one unit, a deployment cost component",
3689
+ valueName: "value",
3690
+ schema: z.string()
3691
+ },
3692
+ {
3693
+ name: "interest",
3694
+ jsonPath: ["interest"],
3695
+ description: "The financing cost of one unit, a cost component",
3696
+ valueName: "value",
3697
+ schema: z.string()
3698
+ },
3699
+ {
3700
+ name: "salvage-value",
3701
+ jsonPath: ["salvageValue"],
3702
+ description: "The value one unit keeps at the end of its useful life, or null to clear it",
3703
+ valueName: "value",
3704
+ schema: z.string()
3705
+ },
3706
+ {
3707
+ name: "simple-cost-basis",
3708
+ jsonPath: ["simpleCostBasis"],
3709
+ description: "A single cost for one unit, which cannot be sent together with the cost components",
3710
+ valueName: "value",
3711
+ schema: z.string()
3712
+ },
3713
+ {
3714
+ name: "tariffs",
3715
+ jsonPath: ["tariffs"],
3716
+ description: "The import duty paid on one unit, a cost component",
3717
+ valueName: "value",
3718
+ schema: z.string()
3719
+ },
3720
+ {
3721
+ name: "tax",
3722
+ jsonPath: ["tax"],
3723
+ description: "The tax paid on one unit, a cost component",
3724
+ valueName: "value",
3725
+ schema: z.string()
3726
+ },
3727
+ {
3728
+ name: "useful-life",
3729
+ jsonPath: ["usefulLife"],
3730
+ description: "The number of months one unit is depreciated over, or null to clear it",
3731
+ valueName: "number",
3732
+ schema: z.coerce.number()
3733
+ }
3734
+ ]
2344
3735
  })]
2345
3736
  },
2346
3737
  {
@@ -2353,6 +3744,7 @@ const surfaceCommands = [
2353
3744
  defineOperation({
2354
3745
  name: "create",
2355
3746
  summary: "Create item field",
3747
+ example: "hardfin item field create item_7Hq2Lm9XcR4tWz8K --field-type <value> --label <value> --order <number>",
2356
3748
  method: "POST",
2357
3749
  path: "/item/{itemKey}/field",
2358
3750
  pathParameters: [{
@@ -2361,11 +3753,54 @@ const surfaceCommands = [
2361
3753
  required: true
2362
3754
  }],
2363
3755
  queryFlags: [],
2364
- takesBody: true
3756
+ bodyFlags: [
3757
+ {
3758
+ name: "field-type",
3759
+ jsonPath: ["fieldType"],
3760
+ description: "The kind of value the field holds",
3761
+ valueName: "value",
3762
+ required: true,
3763
+ schema: z.enum([
3764
+ "BOOLEAN",
3765
+ "DATE",
3766
+ "DATE_TIME",
3767
+ "INTEGER",
3768
+ "MULTILINE_TEXT",
3769
+ "NUMBER",
3770
+ "TEXT",
3771
+ "TIME"
3772
+ ])
3773
+ },
3774
+ {
3775
+ name: "label",
3776
+ jsonPath: ["label"],
3777
+ description: "The field's display name",
3778
+ valueName: "value",
3779
+ required: true,
3780
+ schema: z.string()
3781
+ },
3782
+ {
3783
+ name: "order",
3784
+ jsonPath: ["order"],
3785
+ description: "The field's position within its section, starting at 0",
3786
+ valueName: "number",
3787
+ required: true,
3788
+ schema: z.coerce.number()
3789
+ },
3790
+ {
3791
+ name: "section",
3792
+ jsonPath: ["section"],
3793
+ description: "The group the field is shown in, starting at 0",
3794
+ valueName: "number",
3795
+ required: true,
3796
+ schema: z.coerce.number()
3797
+ }
3798
+ ]
2365
3799
  }),
2366
3800
  defineOperation({
2367
3801
  name: "update",
2368
3802
  summary: "Update item field",
3803
+ example: "hardfin item field update item_7Hq2Lm9XcR4tWz8K pfield_2wn8kq4lxp7rtz3m",
2369
3804
  method: "PATCH",
2370
3805
  path: "/item/{itemKey}/field/{fieldKey}",
2371
3806
  pathParameters: [{
@@ -2378,11 +3813,18 @@ const surfaceCommands = [
2378
3813
  required: true
2379
3814
  }],
2380
3815
  queryFlags: [],
2381
- takesBody: true
3816
+ bodyFlags: [{
3817
+ name: "label",
3818
+ jsonPath: ["label"],
3819
+ description: "The field's new display name, which cannot be empty",
3820
+ valueName: "value",
3821
+ schema: z.string()
3822
+ }]
2382
3823
  }),
2383
3824
  defineOperation({
2384
3825
  name: "delete",
2385
3826
  summary: "Delete item field",
3827
+ example: "hardfin item field delete item_7Hq2Lm9XcR4tWz8K pfield_2wn8kq4lxp7rtz3m",
2386
3828
  method: "DELETE",
2387
3829
  path: "/item/{itemKey}/field/{fieldKey}",
2388
3830
  pathParameters: [{
@@ -2395,7 +3837,7 @@ const surfaceCommands = [
2395
3837
  required: true
2396
3838
  }],
2397
3839
  queryFlags: [],
2398
- takesBody: false
3840
+ bodyFlags: []
2399
3841
  })
2400
3842
  ]
2401
3843
  }
@@ -2411,6 +3853,7 @@ const surfaceCommands = [
2411
3853
  defineOperation({
2412
3854
  name: "list",
2413
3855
  summary: "Get location listing",
3856
+ example: "hardfin location list --limit 10",
2414
3857
  method: "GET",
2415
3858
  path: "/location",
2416
3859
  pathParameters: [],
@@ -2499,20 +3942,136 @@ const surfaceCommands = [
2499
3942
  schema: z.array(z.string())
2500
3943
  }
2501
3944
  ],
2502
- takesBody: false
3945
+ bodyFlags: []
2503
3946
  }),
2504
3947
  defineOperation({
2505
3948
  name: "create",
2506
3949
  summary: "Create location",
3950
+ example: "hardfin location create",
2507
3951
  method: "POST",
2508
3952
  path: "/location",
2509
3953
  pathParameters: [],
2510
3954
  queryFlags: [],
2511
- takesBody: true
3955
+ bodyFlags: [
3956
+ {
3957
+ name: "address-line1",
3958
+ jsonPath: ["address", "addressLine1"],
3959
+ description: "The first line of the street address",
3960
+ valueName: "value",
3961
+ schema: z.string()
3962
+ },
3963
+ {
3964
+ name: "address-line2",
3965
+ jsonPath: ["address", "addressLine2"],
3966
+ description: "The second line of the street address, such as a suite",
3967
+ valueName: "value",
3968
+ schema: z.string()
3969
+ },
3970
+ {
3971
+ name: "address-city",
3972
+ jsonPath: ["address", "city"],
3973
+ description: "The city",
3974
+ valueName: "value",
3975
+ schema: z.string()
3976
+ },
3977
+ {
3978
+ name: "address-country",
3979
+ jsonPath: ["address", "country"],
3980
+ description: "The country",
3981
+ valueName: "value",
3982
+ schema: z.string()
3983
+ },
3984
+ {
3985
+ name: "address-formatted-address",
3986
+ jsonPath: ["address", "formattedAddress"],
3987
+ description: "The whole address on one line",
3988
+ valueName: "value",
3989
+ schema: z.string()
3990
+ },
3991
+ {
3992
+ name: "address-postal-code",
3993
+ jsonPath: ["address", "postalCode"],
3994
+ description: "The postal or ZIP code",
3995
+ valueName: "value",
3996
+ schema: z.string()
3997
+ },
3998
+ {
3999
+ name: "address-state",
4000
+ jsonPath: ["address", "state"],
4001
+ description: "The state or region",
4002
+ valueName: "value",
4003
+ schema: z.string()
4004
+ },
4005
+ {
4006
+ name: "consignee",
4007
+ jsonPath: ["consignee"],
4008
+ description: "The ID of the customer a zone is designated for, such as for reservations, provisioning or a 3PL",
4009
+ valueName: "value",
4010
+ schema: z.string()
4011
+ },
4012
+ {
4013
+ name: "customer-id",
4014
+ jsonPath: ["customerId"],
4015
+ description: "The ID of the customer to assign a site to, or null for your organization's own site",
4016
+ valueName: "value",
4017
+ schema: z.string()
4018
+ },
4019
+ {
4020
+ name: "description",
4021
+ jsonPath: ["description"],
4022
+ description: "A free-form description of a zone",
4023
+ valueName: "value",
4024
+ schema: z.string()
4025
+ },
4026
+ {
4027
+ name: "is-inventory",
4028
+ jsonPath: ["isInventory"],
4029
+ description: "Whether assets at the location count as inventory for reporting",
4030
+ schema: z.boolean()
4031
+ },
4032
+ {
4033
+ name: "is-inventory-override",
4034
+ jsonPath: ["isInventoryOverride"],
4035
+ description: "Whether a zone sets its own isInventory rather than inheriting its parent site's, which a site refuses",
4036
+ schema: z.boolean()
4037
+ },
4038
+ {
4039
+ name: "is-transient",
4040
+ jsonPath: ["isTransient"],
4041
+ description: "Whether assets make only occasional or temporary stops at the location, which hides it from location lists by default",
4042
+ schema: z.boolean()
4043
+ },
4044
+ {
4045
+ name: "name",
4046
+ jsonPath: ["name"],
4047
+ description: "The location's display name",
4048
+ valueName: "value",
4049
+ schema: z.string()
4050
+ },
4051
+ {
4052
+ name: "parent-location-id",
4053
+ jsonPath: ["parentLocationId"],
4054
+ description: "The ID of the site a zone belongs to, required for a zone and refused for a site",
4055
+ valueName: "value",
4056
+ schema: z.string()
4057
+ },
4058
+ {
4059
+ name: "type",
4060
+ jsonPath: ["type"],
4061
+ description: "SITE for a site, or ZONE for a zone within a site",
4062
+ valueName: "value",
4063
+ schema: z.enum([
4064
+ "SITE",
4065
+ "UNKNOWN",
4066
+ "ZONE"
4067
+ ])
4068
+ }
4069
+ ]
2512
4070
  }),
2513
4071
  defineOperation({
2514
4072
  name: "get",
2515
4073
  summary: "Get location",
4074
+ example: "hardfin location get loc_4f9Xk2mQ7pLr8sTz",
2516
4075
  method: "GET",
2517
4076
  path: "/location/{locationKey}",
2518
4077
  pathParameters: [{
@@ -2521,11 +4080,12 @@ const surfaceCommands = [
2521
4080
  required: true
2522
4081
  }],
2523
4082
  queryFlags: [],
2524
- takesBody: false
4083
+ bodyFlags: []
2525
4084
  }),
2526
4085
  defineOperation({
2527
4086
  name: "update",
2528
4087
  summary: "Patch location",
4088
+ example: "hardfin location update loc_4f9Xk2mQ7pLr8sTz",
2529
4089
  method: "PATCH",
2530
4090
  path: "/location/{locationKey}",
2531
4091
  pathParameters: [{
@@ -2534,7 +4094,120 @@ const surfaceCommands = [
2534
4094
  required: true
2535
4095
  }],
2536
4096
  queryFlags: [],
2537
- takesBody: true
4097
+ bodyFlags: [
4098
+ {
4099
+ name: "address-line1",
4100
+ jsonPath: ["address", "addressLine1"],
4101
+ description: "The first line of the street address",
4102
+ valueName: "value",
4103
+ schema: z.string()
4104
+ },
4105
+ {
4106
+ name: "address-line2",
4107
+ jsonPath: ["address", "addressLine2"],
4108
+ description: "The second line of the street address, such as a suite",
4109
+ valueName: "value",
4110
+ schema: z.string()
4111
+ },
4112
+ {
4113
+ name: "address-city",
4114
+ jsonPath: ["address", "city"],
4115
+ description: "The city",
4116
+ valueName: "value",
4117
+ schema: z.string()
4118
+ },
4119
+ {
4120
+ name: "address-country",
4121
+ jsonPath: ["address", "country"],
4122
+ description: "The country",
4123
+ valueName: "value",
4124
+ schema: z.string()
4125
+ },
4126
+ {
4127
+ name: "address-formatted-address",
4128
+ jsonPath: ["address", "formattedAddress"],
4129
+ description: "The whole address on one line",
4130
+ valueName: "value",
4131
+ schema: z.string()
4132
+ },
4133
+ {
4134
+ name: "address-postal-code",
4135
+ jsonPath: ["address", "postalCode"],
4136
+ description: "The postal or ZIP code",
4137
+ valueName: "value",
4138
+ schema: z.string()
4139
+ },
4140
+ {
4141
+ name: "address-state",
4142
+ jsonPath: ["address", "state"],
4143
+ description: "The state or region",
4144
+ valueName: "value",
4145
+ schema: z.string()
4146
+ },
4147
+ {
4148
+ name: "consignee",
4149
+ jsonPath: ["consignee"],
4150
+ description: "The ID of the customer a zone is designated for, such as for reservations, provisioning or a 3PL",
4151
+ valueName: "value",
4152
+ schema: z.string()
4153
+ },
4154
+ {
4155
+ name: "customer-id",
4156
+ jsonPath: ["customerId"],
4157
+ description: "The ID of the customer to assign a site to, or null for your organization's own site",
4158
+ valueName: "value",
4159
+ schema: z.string()
4160
+ },
4161
+ {
4162
+ name: "description",
4163
+ jsonPath: ["description"],
4164
+ description: "A free-form description of a zone",
4165
+ valueName: "value",
4166
+ schema: z.string()
4167
+ },
4168
+ {
4169
+ name: "is-archived",
4170
+ jsonPath: ["isArchived"],
4171
+ description: "Whether the location is archived, and archiving a site archives its zones",
4172
+ schema: z.boolean()
4173
+ },
4174
+ {
4175
+ name: "is-inventory",
4176
+ jsonPath: ["isInventory"],
4177
+ description: "Whether assets at the location count as inventory for reporting",
4178
+ schema: z.boolean()
4179
+ },
4180
+ {
4181
+ name: "is-inventory-override",
4182
+ jsonPath: ["isInventoryOverride"],
4183
+ description: "Whether a zone sets its own isInventory rather than inheriting its parent site's, which a site refuses",
4184
+ schema: z.boolean()
4185
+ },
4186
+ {
4187
+ name: "is-transient",
4188
+ jsonPath: ["isTransient"],
4189
+ description: "Whether assets make only occasional or temporary stops at the location, which hides it from location lists by default",
4190
+ schema: z.boolean()
4191
+ },
4192
+ {
4193
+ name: "name",
4194
+ jsonPath: ["name"],
4195
+ description: "The location's display name",
4196
+ valueName: "value",
4197
+ schema: z.string()
4198
+ },
4199
+ {
4200
+ name: "type",
4201
+ jsonPath: ["type"],
4202
+ description: "SITE for a site, or ZONE for a zone within a site",
4203
+ valueName: "value",
4204
+ schema: z.enum([
4205
+ "SITE",
4206
+ "UNKNOWN",
4207
+ "ZONE"
4208
+ ])
4209
+ }
4210
+ ]
2538
4211
  }),
2539
4212
  {
2540
4213
  name: "zones",
@@ -2545,6 +4218,7 @@ const surfaceCommands = [
2545
4218
  subcommands: [defineOperation({
2546
4219
  name: "list",
2547
4220
  summary: "Get zones",
4221
+ example: "hardfin location zones list loc_4f9Xk2mQ7pLr8sTz",
2548
4222
  method: "GET",
2549
4223
  path: "/location/{locationKey}/zones",
2550
4224
  pathParameters: [{
@@ -2563,7 +4237,7 @@ const surfaceCommands = [
2563
4237
  "true"
2564
4238
  ])
2565
4239
  }],
2566
- takesBody: false
4240
+ bodyFlags: []
2567
4241
  })]
2568
4242
  }
2569
4243
  ]
@@ -2578,6 +4252,7 @@ const surfaceCommands = [
2578
4252
  defineOperation({
2579
4253
  name: "get",
2580
4254
  summary: "Get URL link by key",
4255
+ example: "hardfin url-link get link_7hq2mx9pcr4stz8w",
2581
4256
  method: "GET",
2582
4257
  path: "/url-link/{linkKey}",
2583
4258
  pathParameters: [{
@@ -2586,11 +4261,12 @@ const surfaceCommands = [
2586
4261
  required: true
2587
4262
  }],
2588
4263
  queryFlags: [],
2589
- takesBody: false
4264
+ bodyFlags: []
2590
4265
  }),
2591
4266
  defineOperation({
2592
4267
  name: "update",
2593
4268
  summary: "Update URL link",
4269
+ example: "hardfin url-link update link_7hq2mx9pcr4stz8w",
2594
4270
  method: "PATCH",
2595
4271
  path: "/url-link/{linkKey}",
2596
4272
  pathParameters: [{
@@ -2599,11 +4275,24 @@ const surfaceCommands = [
2599
4275
  required: true
2600
4276
  }],
2601
4277
  queryFlags: [],
2602
- takesBody: true
4278
+ bodyFlags: [{
4279
+ name: "name",
4280
+ jsonPath: ["name"],
4281
+ description: "The link's display name, or null to show the address instead",
4282
+ valueName: "value",
4283
+ schema: z.string()
4284
+ }, {
4285
+ name: "url",
4286
+ jsonPath: ["url"],
4287
+ description: "The address the link points to, which cannot be empty or null",
4288
+ valueName: "value",
4289
+ schema: z.string()
4290
+ }]
2603
4291
  }),
2604
4292
  defineOperation({
2605
4293
  name: "delete",
2606
4294
  summary: "Delete URL link",
4295
+ example: "hardfin url-link delete link_7hq2mx9pcr4stz8w",
2607
4296
  method: "DELETE",
2608
4297
  path: "/url-link/{linkKey}",
2609
4298
  pathParameters: [{
@@ -2612,7 +4301,7 @@ const surfaceCommands = [
2612
4301
  required: true
2613
4302
  }],
2614
4303
  queryFlags: [],
2615
- takesBody: false
4304
+ bodyFlags: []
2616
4305
  })
2617
4306
  ]
2618
4307
  }
@@ -2898,7 +4587,10 @@ const commands = [
2898
4587
  ...surfaceCommands,
2899
4588
  apiCommand,
2900
4589
  configCommand,
2901
- agentGuideCommand
4590
+ agentGuideCommand,
4591
+ completionCommand,
4592
+ mcpCommand,
4593
+ completeCommand
2902
4594
  ];
2903
4595
  //#endregion
2904
4596
  //#region src/command/validate.ts
@@ -2914,7 +4606,7 @@ function toRejectedFlag(command, flags) {
2914
4606
  //#region src/cli.ts
2915
4607
  const program = new Command();
2916
4608
  program.name("hardfin").description("Call the Hardfin API from a terminal or an agent").version(version$1, "-v, --version").option("--api-url <url>", "The API to call, whose host also holds the authorization server").option("--issuer-url <url>", "The authorization server, when it does not sit at the API's host").showHelpAfterError().enablePositionalOptions();
2917
- for (const command of commands) program.addCommand(toProgram(command));
4609
+ for (const command of commands) program.addCommand(toProgram(command), { hidden: command.hidden });
2918
4610
  await program.parseAsync(process.argv);
2919
4611
  /** toProgram wires one registry command into the parser. */
2920
4612
  function toProgram(command) {
@@ -2932,7 +4624,7 @@ function toProgram(command) {
2932
4624
  program.addOption(option);
2933
4625
  }
2934
4626
  for (const example of command.examples) program.addHelpText("after", `\n${example.description}:\n $ ${example.command}`);
2935
- for (const subcommand of command.subcommands ?? []) program.addCommand(toProgram(subcommand));
4627
+ for (const subcommand of command.subcommands ?? []) program.addCommand(toProgram(subcommand), { hidden: subcommand.hidden });
2936
4628
  if (!command.run) return program;
2937
4629
  program.action(async (...parsed) => {
2938
4630
  const flags = parsed[parsed.length - 2] ?? {};