@hardfin/cli 0.0.2-dev.5 → 0.0.2-dev.7

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 +113 -1
  2. package/dist/cli.js +1313 -18
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -7,7 +7,8 @@ It is built for people at a terminal and for agents that call Hardfin on their b
7
7
 
8
8
  ## Status
9
9
 
10
- This package is a placeholder that reserves the name. No commands work yet.
10
+ The CLI is early. `hardfin api` and the generated commands work against an API key, and
11
+ `hardfin login` is not built yet.
11
12
 
12
13
  ## Install
13
14
 
@@ -21,6 +22,117 @@ Previews of unreleased work are published from the `dev` branch.
21
22
  npm install -g @hardfin/cli@dev
22
23
  ```
23
24
 
25
+ ## The command surface
26
+
27
+ Most commands are generated from the published API document rather than written by hand.
28
+
29
+ | Piece | Holds |
30
+ | --- | --- |
31
+ | `hardfin api` | A call to any endpoint, written by hand, and the escape hatch when no generated command fits |
32
+ | `src/command/surface.generated.ts` | Every endpoint as a command, rewritten by the generator |
33
+ | `surface-overrides.json` | The operations whose generated name is wrong |
34
+ | `scripts/generate-surface.mjs` | The generator |
35
+
36
+ ### How an endpoint becomes a command
37
+
38
+ The first path segment is the noun. Every later literal segment nests under it. The method
39
+ and the shape of the last segment decide the verb.
40
+
41
+ | Endpoint | Command |
42
+ | --- | --- |
43
+ | `GET /asset` | `hardfin asset list` |
44
+ | `POST /asset` | `hardfin asset create` |
45
+ | `GET /asset/{assetKey}` | `hardfin asset get <assetKey>` |
46
+ | `PATCH /asset/{assetKey}` | `hardfin asset update <assetKey>` |
47
+ | `PATCH /asset/{assetKey}/accounting` | `hardfin asset accounting update <assetKey>` |
48
+
49
+ A path parameter becomes a positional argument. A query parameter becomes a flag, named in
50
+ kebab case, and an array parameter becomes a flag you repeat. An enum parameter carries its
51
+ values, so a wrong value fails locally with exit code 2 rather than at the API.
52
+
53
+ ### Overrides
54
+
55
+ Two endpoints sometimes want one name. `DELETE /asset/{assetKey}/ownership` and
56
+ `DELETE /asset/{assetKey}/ownership/{segmentKey}` both generate `asset ownership delete`, so
57
+ the generator stops and names the pair.
58
+
59
+ Settle it in `surface-overrides.json`, keyed by `operationId`:
60
+
61
+ ```json
62
+ {
63
+ "assetClearAssetActiveOwnership": {
64
+ "command": ["asset", "ownership", "clear"],
65
+ "summary": "Clear the ownership an asset holds today"
66
+ }
67
+ }
68
+ ```
69
+
70
+ An override for an `operationId` the document no longer publishes fails the generator. That
71
+ is deliberate, because a silently dropped override renames a command nobody meant to rename.
72
+
73
+ ### Regenerating
74
+
75
+ The Surface workflow runs each weekday, reads `reference/core.openapi.yaml` from the
76
+ `hardfinhq/api-spec` repository through a read-only deploy key, and opens a pull request when
77
+ the generated file changes. It needs the `API_SPEC_READ_DEPLOY_KEY` secret.
78
+
79
+ Run it by hand against a local document:
80
+
81
+ ```sh
82
+ npm run generate-surface -- ../api-spec/reference/core.openapi.yaml
83
+ ```
84
+
85
+ The document is bundled, meaning its external files are inlined, but `$ref` pointers within
86
+ it remain. The generator follows those pointers itself.
87
+
88
+ ## Local configuration
89
+
90
+ A local build reaches a local server without editing code. Four layers supply the same
91
+ settings, and the one nearest the top wins.
92
+
93
+ | Layer | Where | Beats |
94
+ | --- | --- | --- |
95
+ | Flag | `--api-url` | everything below |
96
+ | Environment | an exported `HARDFIN_*` variable | the files below |
97
+ | Env file | `.env` in the working directory, or the file `HARDFIN_ENV_FILE` names | the config file |
98
+ | Config file | `config.local.json` in the working directory | the defaults |
99
+ | Default | the published API | nothing |
100
+
101
+ An exported variable beats `.env` because Node leaves a variable that is already set alone.
102
+
103
+ ### What a local build writes
104
+
105
+ ```json
106
+ {
107
+ "apiUrl": "http://localhost:8080/v2",
108
+ "auth": { "tokenUrl": "http://localhost:9000/oauth/token" }
109
+ }
110
+ ```
111
+
112
+ The authentication endpoints follow `apiUrl`, so pointing at a local server moves the whole
113
+ flow. Name one under `auth` to move only that one. The keys are `apiUrl`, `apiKey`,
114
+ `clientId`, and `auth` holding `authorizeUrl`, `tokenUrl`, `deviceUrl`, and `revokeUrl`.
115
+
116
+ A key the file does not define fails the command with exit code 2. A typo that was silently
117
+ ignored would look like a setting that never applied.
118
+
119
+ `config.local.json` and `.env` are both gitignored.
120
+
121
+ ### Seeing what won
122
+
123
+ ```sh
124
+ hardfin config
125
+ ```
126
+
127
+ It prints each setting, its value, and the layer that supplied it. The API key is reported
128
+ as set or not set, never printed.
129
+
130
+ ### Both files are read from the working directory
131
+
132
+ The CLI reads whatever `config.local.json` and `.env` sit in the directory you run it from.
133
+ A directory you do not control can therefore point the CLI at a server you do not expect, so
134
+ run `hardfin config` when a command reaches somewhere surprising.
135
+
24
136
  ## Releasing
25
137
 
26
138
  This section is for anyone who merges a pull request in this repository. It tells you where