@hardfin/cli 0.0.2-dev.11 → 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 +33 -3
  2. package/dist/cli.js +1594 -88
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2,8 +2,8 @@
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
8
  import { spawn, spawnSync } from "node:child_process";
9
9
  import { createServer } from "node:http";
@@ -198,24 +198,34 @@ function toGuide(commands, version) {
198
198
  "## Commands",
199
199
  ""
200
200
  ];
201
- for (const command of commands) {
202
- lines.push(`### \`hardfin ${command.name}\``, "", command.description ?? command.summary, "");
203
- if (command.arguments.length > 0) {
204
- lines.push("| Argument | Required | Holds |", "| --- | --- | --- |");
205
- for (const argument of command.arguments) lines.push(`| \`${argument.name}\` | ${argument.required ? "yes" : "no"} | ${argument.description} |`);
206
- lines.push("");
207
- }
208
- if (command.flags.length > 0) {
209
- lines.push("| Flag | Takes | Does |", "| --- | --- | --- |");
210
- for (const flag of command.flags) {
211
- const name = flag.short ? `-${flag.short}, --${flag.name}` : `--${flag.name}`;
212
- lines.push(`| \`${name}\` | ${flag.valueName ?? "nothing"} | ${flag.description} |`);
213
- }
214
- 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} |`);
215
223
  }
216
- for (const example of command.examples) lines.push(`${example.description}:`, "", "```sh", example.command, "```", "");
224
+ lines.push("");
217
225
  }
218
- 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;
219
229
  }
220
230
  async function runAgentGuide(input) {
221
231
  if (input.flags["json"] === true) {
@@ -604,11 +614,11 @@ async function request(options) {
604
614
  "X-API-Version": API_VERSION,
605
615
  Accept: "application/json"
606
616
  };
607
- 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";
608
618
  const response = await fetch(url, {
609
619
  method: options.method,
610
620
  headers,
611
- 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))
612
622
  });
613
623
  const envelope = toEnvelope(await response.text());
614
624
  if (!response.ok && envelope === void 0) throw new RequestFailure(response.status, [{
@@ -761,6 +771,132 @@ function toBody$1(source) {
761
771
  }
762
772
  }
763
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
764
900
  //#region src/command/config.ts
765
901
  const configCommand = defineCommand({
766
902
  name: "config",
@@ -1496,10 +1632,10 @@ async function runMcp(input) {
1496
1632
  }
1497
1633
  //#endregion
1498
1634
  //#region src/command/operation.ts
1499
- const INPUT_FLAG = {
1500
- name: "input",
1501
- description: "A file holding the JSON request body, or - for stdin",
1502
- valueName: "file",
1635
+ const FILE_FLAG = {
1636
+ name: "file",
1637
+ description: "The file to upload",
1638
+ valueName: "path",
1503
1639
  schema: z.string()
1504
1640
  };
1505
1641
  const JSON_FLAG = {
@@ -1509,15 +1645,22 @@ const JSON_FLAG = {
1509
1645
  };
1510
1646
  /** defineOperation turns one endpoint into the command that calls it. */
1511
1647
  function defineOperation(operation) {
1512
- const flags = [...operation.queryFlags, JSON_FLAG];
1513
- 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
+ ];
1514
1654
  return {
1515
1655
  name: operation.name,
1516
1656
  summary: operation.summary,
1517
1657
  description: operation.description ?? operation.summary,
1518
1658
  arguments: operation.pathParameters,
1519
1659
  flags,
1520
- examples: [],
1660
+ examples: operation.example ? [{
1661
+ description: operation.summary,
1662
+ command: operation.example
1663
+ }] : [],
1521
1664
  run: (input) => runOperation(operation, input)
1522
1665
  };
1523
1666
  }
@@ -1527,13 +1670,24 @@ async function runOperation(operation, input) {
1527
1670
  writeFailure(`this command takes ${operation.pathParameters.length} argument(s)`, input.isJSON);
1528
1671
  return ExitCode.USAGE;
1529
1672
  }
1530
- let body;
1531
- if (typeof input.flags["input"] === "string") {
1532
- body = toBody(input.flags["input"]);
1533
- if (body === void 0) {
1534
- 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);
1535
1688
  return ExitCode.USAGE;
1536
1689
  }
1690
+ form = built;
1537
1691
  }
1538
1692
  try {
1539
1693
  writeData((await request({
@@ -1542,7 +1696,8 @@ async function runOperation(operation, input) {
1542
1696
  method: operation.method,
1543
1697
  path,
1544
1698
  query: toQuery(operation, input.flags),
1545
- body
1699
+ body,
1700
+ form
1546
1701
  })).data);
1547
1702
  return ExitCode.OK;
1548
1703
  } catch (error) {
@@ -1579,13 +1734,65 @@ function toQuery(operation, flags) {
1579
1734
  function toOptionKey(name) {
1580
1735
  return name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
1581
1736
  }
1582
- function toBody(source) {
1583
- 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();
1584
1742
  try {
1585
- return JSON.parse(text);
1743
+ form.append(upload.filePart, await openAsBlob(path), basename(path));
1586
1744
  } catch {
1587
- 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);
1588
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];
1794
+ }
1795
+ holder[path[path.length - 1] ?? ""] = value;
1589
1796
  }
1590
1797
  //#endregion
1591
1798
  //#region src/command/surface.generated.ts
@@ -1600,6 +1807,7 @@ const surfaceCommands = [
1600
1807
  defineOperation({
1601
1808
  name: "list",
1602
1809
  summary: "Get asset listing",
1810
+ example: "hardfin asset list --limit 10",
1603
1811
  method: "GET",
1604
1812
  path: "/asset",
1605
1813
  pathParameters: [],
@@ -1783,16 +1991,170 @@ const surfaceCommands = [
1783
1991
  ])
1784
1992
  }
1785
1993
  ],
1786
- takesBody: false
1994
+ bodyFlags: []
1787
1995
  }),
1788
1996
  defineOperation({
1789
1997
  name: "create",
1790
1998
  summary: "Create asset",
1999
+ example: "hardfin asset create --item-id <value> --serial <value>",
1791
2000
  method: "POST",
1792
2001
  path: "/asset",
1793
2002
  pathParameters: [],
1794
2003
  queryFlags: [],
1795
- 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
+ ]
1796
2158
  }),
1797
2159
  {
1798
2160
  name: "move",
@@ -1809,11 +2171,28 @@ const surfaceCommands = [
1809
2171
  subcommands: [defineOperation({
1810
2172
  name: "create",
1811
2173
  summary: "Execute asset move",
2174
+ example: "hardfin asset move execute create",
1812
2175
  method: "POST",
1813
2176
  path: "/asset/move/execute",
1814
2177
  pathParameters: [],
1815
2178
  queryFlags: [],
1816
- 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
+ }]
1817
2196
  })]
1818
2197
  }, {
1819
2198
  name: "plan",
@@ -1824,17 +2203,32 @@ const surfaceCommands = [
1824
2203
  subcommands: [defineOperation({
1825
2204
  name: "create",
1826
2205
  summary: "Plan asset move",
2206
+ example: "hardfin asset move plan create",
1827
2207
  method: "POST",
1828
2208
  path: "/asset/move/plan",
1829
2209
  pathParameters: [],
1830
2210
  queryFlags: [],
1831
- 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
+ }]
1832
2225
  })]
1833
2226
  }]
1834
2227
  },
1835
2228
  defineOperation({
1836
2229
  name: "get",
1837
2230
  summary: "Get asset",
2231
+ example: "hardfin asset get ast_4f9xk2mq7plr8stz",
1838
2232
  method: "GET",
1839
2233
  path: "/asset/{assetKey}",
1840
2234
  pathParameters: [{
@@ -1843,11 +2237,12 @@ const surfaceCommands = [
1843
2237
  required: true
1844
2238
  }],
1845
2239
  queryFlags: [],
1846
- takesBody: false
2240
+ bodyFlags: []
1847
2241
  }),
1848
2242
  defineOperation({
1849
2243
  name: "update",
1850
2244
  summary: "Patch asset",
2245
+ example: "hardfin asset update ast_4f9xk2mq7plr8stz",
1851
2246
  method: "PATCH",
1852
2247
  path: "/asset/{assetKey}",
1853
2248
  pathParameters: [{
@@ -1856,7 +2251,57 @@ const surfaceCommands = [
1856
2251
  required: true
1857
2252
  }],
1858
2253
  queryFlags: [],
1859
- 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
+ ]
1860
2305
  }),
1861
2306
  {
1862
2307
  name: "accounting",
@@ -1867,6 +2312,7 @@ const surfaceCommands = [
1867
2312
  subcommands: [defineOperation({
1868
2313
  name: "update",
1869
2314
  summary: "Update asset accounting",
2315
+ example: "hardfin asset accounting update ast_4f9xk2mq7plr8stz",
1870
2316
  method: "PATCH",
1871
2317
  path: "/asset/{assetKey}/accounting",
1872
2318
  pathParameters: [{
@@ -1875,7 +2321,117 @@ const surfaceCommands = [
1875
2321
  required: true
1876
2322
  }],
1877
2323
  queryFlags: [],
1878
- 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
+ ]
1879
2435
  }), {
1880
2436
  name: "in-service-management",
1881
2437
  summary: "In service management commands",
@@ -1885,6 +2441,7 @@ const surfaceCommands = [
1885
2441
  subcommands: [defineOperation({
1886
2442
  name: "update",
1887
2443
  summary: "Toggle in service date management",
2444
+ example: "hardfin asset accounting in-service-management update ast_4f9xk2mq7plr8stz --automatic <value>",
1888
2445
  method: "PATCH",
1889
2446
  path: "/asset/{assetKey}/accounting/in-service-management",
1890
2447
  pathParameters: [{
@@ -1893,7 +2450,13 @@ const surfaceCommands = [
1893
2450
  required: true
1894
2451
  }],
1895
2452
  queryFlags: [],
1896
- 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
+ }]
1897
2460
  })]
1898
2461
  }]
1899
2462
  },
@@ -1906,6 +2469,7 @@ const surfaceCommands = [
1906
2469
  subcommands: [defineOperation({
1907
2470
  name: "create",
1908
2471
  summary: "Create asset cost adjustment",
2472
+ example: "hardfin asset cost-adjustment create ast_4f9xk2mq7plr8stz --adjustment-type <value> --amount <value> --effective-date <value>",
1909
2473
  method: "POST",
1910
2474
  path: "/asset/{assetKey}/cost-adjustment",
1911
2475
  pathParameters: [{
@@ -1914,7 +2478,57 @@ const surfaceCommands = [
1914
2478
  required: true
1915
2479
  }],
1916
2480
  queryFlags: [],
1917
- 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
+ ]
1918
2532
  })]
1919
2533
  },
1920
2534
  {
@@ -1926,6 +2540,7 @@ const surfaceCommands = [
1926
2540
  subcommands: [defineOperation({
1927
2541
  name: "list",
1928
2542
  summary: "Get asset event list",
2543
+ example: "hardfin asset event list ast_4f9xk2mq7plr8stz",
1929
2544
  method: "GET",
1930
2545
  path: "/asset/{assetKey}/event",
1931
2546
  pathParameters: [{
@@ -1934,7 +2549,7 @@ const surfaceCommands = [
1934
2549
  required: true
1935
2550
  }],
1936
2551
  queryFlags: [],
1937
- takesBody: false
2552
+ bodyFlags: []
1938
2553
  })]
1939
2554
  },
1940
2555
  {
@@ -1946,6 +2561,7 @@ const surfaceCommands = [
1946
2561
  subcommands: [defineOperation({
1947
2562
  name: "list",
1948
2563
  summary: "Get asset event group listing",
2564
+ example: "hardfin asset event-group list ast_4f9xk2mq7plr8stz",
1949
2565
  method: "GET",
1950
2566
  path: "/asset/{assetKey}/event-group",
1951
2567
  pathParameters: [{
@@ -1966,10 +2582,11 @@ const surfaceCommands = [
1966
2582
  valueName: "value",
1967
2583
  schema: z.string()
1968
2584
  }],
1969
- takesBody: false
2585
+ bodyFlags: []
1970
2586
  }), defineOperation({
1971
2587
  name: "get",
1972
2588
  summary: "Get asset event group",
2589
+ example: "hardfin asset event-group get ast_4f9xk2mq7plr8stz aeg_3mx8kq2plr7stz4w",
1973
2590
  method: "GET",
1974
2591
  path: "/asset/{assetKey}/event-group/{eventGroupKey}",
1975
2592
  pathParameters: [{
@@ -1982,7 +2599,7 @@ const surfaceCommands = [
1982
2599
  required: true
1983
2600
  }],
1984
2601
  queryFlags: [],
1985
- takesBody: false
2602
+ bodyFlags: []
1986
2603
  })]
1987
2604
  },
1988
2605
  {
@@ -1994,6 +2611,7 @@ const surfaceCommands = [
1994
2611
  subcommands: [defineOperation({
1995
2612
  name: "list",
1996
2613
  summary: "Get asset files",
2614
+ example: "hardfin asset file list ast_4f9xk2mq7plr8stz",
1997
2615
  method: "GET",
1998
2616
  path: "/asset/{assetKey}/file",
1999
2617
  pathParameters: [{
@@ -2002,10 +2620,11 @@ const surfaceCommands = [
2002
2620
  required: true
2003
2621
  }],
2004
2622
  queryFlags: [],
2005
- takesBody: false
2623
+ bodyFlags: []
2006
2624
  }), defineOperation({
2007
2625
  name: "delete",
2008
2626
  summary: "Delete asset file",
2627
+ example: "hardfin asset file delete ast_4f9xk2mq7plr8stz file_7hq2mx9pkr4stz8w",
2009
2628
  method: "DELETE",
2010
2629
  path: "/asset/{assetKey}/file/{fileKey}",
2011
2630
  pathParameters: [{
@@ -2018,7 +2637,7 @@ const surfaceCommands = [
2018
2637
  required: true
2019
2638
  }],
2020
2639
  queryFlags: [],
2021
- takesBody: false
2640
+ bodyFlags: []
2022
2641
  })]
2023
2642
  },
2024
2643
  {
@@ -2030,6 +2649,7 @@ const surfaceCommands = [
2030
2649
  subcommands: [defineOperation({
2031
2650
  name: "list",
2032
2651
  summary: "Get asset functional status history",
2652
+ example: "hardfin asset functional-status list ast_4f9xk2mq7plr8stz",
2033
2653
  method: "GET",
2034
2654
  path: "/asset/{assetKey}/functional-status",
2035
2655
  pathParameters: [{
@@ -2038,7 +2658,7 @@ const surfaceCommands = [
2038
2658
  required: true
2039
2659
  }],
2040
2660
  queryFlags: [],
2041
- takesBody: false
2661
+ bodyFlags: []
2042
2662
  })]
2043
2663
  },
2044
2664
  {
@@ -2051,6 +2671,7 @@ const surfaceCommands = [
2051
2671
  defineOperation({
2052
2672
  name: "list",
2053
2673
  summary: "Get asset ownership history",
2674
+ example: "hardfin asset ownership list ast_4f9xk2mq7plr8stz",
2054
2675
  method: "GET",
2055
2676
  path: "/asset/{assetKey}/ownership",
2056
2677
  pathParameters: [{
@@ -2059,11 +2680,12 @@ const surfaceCommands = [
2059
2680
  required: true
2060
2681
  }],
2061
2682
  queryFlags: [],
2062
- takesBody: false
2683
+ bodyFlags: []
2063
2684
  }),
2064
2685
  defineOperation({
2065
2686
  name: "create",
2066
2687
  summary: "Create asset ownership",
2688
+ example: "hardfin asset ownership create ast_4f9xk2mq7plr8stz --customer-id <value> --date <value>",
2067
2689
  method: "POST",
2068
2690
  path: "/asset/{assetKey}/ownership",
2069
2691
  pathParameters: [{
@@ -2072,11 +2694,36 @@ const surfaceCommands = [
2072
2694
  required: true
2073
2695
  }],
2074
2696
  queryFlags: [],
2075
- 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
+ ]
2076
2722
  }),
2077
2723
  defineOperation({
2078
2724
  name: "clear",
2079
2725
  summary: "Clear the ownership an asset holds today",
2726
+ example: "hardfin asset ownership clear ast_4f9xk2mq7plr8stz --date <value>",
2080
2727
  method: "DELETE",
2081
2728
  path: "/asset/{assetKey}/ownership",
2082
2729
  pathParameters: [{
@@ -2085,11 +2732,19 @@ const surfaceCommands = [
2085
2732
  required: true
2086
2733
  }],
2087
2734
  queryFlags: [],
2088
- 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
+ }]
2089
2743
  }),
2090
2744
  defineOperation({
2091
2745
  name: "get",
2092
2746
  summary: "Get asset ownership segment",
2747
+ example: "hardfin asset ownership get ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
2093
2748
  method: "GET",
2094
2749
  path: "/asset/{assetKey}/ownership/{segmentKey}",
2095
2750
  pathParameters: [{
@@ -2102,11 +2757,12 @@ const surfaceCommands = [
2102
2757
  required: true
2103
2758
  }],
2104
2759
  queryFlags: [],
2105
- takesBody: false
2760
+ bodyFlags: []
2106
2761
  }),
2107
2762
  defineOperation({
2108
2763
  name: "update",
2109
2764
  summary: "Patch asset ownership segment",
2765
+ example: "hardfin asset ownership update ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
2110
2766
  method: "PATCH",
2111
2767
  path: "/asset/{assetKey}/ownership/{segmentKey}",
2112
2768
  pathParameters: [{
@@ -2119,11 +2775,34 @@ const surfaceCommands = [
2119
2775
  required: true
2120
2776
  }],
2121
2777
  queryFlags: [],
2122
- 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
+ ]
2123
2801
  }),
2124
2802
  defineOperation({
2125
2803
  name: "delete",
2126
2804
  summary: "Delete asset ownership segment",
2805
+ example: "hardfin asset ownership delete ast_4f9xk2mq7plr8stz aown_8kq2mx7plr4stz9w",
2127
2806
  method: "DELETE",
2128
2807
  path: "/asset/{assetKey}/ownership/{segmentKey}",
2129
2808
  pathParameters: [{
@@ -2136,7 +2815,7 @@ const surfaceCommands = [
2136
2815
  required: true
2137
2816
  }],
2138
2817
  queryFlags: [],
2139
- takesBody: false
2818
+ bodyFlags: []
2140
2819
  })
2141
2820
  ]
2142
2821
  },
@@ -2149,6 +2828,7 @@ const surfaceCommands = [
2149
2828
  subcommands: [defineOperation({
2150
2829
  name: "create",
2151
2830
  summary: "Scrap asset",
2831
+ example: "hardfin asset scrap create ast_4f9xk2mq7plr8stz --disposal-date <value>",
2152
2832
  method: "POST",
2153
2833
  path: "/asset/{assetKey}/scrap",
2154
2834
  pathParameters: [{
@@ -2157,7 +2837,30 @@ const surfaceCommands = [
2157
2837
  required: true
2158
2838
  }],
2159
2839
  queryFlags: [],
2160
- 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
+ ]
2161
2864
  })]
2162
2865
  },
2163
2866
  {
@@ -2169,6 +2872,7 @@ const surfaceCommands = [
2169
2872
  subcommands: [defineOperation({
2170
2873
  name: "create",
2171
2874
  summary: "Unscrap asset",
2875
+ example: "hardfin asset unscrap create ast_4f9xk2mq7plr8stz",
2172
2876
  method: "POST",
2173
2877
  path: "/asset/{assetKey}/unscrap",
2174
2878
  pathParameters: [{
@@ -2177,7 +2881,7 @@ const surfaceCommands = [
2177
2881
  required: true
2178
2882
  }],
2179
2883
  queryFlags: [],
2180
- takesBody: false
2884
+ bodyFlags: []
2181
2885
  })]
2182
2886
  },
2183
2887
  {
@@ -2189,6 +2893,7 @@ const surfaceCommands = [
2189
2893
  subcommands: [defineOperation({
2190
2894
  name: "list",
2191
2895
  summary: "Get asset URL links",
2896
+ example: "hardfin asset url-link list ast_4f9xk2mq7plr8stz",
2192
2897
  method: "GET",
2193
2898
  path: "/asset/{assetKey}/url-link",
2194
2899
  pathParameters: [{
@@ -2197,10 +2902,11 @@ const surfaceCommands = [
2197
2902
  required: true
2198
2903
  }],
2199
2904
  queryFlags: [],
2200
- takesBody: false
2905
+ bodyFlags: []
2201
2906
  }), defineOperation({
2202
2907
  name: "create",
2203
2908
  summary: "Create asset URL link",
2909
+ example: "hardfin asset url-link create ast_4f9xk2mq7plr8stz --url <value>",
2204
2910
  method: "POST",
2205
2911
  path: "/asset/{assetKey}/url-link",
2206
2912
  pathParameters: [{
@@ -2209,7 +2915,20 @@ const surfaceCommands = [
2209
2915
  required: true
2210
2916
  }],
2211
2917
  queryFlags: [],
2212
- 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
+ }]
2213
2932
  })]
2214
2933
  },
2215
2934
  {
@@ -2221,6 +2940,7 @@ const surfaceCommands = [
2221
2940
  subcommands: [defineOperation({
2222
2941
  name: "create",
2223
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>",
2224
2944
  method: "POST",
2225
2945
  path: "/asset/{assetKey}/useful-life-revision",
2226
2946
  pathParameters: [{
@@ -2229,7 +2949,47 @@ const surfaceCommands = [
2229
2949
  required: true
2230
2950
  }],
2231
2951
  queryFlags: [],
2232
- 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
+ ]
2233
2993
  })]
2234
2994
  }
2235
2995
  ]
@@ -2244,6 +3004,7 @@ const surfaceCommands = [
2244
3004
  defineOperation({
2245
3005
  name: "list",
2246
3006
  summary: "Get customers",
3007
+ example: "hardfin customer list --limit 10",
2247
3008
  method: "GET",
2248
3009
  path: "/customer",
2249
3010
  pathParameters: [],
@@ -2315,20 +3076,92 @@ const surfaceCommands = [
2315
3076
  schema: z.string()
2316
3077
  }
2317
3078
  ],
2318
- takesBody: false
3079
+ bodyFlags: []
2319
3080
  }),
2320
3081
  defineOperation({
2321
3082
  name: "create",
2322
3083
  summary: "Create customer",
3084
+ example: "hardfin customer create --name <value>",
2323
3085
  method: "POST",
2324
3086
  path: "/customer",
2325
3087
  pathParameters: [],
2326
3088
  queryFlags: [],
2327
- takesBody: true
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
+ ]
2328
3160
  }),
2329
3161
  defineOperation({
2330
3162
  name: "get",
2331
3163
  summary: "Get customer",
3164
+ example: "hardfin customer get cust_V1StGXR8Z5jdHi6B",
2332
3165
  method: "GET",
2333
3166
  path: "/customer/{customerKey}",
2334
3167
  pathParameters: [{
@@ -2337,11 +3170,12 @@ const surfaceCommands = [
2337
3170
  required: true
2338
3171
  }],
2339
3172
  queryFlags: [],
2340
- takesBody: false
3173
+ bodyFlags: []
2341
3174
  }),
2342
3175
  defineOperation({
2343
3176
  name: "update",
2344
3177
  summary: "Patch customer",
3178
+ example: "hardfin customer update cust_V1StGXR8Z5jdHi6B",
2345
3179
  method: "PATCH",
2346
3180
  path: "/customer/{customerKey}",
2347
3181
  pathParameters: [{
@@ -2350,7 +3184,82 @@ const surfaceCommands = [
2350
3184
  required: true
2351
3185
  }],
2352
3186
  queryFlags: [],
2353
- 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
+ ]
2354
3263
  })
2355
3264
  ]
2356
3265
  },
@@ -2363,14 +3272,44 @@ const surfaceCommands = [
2363
3272
  subcommands: [defineOperation({
2364
3273
  name: "create",
2365
3274
  summary: "Upload file",
3275
+ example: "hardfin file create --file-type <value> --for-entity <value> --file photo.jpg",
2366
3276
  method: "POST",
2367
3277
  path: "/file",
2368
3278
  pathParameters: [],
2369
3279
  queryFlags: [],
2370
- 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
+ }
2371
3309
  }), defineOperation({
2372
3310
  name: "get",
2373
3311
  summary: "Get file",
3312
+ example: "hardfin file get file_7hq2mx9pkr4stz8w",
2374
3313
  method: "GET",
2375
3314
  path: "/file/{fileKey}",
2376
3315
  pathParameters: [{
@@ -2384,7 +3323,7 @@ const surfaceCommands = [
2384
3323
  description: "True when the file downloads as an attachment rather than opening inline",
2385
3324
  schema: z.boolean()
2386
3325
  }],
2387
- takesBody: false
3326
+ bodyFlags: []
2388
3327
  })]
2389
3328
  },
2390
3329
  {
@@ -2397,6 +3336,7 @@ const surfaceCommands = [
2397
3336
  defineOperation({
2398
3337
  name: "list",
2399
3338
  summary: "Get items",
3339
+ example: "hardfin item list --limit 10",
2400
3340
  method: "GET",
2401
3341
  path: "/item",
2402
3342
  pathParameters: [],
@@ -2471,20 +3411,129 @@ const surfaceCommands = [
2471
3411
  schema: z.string()
2472
3412
  }
2473
3413
  ],
2474
- takesBody: false
3414
+ bodyFlags: []
2475
3415
  }),
2476
3416
  defineOperation({
2477
3417
  name: "create",
2478
3418
  summary: "Create item",
3419
+ example: "hardfin item create --name <value> --sku <value> --type <value>",
2479
3420
  method: "POST",
2480
3421
  path: "/item",
2481
3422
  pathParameters: [],
2482
3423
  queryFlags: [],
2483
- 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
+ ]
2484
3532
  }),
2485
3533
  defineOperation({
2486
3534
  name: "get",
2487
3535
  summary: "Get item",
3536
+ example: "hardfin item get item_7Hq2Lm9XcR4tWz8K",
2488
3537
  method: "GET",
2489
3538
  path: "/item/{itemKey}",
2490
3539
  pathParameters: [{
@@ -2493,11 +3542,12 @@ const surfaceCommands = [
2493
3542
  required: true
2494
3543
  }],
2495
3544
  queryFlags: [],
2496
- takesBody: false
3545
+ bodyFlags: []
2497
3546
  }),
2498
3547
  defineOperation({
2499
3548
  name: "update",
2500
3549
  summary: "Update item",
3550
+ example: "hardfin item update item_7Hq2Lm9XcR4tWz8K",
2501
3551
  method: "PATCH",
2502
3552
  path: "/item/{itemKey}",
2503
3553
  pathParameters: [{
@@ -2506,7 +3556,65 @@ const surfaceCommands = [
2506
3556
  required: true
2507
3557
  }],
2508
3558
  queryFlags: [],
2509
- 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
+ ]
2510
3618
  }),
2511
3619
  {
2512
3620
  name: "accounting",
@@ -2517,6 +3625,7 @@ const surfaceCommands = [
2517
3625
  subcommands: [defineOperation({
2518
3626
  name: "update",
2519
3627
  summary: "Update item accounting",
3628
+ example: "hardfin item accounting update item_7Hq2Lm9XcR4tWz8K",
2520
3629
  method: "PATCH",
2521
3630
  path: "/item/{itemKey}/accounting",
2522
3631
  pathParameters: [{
@@ -2525,7 +3634,104 @@ const surfaceCommands = [
2525
3634
  required: true
2526
3635
  }],
2527
3636
  queryFlags: [],
2528
- 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
+ ]
2529
3735
  })]
2530
3736
  },
2531
3737
  {
@@ -2538,6 +3744,7 @@ const surfaceCommands = [
2538
3744
  defineOperation({
2539
3745
  name: "create",
2540
3746
  summary: "Create item field",
3747
+ example: "hardfin item field create item_7Hq2Lm9XcR4tWz8K --field-type <value> --label <value> --order <number>",
2541
3748
  method: "POST",
2542
3749
  path: "/item/{itemKey}/field",
2543
3750
  pathParameters: [{
@@ -2546,11 +3753,54 @@ const surfaceCommands = [
2546
3753
  required: true
2547
3754
  }],
2548
3755
  queryFlags: [],
2549
- 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
+ ]
2550
3799
  }),
2551
3800
  defineOperation({
2552
3801
  name: "update",
2553
3802
  summary: "Update item field",
3803
+ example: "hardfin item field update item_7Hq2Lm9XcR4tWz8K pfield_2wn8kq4lxp7rtz3m",
2554
3804
  method: "PATCH",
2555
3805
  path: "/item/{itemKey}/field/{fieldKey}",
2556
3806
  pathParameters: [{
@@ -2563,11 +3813,18 @@ const surfaceCommands = [
2563
3813
  required: true
2564
3814
  }],
2565
3815
  queryFlags: [],
2566
- 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
+ }]
2567
3823
  }),
2568
3824
  defineOperation({
2569
3825
  name: "delete",
2570
3826
  summary: "Delete item field",
3827
+ example: "hardfin item field delete item_7Hq2Lm9XcR4tWz8K pfield_2wn8kq4lxp7rtz3m",
2571
3828
  method: "DELETE",
2572
3829
  path: "/item/{itemKey}/field/{fieldKey}",
2573
3830
  pathParameters: [{
@@ -2580,7 +3837,7 @@ const surfaceCommands = [
2580
3837
  required: true
2581
3838
  }],
2582
3839
  queryFlags: [],
2583
- takesBody: false
3840
+ bodyFlags: []
2584
3841
  })
2585
3842
  ]
2586
3843
  }
@@ -2596,6 +3853,7 @@ const surfaceCommands = [
2596
3853
  defineOperation({
2597
3854
  name: "list",
2598
3855
  summary: "Get location listing",
3856
+ example: "hardfin location list --limit 10",
2599
3857
  method: "GET",
2600
3858
  path: "/location",
2601
3859
  pathParameters: [],
@@ -2684,20 +3942,136 @@ const surfaceCommands = [
2684
3942
  schema: z.array(z.string())
2685
3943
  }
2686
3944
  ],
2687
- takesBody: false
3945
+ bodyFlags: []
2688
3946
  }),
2689
3947
  defineOperation({
2690
3948
  name: "create",
2691
3949
  summary: "Create location",
3950
+ example: "hardfin location create",
2692
3951
  method: "POST",
2693
3952
  path: "/location",
2694
3953
  pathParameters: [],
2695
3954
  queryFlags: [],
2696
- 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
+ ]
2697
4070
  }),
2698
4071
  defineOperation({
2699
4072
  name: "get",
2700
4073
  summary: "Get location",
4074
+ example: "hardfin location get loc_4f9Xk2mQ7pLr8sTz",
2701
4075
  method: "GET",
2702
4076
  path: "/location/{locationKey}",
2703
4077
  pathParameters: [{
@@ -2706,11 +4080,12 @@ const surfaceCommands = [
2706
4080
  required: true
2707
4081
  }],
2708
4082
  queryFlags: [],
2709
- takesBody: false
4083
+ bodyFlags: []
2710
4084
  }),
2711
4085
  defineOperation({
2712
4086
  name: "update",
2713
4087
  summary: "Patch location",
4088
+ example: "hardfin location update loc_4f9Xk2mQ7pLr8sTz",
2714
4089
  method: "PATCH",
2715
4090
  path: "/location/{locationKey}",
2716
4091
  pathParameters: [{
@@ -2719,7 +4094,120 @@ const surfaceCommands = [
2719
4094
  required: true
2720
4095
  }],
2721
4096
  queryFlags: [],
2722
- 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
+ ]
2723
4211
  }),
2724
4212
  {
2725
4213
  name: "zones",
@@ -2730,6 +4218,7 @@ const surfaceCommands = [
2730
4218
  subcommands: [defineOperation({
2731
4219
  name: "list",
2732
4220
  summary: "Get zones",
4221
+ example: "hardfin location zones list loc_4f9Xk2mQ7pLr8sTz",
2733
4222
  method: "GET",
2734
4223
  path: "/location/{locationKey}/zones",
2735
4224
  pathParameters: [{
@@ -2748,7 +4237,7 @@ const surfaceCommands = [
2748
4237
  "true"
2749
4238
  ])
2750
4239
  }],
2751
- takesBody: false
4240
+ bodyFlags: []
2752
4241
  })]
2753
4242
  }
2754
4243
  ]
@@ -2763,6 +4252,7 @@ const surfaceCommands = [
2763
4252
  defineOperation({
2764
4253
  name: "get",
2765
4254
  summary: "Get URL link by key",
4255
+ example: "hardfin url-link get link_7hq2mx9pcr4stz8w",
2766
4256
  method: "GET",
2767
4257
  path: "/url-link/{linkKey}",
2768
4258
  pathParameters: [{
@@ -2771,11 +4261,12 @@ const surfaceCommands = [
2771
4261
  required: true
2772
4262
  }],
2773
4263
  queryFlags: [],
2774
- takesBody: false
4264
+ bodyFlags: []
2775
4265
  }),
2776
4266
  defineOperation({
2777
4267
  name: "update",
2778
4268
  summary: "Update URL link",
4269
+ example: "hardfin url-link update link_7hq2mx9pcr4stz8w",
2779
4270
  method: "PATCH",
2780
4271
  path: "/url-link/{linkKey}",
2781
4272
  pathParameters: [{
@@ -2784,11 +4275,24 @@ const surfaceCommands = [
2784
4275
  required: true
2785
4276
  }],
2786
4277
  queryFlags: [],
2787
- 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
+ }]
2788
4291
  }),
2789
4292
  defineOperation({
2790
4293
  name: "delete",
2791
4294
  summary: "Delete URL link",
4295
+ example: "hardfin url-link delete link_7hq2mx9pcr4stz8w",
2792
4296
  method: "DELETE",
2793
4297
  path: "/url-link/{linkKey}",
2794
4298
  pathParameters: [{
@@ -2797,7 +4301,7 @@ const surfaceCommands = [
2797
4301
  required: true
2798
4302
  }],
2799
4303
  queryFlags: [],
2800
- takesBody: false
4304
+ bodyFlags: []
2801
4305
  })
2802
4306
  ]
2803
4307
  }
@@ -3084,7 +4588,9 @@ const commands = [
3084
4588
  apiCommand,
3085
4589
  configCommand,
3086
4590
  agentGuideCommand,
3087
- mcpCommand
4591
+ completionCommand,
4592
+ mcpCommand,
4593
+ completeCommand
3088
4594
  ];
3089
4595
  //#endregion
3090
4596
  //#region src/command/validate.ts
@@ -3100,7 +4606,7 @@ function toRejectedFlag(command, flags) {
3100
4606
  //#region src/cli.ts
3101
4607
  const program = new Command();
3102
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();
3103
- for (const command of commands) program.addCommand(toProgram(command));
4609
+ for (const command of commands) program.addCommand(toProgram(command), { hidden: command.hidden });
3104
4610
  await program.parseAsync(process.argv);
3105
4611
  /** toProgram wires one registry command into the parser. */
3106
4612
  function toProgram(command) {
@@ -3118,7 +4624,7 @@ function toProgram(command) {
3118
4624
  program.addOption(option);
3119
4625
  }
3120
4626
  for (const example of command.examples) program.addHelpText("after", `\n${example.description}:\n $ ${example.command}`);
3121
- for (const subcommand of command.subcommands ?? []) program.addCommand(toProgram(subcommand));
4627
+ for (const subcommand of command.subcommands ?? []) program.addCommand(toProgram(subcommand), { hidden: subcommand.hidden });
3122
4628
  if (!command.run) return program;
3123
4629
  program.action(async (...parsed) => {
3124
4630
  const flags = parsed[parsed.length - 2] ?? {};